合同
This commit is contained in:
parent
c44b46605d
commit
6f924ed29a
@ -73,4 +73,10 @@ export function getListByDeptId(data) {
|
||||
return api.get('/bpm/oa/contract/getListByDeptId', data, {
|
||||
login: false
|
||||
})
|
||||
}
|
||||
}
|
||||
// 获取部门类型为公司的部门信息
|
||||
export function getCompanyDept(data) {
|
||||
return api.get('/system/dept/getCompanyDept', data, {
|
||||
login: false
|
||||
})
|
||||
}
|
||||
|
91
api/user.js
91
api/user.js
@ -1,32 +1,107 @@
|
||||
import api from './api'
|
||||
import {
|
||||
VUE_APP_API_URL
|
||||
} from '@/config'
|
||||
import cookie from '@/utils/cookie'
|
||||
|
||||
|
||||
export function userGetUserInfo(data) {
|
||||
return api.get('/system/user/profile/get', data, { login: true })
|
||||
return api.get('/system/user/profile/get', data, {
|
||||
login: true
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function getSimpleUserList(data) {
|
||||
return api.get('/system/user/page', data, { login: true })
|
||||
return api.get('/system/user/page', data, {
|
||||
login: true
|
||||
})
|
||||
}
|
||||
|
||||
export function getSimpleUserList2(data) {
|
||||
return api.get('/system/user/simple-list', data, { login: true })
|
||||
return api.get('/system/user/simple-list', data, {
|
||||
login: true
|
||||
})
|
||||
}
|
||||
|
||||
export function getFlowUsers(data) {
|
||||
return api.get('/crm/flow/flow-users', data, { login: true })
|
||||
return api.get('/crm/flow/flow-users', data, {
|
||||
login: true
|
||||
})
|
||||
}
|
||||
|
||||
export function updateUser(data) {
|
||||
return api.put('/system/user/profile/update', data, { login: true })
|
||||
return api.put('/system/user/profile/update', data, {
|
||||
login: true
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function updateUserProfilePassword(data) {
|
||||
return api.put('/system/user/profile/update-password', data, { login: true })
|
||||
return api.put('/system/user/profile/update-password', data, {
|
||||
login: true
|
||||
})
|
||||
}
|
||||
|
||||
export function getAllUserList(data) {
|
||||
return api.get('/system/user/list-all', data, {
|
||||
login: true
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteBpmFile(data) {
|
||||
return api.delete(`/infra/file/deleteBpmFile?url=${data.url}`, data, {
|
||||
login: true
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//上传文件 流程的
|
||||
export function uploadFile(filePath, cancelLoading) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!cancelLoading) {
|
||||
uni.showLoading({
|
||||
title: '上传中'
|
||||
})
|
||||
}
|
||||
let url = VUE_APP_API_URL + '/infra/file/bpmUpload'
|
||||
uni.showLoading({
|
||||
title: '正在上传'
|
||||
})
|
||||
uni.uploadFile({
|
||||
url,
|
||||
name: 'uploadFiles',
|
||||
filePath: filePath,
|
||||
header: {
|
||||
'Authorization': 'Bearer ' + cookie.get('accessToken'),
|
||||
'tenant-id': '1'
|
||||
},
|
||||
success: res => {
|
||||
console.log(res)
|
||||
uni.hideLoading()
|
||||
if (JSON.parse(res.data).code == 200 || JSON.parse(res.data).code == 0) {
|
||||
resolve(JSON.parse(res.data).data)
|
||||
} else if (JSON.parse(res.data).code == 401) {
|
||||
uni.showToast({
|
||||
title: '登录过期,请重新登录',
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.reLaunch({
|
||||
url: '/pages/components/pages/login/login'
|
||||
})
|
||||
}, 1000)
|
||||
reject(res)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: JSON.parse(res.data).msg
|
||||
});
|
||||
reject(res)
|
||||
}
|
||||
},
|
||||
fail: err => {
|
||||
uni.hideLoading()
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
81
components/xtx-treeNode/README.md
Normal file
81
components/xtx-treeNode/README.md
Normal file
@ -0,0 +1,81 @@
|
||||
## 适用于组织架构的基础展示
|
||||
|
||||
使用
|
||||
```
|
||||
<xtx-treeNode :list="list" @change="treeChange"></xtx-treeNode>
|
||||
```
|
||||
list数据结构
|
||||
```
|
||||
list: [{
|
||||
id: '1',
|
||||
name: '机构一',
|
||||
children: [
|
||||
{
|
||||
id: '101',
|
||||
name: '人事部',
|
||||
children: []
|
||||
},{
|
||||
id: '102',
|
||||
name: '总部',
|
||||
children: [
|
||||
{
|
||||
id: '1021',
|
||||
name: '选项一',
|
||||
children: []
|
||||
},{
|
||||
id: '1022',
|
||||
name: '选项二',
|
||||
children: []
|
||||
},{
|
||||
id: '1023',
|
||||
name: '选项三',
|
||||
children: []
|
||||
}
|
||||
]
|
||||
},{
|
||||
id: '103',
|
||||
name: '后勤部',
|
||||
children: []
|
||||
}
|
||||
]
|
||||
},{
|
||||
id: '12',
|
||||
name: '机构二',
|
||||
children: [
|
||||
{
|
||||
id: '10121',
|
||||
name: '选项一',
|
||||
children: []
|
||||
},{
|
||||
id: '10122',
|
||||
name: '选项二',
|
||||
children: []
|
||||
},{
|
||||
id: '10123',
|
||||
name: '选项三',
|
||||
children: []
|
||||
}
|
||||
]
|
||||
},{
|
||||
id: '13',
|
||||
name: '机构三',
|
||||
children: [{
|
||||
id: '10131',
|
||||
name: '选项一',
|
||||
children: []
|
||||
},{
|
||||
id: '10132',
|
||||
name: '选项二',
|
||||
children: []
|
||||
},{
|
||||
id: '10133',
|
||||
name: '选项三',
|
||||
children: []
|
||||
}]
|
||||
}]
|
||||
```
|
||||
## 事件说明
|
||||
|
||||
| 事件名 | 说明 | 回调 |
|
||||
| ------- | ------- | ------- |
|
||||
| change | 点击node节点触发 | ({ id: '10131', name: '选项一', children: []})=>{} |
|
70
components/xtx-treeNode/xtx-treeNode.vue
Normal file
70
components/xtx-treeNode/xtx-treeNode.vue
Normal file
@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<view>
|
||||
<view
|
||||
class="item--list"
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
>
|
||||
<view class="item--title" hover-class="tree__hover-class" @click="selectNode(item)">
|
||||
<view>{{ item.name }}</view>
|
||||
<view
|
||||
v-if="item.children && item.children.length"
|
||||
class="open__and--close"
|
||||
@click.stop="handleOpenClose(item, index)"
|
||||
>
|
||||
{{ item.isOpen?'收起':'展开'}}</view>
|
||||
</view>
|
||||
<view v-if="item.isOpen && item.children && item.children.length" class="">
|
||||
<treeItem :list="item.children" @change="selectNode"></treeItem>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import treeItem from '../xtx-treeNode/xtx-treeNode'
|
||||
export default {
|
||||
name: 'treeItem',
|
||||
components: {
|
||||
treeItem
|
||||
},
|
||||
props: {
|
||||
list: {
|
||||
item: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectNode(item) {
|
||||
this.$emit('change', item)
|
||||
},
|
||||
handleOpenClose(item, index) {
|
||||
if (!item.hasOwnProperty('isOpen')) {
|
||||
item.isOpen = false
|
||||
}
|
||||
item.isOpen = !item.isOpen
|
||||
this.$forceUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.item--list {
|
||||
padding-left: 25rpx;
|
||||
}
|
||||
.item--title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 28rpx;
|
||||
border-bottom: 1rpx solid #f7f7f7;
|
||||
padding: 25rpx;
|
||||
}
|
||||
.open__and--close {
|
||||
margin-left: auto;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.tree__hover-class {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
</style>
|
14
pages.json
14
pages.json
@ -362,12 +362,14 @@
|
||||
"text": "客户",
|
||||
"iconPath": "static/images/tabBar/customer.png",
|
||||
"selectedIconPath": "static/images/tabBar/customer-selected.png"
|
||||
}, {
|
||||
"pagePath": "pages/msg/index",
|
||||
"text": "消息",
|
||||
"iconPath": "static/images/tabBar/msg.png",
|
||||
"selectedIconPath": "static/images/tabBar/msg-select.png"
|
||||
}, {
|
||||
},
|
||||
//{
|
||||
// "pagePath": "pages/msg/index",
|
||||
// "text": "消息",
|
||||
// "iconPath": "static/images/tabBar/msg.png",
|
||||
// "selectedIconPath": "static/images/tabBar/msg-select.png"
|
||||
// },
|
||||
{
|
||||
"pagePath": "pages/mine/mine",
|
||||
"text": "我的",
|
||||
"iconPath": "static/images/tabBar/mine.png",
|
||||
|
@ -9,16 +9,16 @@
|
||||
<uv-input v-model="form.contractNo" :disabled="isCheck" />
|
||||
</uv-form-item> -->
|
||||
<uv-form-item required label="合同名称:" prop="contractName">
|
||||
<uv-input v-model="form.contractName" :disabled="isCheck" />
|
||||
<uv-input v-model="form.contractName" :disabled="isCheck" placeholder="请输入合同名称" />
|
||||
</uv-form-item>
|
||||
<uv-form-item label="选择客户:" @click="type != 'check' ? selectShow() : ''" prop="customerName" required>
|
||||
<uv-input disabledColor="#ffffff" disabled v-model="form.customerName" placeholder="选择客户">
|
||||
<uv-form-item label="选择客户:" @click="type !== 'detail' ? selectShow() : ''" prop="customerName" required>
|
||||
<uv-input disabledColor="#ffffff" disabled="true" v-model="form.customerName" placeholder="选择客户">
|
||||
<template v-slot:suffix>
|
||||
<uv-icon name="arrow-right"></uv-icon>
|
||||
</template>
|
||||
</uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="选择商机:" @click="type != 'check' ? selectShow4() : ''">
|
||||
<uv-form-item label="选择商机:" @click="type !== 'detail' ? selectShow4() : ''">
|
||||
<uv-input disabledColor="#ffffff" disabled v-model="form.businessName" placeholder="选择商机">
|
||||
<template v-slot:suffix>
|
||||
<uv-icon name="arrow-right"></uv-icon>
|
||||
@ -26,38 +26,45 @@
|
||||
</uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="合同金额:" prop="contractMoney" required>
|
||||
<uv-input type="number" v-model="form.contractMoney" :disabled="isCheck" />
|
||||
<uv-input type="number" v-model="form.contractMoney" :disabled="isCheck" placeholder="请输入合同金额" />
|
||||
</uv-form-item>
|
||||
<uv-form-item label="下单时间 :" @click="type != 'check' ? createTimeShow() : ''">
|
||||
<uv-input v-model="orderTime" placeholder="选择下单时间 " disabled disabledColor="#ffffff">
|
||||
<uv-form-item label="签约时间 :" @click="type !== 'detail' ? createTimeShow() : ''">
|
||||
<uv-input v-model="form.signingDate" placeholder="选择签约时间 " disabled disabledColor="#ffffff">
|
||||
<template v-slot:suffix>
|
||||
<uv-icon name="arrow-right"></uv-icon>
|
||||
</template>
|
||||
</uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="开始时间 :" @click="type != 'check' ? createTimeShow2() : ''">
|
||||
<uv-input v-model="startTime" placeholder="选择开始时间 " disabled disabledColor="#ffffff">
|
||||
<uv-form-item label="开始时间 :" @click="type !== 'detail' ? createTimeShow2() : ''">
|
||||
<uv-input v-model="form.startDate" placeholder="选择开始时间 " disabled disabledColor="#ffffff">
|
||||
<template v-slot:suffix>
|
||||
<uv-icon name="arrow-right"></uv-icon>
|
||||
</template>
|
||||
</uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="结束时间 :" @click="type != 'check' ? createTimeShow3() : ''">
|
||||
<uv-input v-model="endTime" placeholder="选择结束时间 " disabled disabledColor="#ffffff">
|
||||
<uv-form-item label="结束时间 :" @click="type !== 'detail' ? createTimeShow3() : ''">
|
||||
<uv-input v-model="form.endDate" placeholder="选择结束时间 " disabled disabledColor="#ffffff">
|
||||
<template v-slot:suffix>
|
||||
<uv-icon name="arrow-right"></uv-icon>
|
||||
</template>
|
||||
</uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="客户签约人:" @click="type != 'check' ? selectShow2() : ''" required>
|
||||
<uv-form-item label="客户签约人:" @click="type !== 'detail' ? selectShow2() : ''" required>
|
||||
<uv-input disabledColor="#ffffff" disabled v-model="form.contactsName" placeholder="选择签约人">
|
||||
<template v-slot:suffix>
|
||||
<uv-icon name="arrow-right"></uv-icon>
|
||||
</template>
|
||||
</uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="公司签约人:" @click="type != 'check' ? selectShow3() : ''" required>
|
||||
<uv-input disabledColor="#ffffff" disabled v-model="form.orderAdminName" placeholder="选择签约人">
|
||||
<uv-form-item label="签约公司:" @click="type !== 'detail' ? selectShow6() : ''" required>
|
||||
<uv-input disabledColor="#ffffff" disabled v-model="form.companyName" placeholder="选择签约公司">
|
||||
<template v-slot:suffix>
|
||||
<uv-icon name="arrow-right"></uv-icon>
|
||||
</template>
|
||||
</uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="公司签约人:" @click="type !== 'detail' ? selectShow3() : ''" required>
|
||||
<uv-input disabledColor="#ffffff" disabled v-model="form.signatoryName" placeholder="选择签约人">
|
||||
<template v-slot:suffix>
|
||||
<uv-icon name="arrow-right"></uv-icon>
|
||||
</template>
|
||||
@ -71,7 +78,7 @@
|
||||
</uv-form-item>
|
||||
</uv-form>
|
||||
<!-- 产品 -->
|
||||
<view class="flex cif-title" @click="selectProduct">
|
||||
<view class="flex cif-title" @click="type !== 'detail' ? selectProduct() : ''">
|
||||
<view class="flex-1 text">产品关联</view>
|
||||
<view class="flex align-center" style="color:#2979ff">
|
||||
选择产品<uv-icon name="arrow-right" color="#909399" size="20"></uv-icon>
|
||||
@ -82,15 +89,13 @@
|
||||
<view class="item" v-for="(item,index) in selectList" :key="index">
|
||||
<view class="number flex">
|
||||
<view class="flex-1">序号: {{index+1}}</view>
|
||||
<uv-number-box :min="1" v-model="item.nums" :longPress="false"
|
||||
@change="isCheck ? valChange() : ''"></uv-number-box>
|
||||
<uni-number-box :min="1" v-model="item.nums" @change="valChange" :disabled="isCheck" />
|
||||
</view>
|
||||
<view class="content flex align-center">
|
||||
<view class="flex-1 storeName">{{item.storeName ? item.storeName : item.name}}({{item.sku}})</view>
|
||||
<view class="price flex align-center">
|
||||
<view class="pr-1" style="font-weight: 600;">¥</view>
|
||||
<uv-input :disabled="true" type="number" :clearable="false" placeholder="请输入价格" v-model="item.price"
|
||||
@input="isCheck ? inputChang : ''" />
|
||||
<uv-input :disabled="true" type="number" :clearable="false" placeholder="请输入价格" v-model="item.price" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="brief flex align-center">
|
||||
@ -98,7 +103,7 @@
|
||||
<uv-input v-model="item.remarks" :disabled="isCheck" />
|
||||
</view>
|
||||
<!-- 删除按钮 -->
|
||||
<view class="close" @click="type != 'check' ? remove(index) : ''">
|
||||
<view class="close" @click="type !== 'detail' ? remove(index) : ''">
|
||||
<uv-icon name="close" color="#909399" size="20"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
@ -107,25 +112,62 @@
|
||||
</view>
|
||||
<view class="flex mb-1 mt-1 align-center">
|
||||
<view class="mr-1" style="width:150rpx">优惠金额:</view>
|
||||
<view class="flex-1"><uv-input type="number" v-model="form.discountRate" :disabled="isCheck"
|
||||
placeholder="请填写0到100的数" @input="inputChang" /></view>
|
||||
<view class="flex-1">
|
||||
<uni-easyinput type="number" :disabled="isCheck" placeholder="请填写优惠金额" @blur="inputChang"
|
||||
v-model="form.discountRate"></uni-easyinput>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex mb-1 mt-3 align-center">
|
||||
<view class="mr-1" style="width: 150rpx">总额:</view>
|
||||
<view class="flex-1"><uv-input type="number" v-model="form.totalPrice" :disabled="isCheck" /></view>
|
||||
<view class="flex-1"><uv-input type="number" v-model="form.totalPrice" :disabled="true" /></view>
|
||||
</view>
|
||||
<view class="mt-4" style="text-align: center;" v-if="!isCheck">
|
||||
<uv-button color="#09b4f1" @click="submit" :disabled="form.checkStatus == 1 || form.checkStatus == 2"
|
||||
:ripple="true">确定提交</uv-button>
|
||||
<view class="container-item" style="flex-direction: column;align-items: flex-start;border-bottom: none;">
|
||||
<view class="container-item-upload">
|
||||
<view class="container-item-label">图片</view>
|
||||
</view>
|
||||
<view class="item-photo-list">
|
||||
<view class="item-photo-list-item" style="font-size: 0; position: relative;margin-bottom: 60rpx;"
|
||||
:style="{marginRight:(index+1)%3==0?'0rpx':'20rpx'}" v-for="(item, index) in imgFiles" :key="item"
|
||||
@click="replaceImage(item, index)">
|
||||
<image v-if="!isCheck" src="@/static/greyguanbi.png" mode="aspectFit" class="item-photo-list-item-close"
|
||||
@click.stop="deleteItem(item, index)"></image>
|
||||
<image v-if="!isCheck" :src="item.url" mode="" style="width: 100%; height: 100%"></image>
|
||||
</view>
|
||||
<image src="http://sys.znkjfw.com/imgs/process/uploadzp.png" mode="aspectFill" class="item-photo-list-item"
|
||||
v-if="imgFiles.length<9 && !isCheck" @click="chooseImage"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-4 flex justify-end" style="text-align: center;" v-else>
|
||||
<view class="container-item" style="flex-direction: column;align-items: flex-start;border-bottom: none;">
|
||||
<view class="container-item-upload">
|
||||
<view class="container-item-label">附件 (pdf)</view>
|
||||
</view>
|
||||
<view class="item-photo-list">
|
||||
<view class="item-photo-list-item" style="font-size: 0; position: relative;margin-bottom: 60rpx;"
|
||||
:style="{marginRight:(index+1)%3==0?'0rpx':'20rpx'}" v-for="(item, index) in pdfList" :key="item">
|
||||
<image v-if="!isCheck" src="@/static/greyguanbi.png" mode="aspectFit" class="item-photo-list-item-close"
|
||||
@click.stop="deleteFiles(item, index)"></image>
|
||||
<image v-if="!isCheck" src="http://sys.znkjfw.com/imgs/process/pdfIcon.png" mode=""
|
||||
style="width: 100%; height: 100%">
|
||||
</image>
|
||||
<view class="item-photo-list-item-name">
|
||||
{{item.name || ''}}
|
||||
</view>
|
||||
</view>
|
||||
<image v-if="!isCheck" src="http://sys.znkjfw.com/imgs/process/uploadzp.png" mode="aspectFill"
|
||||
class="item-photo-list-item" @click="chooseFiles"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-4" style="text-align: center;">
|
||||
<uv-button color="#09b4f1" @click="submit" :disabled="isCheck" :ripple="true">确定提交</uv-button>
|
||||
</view>
|
||||
<!-- <view class="mt-4 flex justify-end" style="text-align: center;" v-else>
|
||||
<view style="width: 25%;margin-right: 10rpx;">
|
||||
<uv-button color="#09b4f1" @click="submitCheck(1)">审核</uv-button>
|
||||
</view>
|
||||
<view style="width: 25%;">
|
||||
<uv-button type="error" @click="selectShow5()">拒绝</uv-button>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
<uv-popup mode="bottom" round="38" ref="selectShowRef5">
|
||||
<view class="popup-content">
|
||||
@ -134,7 +176,7 @@
|
||||
</view>
|
||||
<text class="">输入驳回理由</text>
|
||||
<view class="" @click="selectShowClose5" style="width: 45px;">
|
||||
<uv-icon name="close" color="#909399" size="30"></uv-icon>
|
||||
<uv-icon name="close" color="#909399" size="24"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view style="height: 500rpx;padding: 20rpx;">
|
||||
@ -143,7 +185,6 @@
|
||||
<view style="padding: 20rpx;">
|
||||
<uv-button color="#09b4f1" @click="submitCheck(2)">确定</uv-button>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</uv-popup>
|
||||
<!-- 选择客户弹窗 -->
|
||||
@ -154,7 +195,7 @@
|
||||
</view>
|
||||
<text class="">选择客户</text>
|
||||
<view class="" @click="selectShowClose" style="width: 45px;">
|
||||
<uv-icon name="close" color="#909399" size="30"></uv-icon>
|
||||
<uv-icon name="close" color="#909399" size="24"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
<uv-search margin="30rpx 20rpx" shape="square" v-model="keyword" :show-action="false" :clearabled="true"
|
||||
@ -184,7 +225,7 @@
|
||||
</view>
|
||||
<text class="">选择客户签约人</text>
|
||||
<view class="" @click="selectShowClose2" style="width: 45px;">
|
||||
<uv-icon name="close" color="#909399" size="30"></uv-icon>
|
||||
<uv-icon name="close" color="#909399" size="24"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view scroll-y style="height: 760rpx;width: 100%;">
|
||||
@ -212,17 +253,17 @@
|
||||
</view>
|
||||
<text class="">选择公司签约人</text>
|
||||
<view class="" @click="selectShowClose3" style="width: 45px;">
|
||||
<uv-icon name="close" color="#909399" size="30"></uv-icon>
|
||||
<uv-icon name="close" color="#909399" size="24"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
<uv-search margin="30rpx 20rpx" shape="square" v-model="keyword3" :show-action="false" :clearabled="true"
|
||||
placeholder="输入用户名称搜索" @change="onSearch3"></uv-search>
|
||||
<scroll-view scroll-y style="height: 760rpx;width: 100%;" @scrolltolower="reachBottom3">
|
||||
<uv-search margin="10rpx 26rpx 30rpx 26rpx" shape="square" v-model="keyword3" :show-action="false"
|
||||
:clearabled="true" placeholder="输入用户名称搜索" @change="onSearch3"></uv-search>
|
||||
<scroll-view scroll-y style="height: 760rpx;width: 100%;">
|
||||
<view class="list">
|
||||
<block v-if="userList.length > 0">
|
||||
<view class="mb-4">
|
||||
<view class="item flex" v-for="(item,index) in userList" :key="index" @click="onItem3(item,index)">
|
||||
<view class="title">{{item.username}}</view>
|
||||
<view class="title">{{item.nickname}}</view>
|
||||
<view class="check-icon">
|
||||
<uv-icon v-if="item.checked" name="checkmark" color="#09b4f1" size="28"></uv-icon>
|
||||
</view>
|
||||
@ -242,10 +283,10 @@
|
||||
</view>
|
||||
<text class="">选择商机</text>
|
||||
<view class="" @click="selectShowClose4" style="width: 45px;">
|
||||
<uv-icon name="close" color="#909399" size="30"></uv-icon>
|
||||
<uv-icon name="close" color="#909399" size="24"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view scroll-y style="height: 760rpx;width: 100%;" @scrolltolower="reachBottom3">
|
||||
<scroll-view scroll-y style="height: 760rpx;width: 100%;">
|
||||
<view class="list">
|
||||
<block v-if="businessList.length > 0">
|
||||
<view class="mb-4">
|
||||
@ -262,11 +303,40 @@
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uv-popup>
|
||||
<uv-datetime-picker ref="datetimePicker" v-model="timeValue" mode="datetime"
|
||||
<!-- 签约公司 -->
|
||||
<uv-popup mode="bottom" round="38" ref="selectShowRef6">
|
||||
<view class="popup-content">
|
||||
<view class="popup-title">
|
||||
<view class="" style="width: 45px;">
|
||||
</view>
|
||||
<text class="">选择签约公司</text>
|
||||
<view class="" @click="selectShowClose6" style="width: 45px;">
|
||||
<uv-icon name="close" color="#909399" size="24"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view scroll-y style="height: 760rpx;width: 100%;">
|
||||
<view class="list">
|
||||
<block v-if="companyList.length > 0">
|
||||
<view class="mb-4">
|
||||
<view class="item flex" v-for="(item,index) in companyList" :key="index" @click="onItem6(item,index)">
|
||||
<view class="title">{{item.name}}</view>
|
||||
<view class="check-icon">
|
||||
<uv-icon v-if="item.checked" name="checkmark" color="#09b4f1" size="28"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<uv-empty text="暂无数据" v-else mode="list"></uv-empty>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uv-popup>
|
||||
|
||||
<uv-datetime-picker ref="datetimePicker" v-model="timeValue" mode="date"
|
||||
@confirm="createTimeChange"></uv-datetime-picker>
|
||||
<uv-datetime-picker ref="datetimePicker2" v-model="timeValue2" mode="datetime"
|
||||
<uv-datetime-picker ref="datetimePicker2" v-model="timeValue2" mode="date"
|
||||
@confirm="createTimeChange2"></uv-datetime-picker>
|
||||
<uv-datetime-picker ref="datetimePicker3" v-model="timeValue2" mode="datetime"
|
||||
<uv-datetime-picker ref="datetimePicker3" v-model="timeValue2" mode="date"
|
||||
@confirm="createTimeChange3"></uv-datetime-picker>
|
||||
</view>
|
||||
</template>
|
||||
@ -283,8 +353,7 @@
|
||||
} from '@dcloudio/uni-app'
|
||||
import {
|
||||
getCustomerListPage,
|
||||
getContactsPage,
|
||||
createOAContract
|
||||
getContactsPage
|
||||
} from '@/api/customer'
|
||||
import {
|
||||
getBusinessProductListByBusinessId,
|
||||
@ -296,17 +365,24 @@
|
||||
getContract,
|
||||
getContractProductListByContractId,
|
||||
updateContract,
|
||||
check
|
||||
check,
|
||||
getCompanyDept,
|
||||
createOAContract,
|
||||
getOAContract
|
||||
} from '@/api/contract'
|
||||
import {
|
||||
getSimpleUserList,
|
||||
getFlowUsers,
|
||||
getSimpleUserList2
|
||||
getSimpleUserList2,
|
||||
getAllUserList,
|
||||
uploadFile,
|
||||
deleteBpmFile
|
||||
} from '@/api/user'
|
||||
import AddressSelect from '@/components/AddressSelect/index.vue'
|
||||
import {
|
||||
formatDateTime,
|
||||
prePage
|
||||
timestampToDate,
|
||||
prePage,
|
||||
getFileType
|
||||
} from '@/utils/util'
|
||||
import {
|
||||
useMainStore
|
||||
@ -314,6 +390,9 @@
|
||||
import {
|
||||
storeToRefs
|
||||
} from 'pinia'
|
||||
import {
|
||||
deepClone
|
||||
} from '../../../../uni_modules/uv-ui-tools/libs/function'
|
||||
const main = useMainStore()
|
||||
const {
|
||||
selectProductList
|
||||
@ -327,7 +406,7 @@
|
||||
const goodsName = ref('')
|
||||
const page = ref(1)
|
||||
const page3 = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const pageSize = ref(15)
|
||||
const lastPage = ref(false)
|
||||
const lastPage3 = ref(false)
|
||||
const selectList = ref([])
|
||||
@ -335,33 +414,30 @@
|
||||
const type = ref('add')
|
||||
const contractId = ref(0)
|
||||
const customerId = ref(0)
|
||||
const nextTime = ref('')
|
||||
const orderTime = ref(formatDateTime(new Date()))
|
||||
const startTime = ref(formatDateTime(new Date()))
|
||||
const endTime = ref(formatDateTime(new Date()))
|
||||
const content = ref('')
|
||||
const customerName = ref('')
|
||||
const form = ref({
|
||||
fileItems: [], //附件
|
||||
contractType: 1, // 合同类型
|
||||
contractNo: '', //合同编号
|
||||
contractName: '', //合同名称
|
||||
customerId: '', //客户ID
|
||||
customerName: '', //客户名称
|
||||
nextTime: '', //下次联系时间
|
||||
startDate: new Date(), //开始时间
|
||||
orderTime: new Date(), //下单时间
|
||||
endDate: new Date(), //结束时间
|
||||
startDate: timestampToDate(new Date()), //开始时间
|
||||
signingDate: timestampToDate(new Date()), //签约日期
|
||||
endDate: timestampToDate(new Date()), //结束时间
|
||||
remark: '', //备注
|
||||
discountRate: '', //整单折扣
|
||||
totalPrice: '', //产品总金额
|
||||
discountRate: 0, //整单折扣
|
||||
totalPrice: 0, //产品总金额
|
||||
contactsName: '', //客户签约人
|
||||
contactsId: '', //签约人id
|
||||
orderAdminName: '', //签约人名称
|
||||
companyId: '', //签约公司编号
|
||||
companyName: '', //签约公司名称
|
||||
businessId: '', //商机ID
|
||||
invoiceMoney: '', // 已开票金额
|
||||
returnMoney: '', // 已收/已付金额
|
||||
contractMoney: '', // 合同金额
|
||||
signatoryId: '', // 签约人编号
|
||||
signatoryName: '', // 签约人名称
|
||||
})
|
||||
const timeText = ref('')
|
||||
const errorType = ref('message')
|
||||
@ -381,55 +457,147 @@
|
||||
})
|
||||
|
||||
onLoad((e) => {
|
||||
if (e.type) {
|
||||
type.value = e.type
|
||||
}
|
||||
if (type.value == 'check') {
|
||||
type.value = e.type
|
||||
if (type.value == 'detail') {
|
||||
isCheck.value = true
|
||||
title.value = '审核合同'
|
||||
title.value = '合同详情'
|
||||
contractId.value = e.id
|
||||
getContractInfo()
|
||||
}
|
||||
if (type.value == "edit") {
|
||||
title.value = '编辑合同'
|
||||
contractId.value = e.id
|
||||
getContractInfo()
|
||||
} else {
|
||||
// getNumber()
|
||||
}
|
||||
getUserList() //获取签约人
|
||||
getCustomerList()
|
||||
getUserList()
|
||||
// getFlowUsersList() 获取审批人的
|
||||
getCompanyList() //获取公司列表
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
selectList.value = selectProductList.value
|
||||
selectList.value = selectProductList.value || []
|
||||
count_price()
|
||||
})
|
||||
|
||||
const getFlowUsersList = async () => {
|
||||
let data = await getFlowUsers({
|
||||
flowType: 'contract'
|
||||
// 附件上传相关
|
||||
const imgFiles = ref([]) //图片列表
|
||||
const pdfList = ref([]) //pdf列表
|
||||
//删除文件
|
||||
const deleteFiles = (val, i) => {
|
||||
deleteBpmFile({
|
||||
url: val.url
|
||||
}).then(res => {
|
||||
pdfList.value.splice(i, 1)
|
||||
})
|
||||
let users = await getSimpleUserList2()
|
||||
let userIdArr = []
|
||||
let userArr = []
|
||||
for (var i = 0; i <= data.length; i++) {
|
||||
users.forEach((item, index) => {
|
||||
if (data[i] == item.id) {
|
||||
userIdArr.push(item.id)
|
||||
userArr.push(item.nickname)
|
||||
}
|
||||
//上传
|
||||
const uploadFileApi = (url) => {
|
||||
return new Promise((reslove, reject) => {
|
||||
uploadFile(url, true)
|
||||
.then((res) => {
|
||||
console.log(res, 'success')
|
||||
reslove(res);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err, 'err')
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
//获取文件后缀名
|
||||
const getExtension = (fileName) => {
|
||||
let arr = fileName.split('.');
|
||||
return arr[arr.length - 1];
|
||||
}
|
||||
//选择图片
|
||||
const chooseImage = () => {
|
||||
uni.chooseImage({
|
||||
count: 9 - imgFiles.value.length, //默认9
|
||||
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
|
||||
sourceType: ['album', 'camera'], //从相册选择
|
||||
success: (res) => {
|
||||
let promise = Promise.resolve();
|
||||
let arr = [];
|
||||
uni.showLoading({
|
||||
title: '上传中'
|
||||
})
|
||||
|
||||
res.tempFilePaths.forEach((item) => {
|
||||
promise = promise.then(() => uploadFileApi(item));
|
||||
promise
|
||||
.then((ress) => {
|
||||
arr.push(1)
|
||||
imgFiles.value.push({
|
||||
name: ress.name,
|
||||
url: ress.url
|
||||
})
|
||||
if (arr.length >= res.tempFilePaths.length) {
|
||||
uni.hideLoading()
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.hideLoading()
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
//上传文件 pdf
|
||||
const chooseFiles = () => {
|
||||
wx.chooseMessageFile({
|
||||
count: 9 - pdfList.value.length, //默认100
|
||||
extension: ['pdf', '.pdf'],
|
||||
success: (res) => {
|
||||
let isUploadFile = true
|
||||
res.tempFiles.forEach(item => {
|
||||
if (getExtension(item.name) != 'pdf') {
|
||||
isUploadFile = false
|
||||
}
|
||||
})
|
||||
if (!isUploadFile) {
|
||||
uni.showToast({
|
||||
title: '请您上传pdf格式文件',
|
||||
});
|
||||
return
|
||||
}
|
||||
let promise = Promise.resolve();
|
||||
let arr = [];
|
||||
uni.showLoading({
|
||||
title: '上传中'
|
||||
})
|
||||
|
||||
res.tempFiles.forEach((item) => {
|
||||
promise = promise.then(() => uploadFileApi(item.path));
|
||||
promise
|
||||
.then((ress) => {
|
||||
arr.push(1)
|
||||
pdfList.value.push({
|
||||
name: ress.name,
|
||||
url: ress.url
|
||||
})
|
||||
if (arr.length >= res.tempFilePaths.length) {
|
||||
uni.hideLoading()
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.hideLoading()
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//获取公司列表
|
||||
const companyList = ref([])
|
||||
const getCompanyList = async () => {
|
||||
companyList.value = await getCompanyDept()
|
||||
if (form.value.companyId) {
|
||||
companyList.value.forEach((item, index) => {
|
||||
if (form.value.companyId == item.id) {
|
||||
item.checked = true
|
||||
} else {
|
||||
item.checked = false
|
||||
}
|
||||
})
|
||||
}
|
||||
form.value.flowAdminIdName = userArr.join(',')
|
||||
form.value.flowAdminId = userIdArr
|
||||
}
|
||||
|
||||
//合同编号
|
||||
const getNumber = async () => {
|
||||
form.value.contractNo = await getContractNo()
|
||||
}
|
||||
|
||||
const selectShowRef = ref()
|
||||
const selectShow = () => {
|
||||
@ -446,8 +614,7 @@
|
||||
|
||||
// 选择时间
|
||||
const createTimeChange = (e) => {
|
||||
form.value.orderTime = e.value
|
||||
orderTime.value = formatDateTime(e.value)
|
||||
form.value.signingDate = timestampToDate(e.value)
|
||||
}
|
||||
|
||||
const datetimePicker2 = ref()
|
||||
@ -457,8 +624,19 @@
|
||||
|
||||
// 选择时间
|
||||
const createTimeChange2 = (e) => {
|
||||
form.value.startDate = e.value
|
||||
startTime.value = formatDateTime(e.value)
|
||||
form.value.startDate = timestampToDate(e.value)
|
||||
if (form.value.endDate) {
|
||||
//比较开始时间和结束时间大小
|
||||
let startDate = new Date(form.value.startDate);
|
||||
let endDate = new Date(form.value.endDate);
|
||||
if (endDate < startDate) {
|
||||
form.value.endDate = ''
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '结束时间不能大于开始时间'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const datetimePicker3 = ref()
|
||||
@ -468,15 +646,36 @@
|
||||
|
||||
// 选择时间
|
||||
const createTimeChange3 = (e) => {
|
||||
form.value.endDate = e.value
|
||||
endTime.value = formatDateTime(e.value)
|
||||
form.value.endDate = timestampToDate(e.value)
|
||||
if (form.value.startDate) {
|
||||
//比较开始时间和结束时间大小
|
||||
let startDate = new Date(form.value.startDate);
|
||||
let endDate = new Date(form.value.endDate);
|
||||
if (endDate < startDate) {
|
||||
form.value.endDate = ''
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '结束时间不能大于开始时间'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
// 获取商机数据详情
|
||||
const getContractInfo = async () => {
|
||||
form.value = await getContract({
|
||||
form.value = await getOAContract({
|
||||
id: contractId.value
|
||||
})
|
||||
form.value.flowAdminId = form.value.flowAdminId2
|
||||
if (form.value.fileItems.length) {
|
||||
form.value.fileItems.forEach(item => {
|
||||
if (getFileType(item.name) == 'image') {
|
||||
imgFiles.value.push(item)
|
||||
}
|
||||
if (getFileType(item.name) == 'pdf') {
|
||||
pdfList.value.push(item)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
selectList.value = await getContractProductListByContractId({
|
||||
contractId: contractId.value
|
||||
})
|
||||
@ -493,7 +692,6 @@
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/business/selectProduct'
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
const getCustomerList = async (isNextPage, pages) => {
|
||||
@ -505,7 +703,7 @@
|
||||
}).then(res => {
|
||||
if (res) {
|
||||
// 不够一页
|
||||
if (res.list.length < 10) {
|
||||
if (res.list.length < pageSize.value) {
|
||||
listStatus.value = 'nomore'
|
||||
}
|
||||
// 最后一页
|
||||
@ -534,37 +732,20 @@
|
||||
}
|
||||
|
||||
const getUserList = async (isNextPage, pages) => {
|
||||
await getSimpleUserList({
|
||||
pageNo: page.value,
|
||||
pageSize: pageSize.value,
|
||||
await getAllUserList({
|
||||
username: keyword3.value,
|
||||
deptId: form.value.companyId
|
||||
}).then(res => {
|
||||
if (res) {
|
||||
// 不够一页
|
||||
if (res.list.length < 10) {
|
||||
listStatus3.value = 'nomore'
|
||||
}
|
||||
// 最后一页
|
||||
if (res.list.length == 0) {
|
||||
lastPage3.value = true
|
||||
}
|
||||
// 第二页开始
|
||||
if (isNextPage) {
|
||||
userList.value = userList.value.concat(res.list)
|
||||
return
|
||||
}
|
||||
userList.value = res.list
|
||||
|
||||
if (form.value.orderAdminId) {
|
||||
userList.value.forEach((item, index) => {
|
||||
if (form.value.orderAdminId == item.id) {
|
||||
item.checked = true
|
||||
username.value = item.username
|
||||
} else {
|
||||
item.checked = false
|
||||
}
|
||||
})
|
||||
}
|
||||
userList.value = res
|
||||
if (form.value.signatoryId) {
|
||||
userList.value.forEach((item, index) => {
|
||||
if (form.value.signatoryId == item.id) {
|
||||
item.checked = true
|
||||
username.value = item.nickname
|
||||
} else {
|
||||
item.checked = false
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -574,28 +755,16 @@
|
||||
const reachBottom = () => {
|
||||
if (lastPage.value || listStatus.value == 'loading') return
|
||||
listStatus.value = 'loading'
|
||||
setTimeout(() => {
|
||||
getCustomerList(true, ++page.value)
|
||||
if (customerList.value.length >= 10) {
|
||||
listStatus.value = 'loadmore';
|
||||
} else {
|
||||
listStatus.values = 'loading';
|
||||
}
|
||||
}, 1200)
|
||||
page.value++
|
||||
getCustomerList(true, page.value)
|
||||
if (customerList.value.length >= pageSize.value) {
|
||||
listStatus.value = 'loadmore';
|
||||
} else {
|
||||
listStatus.values = 'loading';
|
||||
}
|
||||
}
|
||||
|
||||
const reachBottom3 = () => {
|
||||
if (lastPage3.value || listStatus3.value == 'loading') return
|
||||
listStatus3.value = 'loading'
|
||||
setTimeout(() => {
|
||||
getUserList(true, ++page3.value)
|
||||
if (userList.value.length >= 10) {
|
||||
listStatus3.value = 'loadmore';
|
||||
} else {
|
||||
listStatus3.values = 'loading';
|
||||
}
|
||||
}, 1200)
|
||||
}
|
||||
|
||||
// 选择客户
|
||||
const onItem = async (val, i) => {
|
||||
customerList.value.forEach((item, index) => {
|
||||
@ -607,7 +776,6 @@
|
||||
}
|
||||
})
|
||||
form.value.customerId = val.id
|
||||
|
||||
form.value.customerName = val.name ? val.name : ''
|
||||
//选择了客户 返回客户联系人
|
||||
let data = await getContactsPage({
|
||||
@ -640,7 +808,6 @@
|
||||
}
|
||||
})
|
||||
form.value.contactsId = val.id
|
||||
|
||||
form.value.contactsName = val.name ? val.name : ''
|
||||
selectShowClose2()
|
||||
}
|
||||
@ -658,13 +825,12 @@
|
||||
userList.value.forEach((item, index) => {
|
||||
if (val.id == item.id) {
|
||||
item.checked = true
|
||||
val.username = val.username ? val.username : item.username;
|
||||
} else {
|
||||
item.checked = false
|
||||
}
|
||||
})
|
||||
form.value.orderAdminId = val.id
|
||||
form.value.orderAdminName = val.username ? val.username : ''
|
||||
form.value.signatoryId = val.id
|
||||
form.value.signatoryName = val.nickname ? val.nickname : ''
|
||||
selectShowClose3()
|
||||
}
|
||||
|
||||
@ -690,7 +856,6 @@
|
||||
selectList.value = await getBusinessProductListByBusinessId({
|
||||
businessId: val.id
|
||||
})
|
||||
|
||||
selectShowClose4()
|
||||
}
|
||||
|
||||
@ -702,12 +867,52 @@
|
||||
unref(selectShowRef5).close()
|
||||
}
|
||||
|
||||
//公司
|
||||
const selectShowRef6 = ref()
|
||||
const selectShow6 = async () => {
|
||||
unref(selectShowRef6).open()
|
||||
}
|
||||
const selectShowClose6 = () => {
|
||||
unref(selectShowRef6).close()
|
||||
}
|
||||
const onItem6 = (val, i) => {
|
||||
companyList.value.forEach((item, index) => {
|
||||
if (val.id == item.id) {
|
||||
item.checked = true
|
||||
} else {
|
||||
item.checked = false
|
||||
}
|
||||
})
|
||||
form.value.companyId = val.id
|
||||
form.value.companyName = val.name
|
||||
userList.value = []
|
||||
page3.value = 1
|
||||
getUserList()
|
||||
selectShowClose6()
|
||||
}
|
||||
|
||||
// 产品数量增加
|
||||
const valChange = () => {
|
||||
const valChange = (e) => {
|
||||
count_price()
|
||||
}
|
||||
// 优惠率改变
|
||||
const inputChang = () => {
|
||||
const inputChang = (e) => {
|
||||
if (e.detail.value > form.value.totalPrice) {
|
||||
form.value.discountRate = 0
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '折扣金额不能大于总金额'
|
||||
})
|
||||
}
|
||||
|
||||
if (e.detail.value < 0) {
|
||||
form.value.discountRate = 0
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '折扣金额不能小于0'
|
||||
})
|
||||
}
|
||||
|
||||
count_price()
|
||||
}
|
||||
// 移除已选产品
|
||||
@ -717,16 +922,18 @@
|
||||
}
|
||||
// 计算价格
|
||||
const count_price = () => {
|
||||
let total = 0;
|
||||
setTimeout(() => {
|
||||
for (let i = 0; i < selectList.value.length; i++) {
|
||||
total += selectList.value[i].nums * selectList.value[i].price
|
||||
}
|
||||
if (form.value.discountRate > 0) {
|
||||
total = total - (form.value.discountRate / 100) * total
|
||||
let list = deepClone(selectList.value)
|
||||
|
||||
if (list.length > 0) {
|
||||
let total = 0;
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
total = total + (list[i].nums * list[i].price)
|
||||
}
|
||||
total = total - Number(form.value.discountRate || 0)
|
||||
form.value.totalPrice = total.toFixed(2)
|
||||
}, 500)
|
||||
} else {
|
||||
form.value.totalPrice = 0
|
||||
}
|
||||
}
|
||||
|
||||
const submitCheck = async (type) => {
|
||||
@ -785,7 +992,7 @@
|
||||
})
|
||||
return
|
||||
}
|
||||
if (form.value.orderAdminIdName == '') {
|
||||
if (form.value.signatoryId == '') {
|
||||
uni.showToast({
|
||||
icon: 'error',
|
||||
title: '请选择公司签约人'
|
||||
@ -819,11 +1026,10 @@
|
||||
obj.subtotal = item.nums * item.price
|
||||
newArr[index] = obj
|
||||
})
|
||||
if (type.value == 'add') {
|
||||
|
||||
if (type.value !== 'detail') {
|
||||
form.value.contractProducts = newArr
|
||||
await createContract(form.value)
|
||||
|
||||
form.value.fileItems = [...imgFiles.value, ...pdfList.value]
|
||||
await createOAContract(form.value)
|
||||
uni.showToast({
|
||||
title: '添加成功',
|
||||
icon: 'success',
|
||||
@ -834,9 +1040,6 @@
|
||||
uni.navigateBack();
|
||||
}, 1000);
|
||||
} else {
|
||||
// selectList.value.forEach((item,index)=>{
|
||||
// item.subtotal = item.nums * item.price
|
||||
// })
|
||||
form.value.contractProducts = newArr
|
||||
await updateContract(form.value)
|
||||
uni.showToast({
|
||||
@ -855,7 +1058,7 @@
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.set-box {
|
||||
padding: 0rpx 22rpx 34rpx 22rpx;
|
||||
padding: 0rpx 22rpx 30rpx 34rpx;
|
||||
margin-bottom: 80rpx;
|
||||
|
||||
.cif-title {
|
||||
@ -924,7 +1127,7 @@
|
||||
font-size: 35rpx;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
height: 50px;
|
||||
height: 64px;
|
||||
padding-right: 25rpx;
|
||||
}
|
||||
|
||||
@ -932,19 +1135,17 @@
|
||||
margin-bottom: 45rpx;
|
||||
|
||||
.item {
|
||||
padding: 0 25rpx;
|
||||
padding: 0 20rpx 30rpx 30rpx;
|
||||
justify-content: space-between;
|
||||
height: 45px;
|
||||
|
||||
.title {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
font-size: 29rpx;
|
||||
}
|
||||
|
||||
.check-icon {
|
||||
text-align: center;
|
||||
width: 100rpx;
|
||||
// width: 100rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -959,4 +1160,69 @@
|
||||
.storeName {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.container-item {
|
||||
width: 100%;
|
||||
padding: 25rpx 0;
|
||||
border-bottom: 1rpx solid #e8e8e8;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.container-item-label {
|
||||
flex-shrink: 0;
|
||||
color: #020202;
|
||||
font-weight: 400;
|
||||
font-face: PingFang SC;
|
||||
font-size: 30rpx;
|
||||
margin-right: 15rpx;
|
||||
}
|
||||
|
||||
.item-photo-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 30rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.item-photo-list-item-name {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
bottom: -40rpx;
|
||||
font-size: 22rpx;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
/* 确保超出容器的文本被裁剪 */
|
||||
white-space: nowrap;
|
||||
/* 确保文本在一行内显示 */
|
||||
text-overflow: ellipsis;
|
||||
/* 超出部分显示为省略号 */
|
||||
}
|
||||
|
||||
.item-photo-list-item-close {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
position: absolute;
|
||||
right: -20rpx;
|
||||
top: -20rpx;
|
||||
}
|
||||
|
||||
.item-photo-list-item {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
flex-shrink: 0;
|
||||
border: 2rpx solid #e5e5e5;
|
||||
border-radius: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
/* margin-right: 20rpx; */
|
||||
}
|
||||
|
||||
.container-item-upload {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
@ -19,35 +19,30 @@
|
||||
@scrolltolower="reachBottom">
|
||||
<view class="page-box">
|
||||
<block v-if="dataList.length > 0">
|
||||
<view class="client" v-for="(items, index) in dataList" :key="index" @click="onItem(items.id)">
|
||||
<view class="client" v-for="(items, index) in dataList" :key="index">
|
||||
<view class="top">
|
||||
<view class="left uv-line-1">
|
||||
<view class="store uv-line-1">{{items.name}}</view>
|
||||
<view class="store uv-line-1">{{items.contractName}}</view>
|
||||
</view>
|
||||
<view class="flex">
|
||||
<uv-text v-if="items.checkStatus === 1" type="warning" text="审核中"></uv-text>
|
||||
<uv-text v-else-if="items.checkStatus === 2" type="success" text="审核通过"></uv-text>
|
||||
<uv-text v-else-if="items.checkStatus === 3" type="info" text="审核未通过"></uv-text>
|
||||
<uv-text v-else type="error" text="待审核"></uv-text>
|
||||
<uv-icon name="arrow-right" :size="20"></uv-icon>
|
||||
<view class="flex align-center">
|
||||
<text
|
||||
:style="{color:items.result==1?'#4687fc':items.result==2?'#4cd964':items.result==3?'#dd524d':'#999999'}">{{fillterStatus(items.result)}}</text>
|
||||
<uv-icon name="arrow-right" :size="16"
|
||||
:color="items.result==1?'#4687fc':items.result==2?'#4cd964':items.result==3?'#dd524d':'#999999'"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item align-center">
|
||||
<view class="content">
|
||||
<view class="title uv-line-2">¥{{items.money}} <text class="pl-1">回款:¥{{items.returnMoney}}</text>
|
||||
<view class="title uv-line-2">¥{{items.contractMoney}} <text
|
||||
class="pl-1">回款:¥{{items.returnMoney}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right">{{items.orderAdminName ? items.orderAdminName : '--'}}</view>
|
||||
<view class="right">{{items.signatoryName ? items.signatoryName : '暂无'}}</view>
|
||||
</view>
|
||||
<view class="bottom">
|
||||
<view class="client_time">到期:{{timeFormats(items.endTime)}}</view>
|
||||
<view class="client_time">到期:{{timestampToDate(items.endDate)}}</view>
|
||||
<view class="flex">
|
||||
<block v-if="items.isCheck">
|
||||
<view class="btn ml-1 entity" @click.stop="onCheck(items.id)">审核</view>
|
||||
</block>
|
||||
<block v-else>
|
||||
<view class="btn ml-1 primary" @click.stop="onCheck(items.id,'look')">详情</view>
|
||||
</block>
|
||||
<view class="btn ml-1 primary" @click.stop="onCheck(items.id)">详情</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -76,10 +71,13 @@
|
||||
} from '@dcloudio/uni-app'
|
||||
import {
|
||||
getContractPage,
|
||||
getOAContractPage
|
||||
getOAContractPage,
|
||||
} from '@/api/contract'
|
||||
import {
|
||||
formatDateTime
|
||||
getDictData,
|
||||
} from '@/api/customer.js'
|
||||
import {
|
||||
timestampToDate
|
||||
} from '@/utils/util'
|
||||
const title = ref('合同')
|
||||
const keyword = ref('')
|
||||
@ -131,8 +129,30 @@
|
||||
scrollTop.value = 0
|
||||
dataList.value = []
|
||||
getList()
|
||||
getStatusList()
|
||||
})
|
||||
|
||||
const statusList = ref([])
|
||||
const getStatusList = () => {
|
||||
getDictData({
|
||||
type: 'bpm_process_instance_result'
|
||||
}).then(res => {
|
||||
statusList.value = res
|
||||
})
|
||||
}
|
||||
|
||||
//格式化状态
|
||||
const fillterStatus = (status) => {
|
||||
if (statusList.value.length) {
|
||||
let obj = statusList.value.find(item => {
|
||||
return item.value == status
|
||||
})
|
||||
return obj == undefined ? '' : obj.name
|
||||
} else {
|
||||
return status
|
||||
}
|
||||
}
|
||||
|
||||
const timeFormats = (val) => {
|
||||
if (val) {
|
||||
return formatDateTime(val)
|
||||
@ -140,24 +160,12 @@
|
||||
return '--'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const handleSelect = (key) => {
|
||||
relation.value = key.value
|
||||
getList()
|
||||
}
|
||||
|
||||
// 审核
|
||||
const onCheck = (id, type) => {
|
||||
if (type == 'look') {
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/contract/add?id=' + id + '&type=edit'
|
||||
});
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/contract/add?id=' + id + '&type=check'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const getList = async (isNextPage, pages) => {
|
||||
await getOAContractPage({
|
||||
@ -205,9 +213,10 @@
|
||||
getList()
|
||||
}
|
||||
|
||||
const onItem = (val) => {
|
||||
// 详情
|
||||
const onCheck = (id, type) => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/contract/add?id=' + val + '&type=edit'
|
||||
url: '/pages/components/pages/contract/add?id=' + id + '&type=detail'
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,133 +1,146 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
@leftClick="$onClickLeft"
|
||||
bgColor="#09b4f1"
|
||||
>
|
||||
<template v-slot:left>
|
||||
<uv-icon name="arrow-left" size="19" color="#ffffff"></uv-icon>
|
||||
</template>
|
||||
<template v-slot:center>
|
||||
<text style="color:#ffffff">{{title}}</text>
|
||||
</template>
|
||||
</uv-navbar>
|
||||
<view class="bg-white">
|
||||
<uv-cell-group>
|
||||
<uv-cell customStyle="padding:10rpx 0" title="修改个人信息" :isLink="true" arrow-direction="right" @click="gopage('/pages/components/pages/mine/edit')"></uv-cell>
|
||||
<uv-cell customStyle="padding:10rpx 0" title="修改密码" :isLink="true" arrow-direction="right" @click="gopage('/pages/components/pages/mine/pass')"></uv-cell>
|
||||
<uv-cell customStyle="padding:10rpx 0" title="退出登录" :isLink="true" arrow-direction="right" @click="logout"></uv-cell>
|
||||
</uv-cell-group>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed
|
||||
} from 'vue'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onLoad,onShow} from '@dcloudio/uni-app'
|
||||
import { formatDateTime } from '@/utils/util'
|
||||
import {
|
||||
userLogout
|
||||
} from '@/api/auth'
|
||||
import { VUE_APP_UPLOAD_URL,TENANT_ID } from '@/config';
|
||||
const main = useMainStore()
|
||||
const { openid, lang } = storeToRefs(main)
|
||||
|
||||
const title = ref('设置')
|
||||
const date = ref('')
|
||||
const member = ref({})
|
||||
|
||||
onLoad(() => {
|
||||
member.value = main.member;
|
||||
})
|
||||
|
||||
const logout = () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定退出吗?',
|
||||
success: async function (res) {
|
||||
if (res.confirm) {
|
||||
await userLogout()
|
||||
uni.showToast({
|
||||
title: '退出成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
setTimeout(() => {
|
||||
gopage('/pages/components/pages/login/login')
|
||||
}, 1500);
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const gopage = (url) => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.form {
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
.label {
|
||||
width: 160rpx;
|
||||
font-size: $font-size-base;
|
||||
color: $text-color-base;
|
||||
}
|
||||
|
||||
.input {
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
|
||||
.radio {
|
||||
padding: 10rpx 30rpx;
|
||||
border-radius: 6rpx;
|
||||
border: 2rpx solid $text-color-assist;
|
||||
color: $text-color-assist;
|
||||
font-size: $font-size-base;
|
||||
|
||||
&.checked {
|
||||
background-color: $color-primary;
|
||||
color: $text-color-white;
|
||||
border: 2rpx solid $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-box {
|
||||
// height: calc((100vh - 40rpx) / 2);
|
||||
}
|
||||
.save-btn {
|
||||
width: 90%;
|
||||
border-radius: 50rem !important;
|
||||
font-size: $font-size-lg;
|
||||
}
|
||||
.logout-btn {
|
||||
width: 90%;
|
||||
border-radius: 50rem !important;
|
||||
font-size: $font-size-lg;
|
||||
background-color:rgb(237, 81, 29);
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<uv-navbar :fixed="false" @leftClick="$onClickLeft" bgColor="#09b4f1">
|
||||
<template v-slot:left>
|
||||
<uv-icon name="arrow-left" size="19" color="#ffffff"></uv-icon>
|
||||
</template>
|
||||
<template v-slot:center>
|
||||
<text style="color:#ffffff">{{title}}</text>
|
||||
</template>
|
||||
</uv-navbar>
|
||||
<view class="bg-white">
|
||||
<uv-cell-group :border='false'>
|
||||
<!-- <uv-cell customStyle="padding:10rpx 0" title="修改个人信息" :isLink="true" arrow-direction="right"
|
||||
@click="gopage('/pages/components/pages/mine/edit')"></uv-cell>
|
||||
<uv-cell customStyle="padding:10rpx 0" title="修改密码" :isLink="true" arrow-direction="right"
|
||||
@click="gopage('/pages/components/pages/mine/pass')"></uv-cell> -->
|
||||
<uv-cell size="large" title="退出登录" :isLink="true" arrow-direction="right" @click="logout"></uv-cell>
|
||||
</uv-cell-group>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed
|
||||
} from 'vue'
|
||||
import {
|
||||
useMainStore
|
||||
} from '@/store/store'
|
||||
import {
|
||||
storeToRefs
|
||||
} from 'pinia'
|
||||
import {
|
||||
onLoad,
|
||||
onShow
|
||||
} from '@dcloudio/uni-app'
|
||||
import {
|
||||
formatDateTime
|
||||
} from '@/utils/util'
|
||||
import {
|
||||
userLogout
|
||||
} from '@/api/auth'
|
||||
import {
|
||||
VUE_APP_UPLOAD_URL,
|
||||
TENANT_ID
|
||||
} from '@/config';
|
||||
const main = useMainStore()
|
||||
const {
|
||||
openid,
|
||||
lang
|
||||
} = storeToRefs(main)
|
||||
|
||||
const title = ref('设置')
|
||||
const date = ref('')
|
||||
const member = ref({})
|
||||
|
||||
onLoad(() => {
|
||||
member.value = main.member;
|
||||
})
|
||||
|
||||
const logout = () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定退出吗?',
|
||||
success: async function(res) {
|
||||
if (res.confirm) {
|
||||
await userLogout()
|
||||
uni.showToast({
|
||||
title: '退出成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
setTimeout(() => {
|
||||
gopage('/pages/components/pages/login/login')
|
||||
}, 1500);
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const gopage = (url) => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.form {
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
.label {
|
||||
width: 160rpx;
|
||||
font-size: $font-size-base;
|
||||
color: $text-color-base;
|
||||
}
|
||||
|
||||
.input {}
|
||||
|
||||
.radio-group {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
|
||||
.radio {
|
||||
padding: 10rpx 30rpx;
|
||||
border-radius: 6rpx;
|
||||
border: 2rpx solid $text-color-assist;
|
||||
color: $text-color-assist;
|
||||
font-size: $font-size-base;
|
||||
|
||||
&.checked {
|
||||
background-color: $color-primary;
|
||||
color: $text-color-white;
|
||||
border: 2rpx solid $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-box {
|
||||
// height: calc((100vh - 40rpx) / 2);
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
width: 90%;
|
||||
border-radius: 50rem !important;
|
||||
font-size: $font-size-lg;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
width: 90%;
|
||||
border-radius: 50rem !important;
|
||||
font-size: $font-size-lg;
|
||||
background-color: rgb(237, 81, 29);
|
||||
}
|
||||
</style>
|
@ -8,7 +8,6 @@
|
||||
</template>
|
||||
</uv-navbar>
|
||||
<view class="bg-white">
|
||||
<view class="font-size-sm px-5 py-2">2024-10-07</view>
|
||||
<uv-cell-group>
|
||||
<uv-cell @click="gopage('/pages/customer/index')" icon="/static/images/19.png" title="待跟进客户"
|
||||
iconStyle="height:70rpx;width:70rpx;margin-right:10rpx">
|
||||
|
@ -12,9 +12,9 @@
|
||||
<text class="id-text">{{roleName}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="mt-2 mr-4" @tap="gopage('/pages/components/pages/mine/index')">
|
||||
<view class="mt-2 mr-4" @tap="gopage('/pages/components/pages/mine/index')">
|
||||
<image src="/static/images/mine/set.png" class="setting-icon-img"></image>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
<view style="padding: 0 30rpx;">
|
||||
<view class="user-box">
|
||||
|
BIN
static/greyguanbi.png
Normal file
BIN
static/greyguanbi.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
115
uni_modules/uni-easyinput/changelog.md
Normal file
115
uni_modules/uni-easyinput/changelog.md
Normal file
@ -0,0 +1,115 @@
|
||||
## 1.1.19(2024-07-18)
|
||||
- 修复 初始值传入 null 导致input报错的bug
|
||||
## 1.1.18(2024-04-11)
|
||||
- 修复 easyinput组件双向绑定问题
|
||||
## 1.1.17(2024-03-28)
|
||||
- 修复 在头条小程序下丢失事件绑定的问题
|
||||
## 1.1.16(2024-03-20)
|
||||
- 修复 在密码输入情况下 清除和小眼睛覆盖bug 在edge浏览器下显示双眼睛bug
|
||||
## 1.1.15(2024-02-21)
|
||||
- 新增 左侧插槽:left
|
||||
## 1.1.14(2024-02-19)
|
||||
- 修复 onBlur的emit传值错误
|
||||
## 1.1.12(2024-01-29)
|
||||
- 补充 adjust-position文档属性补充
|
||||
## 1.1.11(2024-01-29)
|
||||
- 补充 adjust-position属性传递值:(Boolean)当键盘弹起时,是否自动上推页面
|
||||
## 1.1.10(2024-01-22)
|
||||
- 去除 移除无用的log输出
|
||||
## 1.1.9(2023-04-11)
|
||||
- 修复 vue3 下 keyboardheightchange 事件报错的bug
|
||||
## 1.1.8(2023-03-29)
|
||||
- 优化 trim 属性默认值
|
||||
## 1.1.7(2023-03-29)
|
||||
- 新增 cursor-spacing 属性
|
||||
## 1.1.6(2023-01-28)
|
||||
- 新增 keyboardheightchange 事件,可监听键盘高度变化
|
||||
## 1.1.5(2022-11-29)
|
||||
- 优化 主题样式
|
||||
## 1.1.4(2022-10-27)
|
||||
- 修复 props 中背景颜色无默认值的bug
|
||||
## 1.1.0(2022-06-30)
|
||||
|
||||
- 新增 在 uni-forms 1.4.0 中使用可以在 blur 时校验内容
|
||||
- 新增 clear 事件,点击右侧叉号图标触发
|
||||
- 新增 change 事件 ,仅在输入框失去焦点或用户按下回车时触发
|
||||
- 优化 组件样式,组件获取焦点时高亮显示,图标颜色调整等
|
||||
|
||||
## 1.0.5(2022-06-07)
|
||||
|
||||
- 优化 clearable 显示策略
|
||||
|
||||
## 1.0.4(2022-06-07)
|
||||
|
||||
- 优化 clearable 显示策略
|
||||
|
||||
## 1.0.3(2022-05-20)
|
||||
|
||||
- 修复 关闭图标某些情况下无法取消的 bug
|
||||
|
||||
## 1.0.2(2022-04-12)
|
||||
|
||||
- 修复 默认值不生效的 bug
|
||||
|
||||
## 1.0.1(2022-04-02)
|
||||
|
||||
- 修复 value 不能为 0 的 bug
|
||||
|
||||
## 1.0.0(2021-11-19)
|
||||
|
||||
- 优化 组件 UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-easyinput](https://uniapp.dcloud.io/component/uniui/uni-easyinput)
|
||||
|
||||
## 0.1.4(2021-08-20)
|
||||
|
||||
- 修复 在 uni-forms 的动态表单中默认值校验不通过的 bug
|
||||
|
||||
## 0.1.3(2021-08-11)
|
||||
|
||||
- 修复 在 uni-forms 中重置表单,错误信息无法清除的问题
|
||||
|
||||
## 0.1.2(2021-07-30)
|
||||
|
||||
- 优化 vue3 下事件警告的问题
|
||||
|
||||
## 0.1.1
|
||||
|
||||
- 优化 errorMessage 属性支持 Boolean 类型
|
||||
|
||||
## 0.1.0(2021-07-13)
|
||||
|
||||
- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||
|
||||
## 0.0.16(2021-06-29)
|
||||
|
||||
- 修复 confirmType 属性(仅 type="text" 生效)导致多行文本框无法换行的 bug
|
||||
|
||||
## 0.0.15(2021-06-21)
|
||||
|
||||
- 修复 passwordIcon 属性拼写错误的 bug
|
||||
|
||||
## 0.0.14(2021-06-18)
|
||||
|
||||
- 新增 passwordIcon 属性,当 type=password 时是否显示小眼睛图标
|
||||
- 修复 confirmType 属性不生效的问题
|
||||
|
||||
## 0.0.13(2021-06-04)
|
||||
|
||||
- 修复 disabled 状态可清出内容的 bug
|
||||
|
||||
## 0.0.12(2021-05-12)
|
||||
|
||||
- 新增 组件示例地址
|
||||
|
||||
## 0.0.11(2021-05-07)
|
||||
|
||||
- 修复 input-border 属性不生效的问题
|
||||
|
||||
## 0.0.10(2021-04-30)
|
||||
|
||||
- 修复 ios 遮挡文字、显示一半的问题
|
||||
|
||||
## 0.0.9(2021-02-05)
|
||||
|
||||
- 调整为 uni_modules 目录规范
|
||||
- 优化 兼容 nvue 页面
|
54
uni_modules/uni-easyinput/components/uni-easyinput/common.js
Normal file
54
uni_modules/uni-easyinput/components/uni-easyinput/common.js
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @desc 函数防抖
|
||||
* @param func 目标函数
|
||||
* @param wait 延迟执行毫秒数
|
||||
* @param immediate true - 立即执行, false - 延迟执行
|
||||
*/
|
||||
export const debounce = function(func, wait = 1000, immediate = true) {
|
||||
let timer;
|
||||
return function() {
|
||||
let context = this,
|
||||
args = arguments;
|
||||
if (timer) clearTimeout(timer);
|
||||
if (immediate) {
|
||||
let callNow = !timer;
|
||||
timer = setTimeout(() => {
|
||||
timer = null;
|
||||
}, wait);
|
||||
if (callNow) func.apply(context, args);
|
||||
} else {
|
||||
timer = setTimeout(() => {
|
||||
func.apply(context, args);
|
||||
}, wait)
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @desc 函数节流
|
||||
* @param func 函数
|
||||
* @param wait 延迟执行毫秒数
|
||||
* @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发
|
||||
*/
|
||||
export const throttle = (func, wait = 1000, type = 1) => {
|
||||
let previous = 0;
|
||||
let timeout;
|
||||
return function() {
|
||||
let context = this;
|
||||
let args = arguments;
|
||||
if (type === 1) {
|
||||
let now = Date.now();
|
||||
|
||||
if (now - previous > wait) {
|
||||
func.apply(context, args);
|
||||
previous = now;
|
||||
}
|
||||
} else if (type === 2) {
|
||||
if (!timeout) {
|
||||
timeout = setTimeout(() => {
|
||||
timeout = null;
|
||||
func.apply(context, args)
|
||||
}, wait)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,676 @@
|
||||
<template>
|
||||
<view class="uni-easyinput" :class="{ 'uni-easyinput-error': msg }" :style="boxStyle">
|
||||
<view class="uni-easyinput__content" :class="inputContentClass" :style="inputContentStyle">
|
||||
<uni-icons v-if="prefixIcon" class="content-clear-icon" :type="prefixIcon" color="#c0c4cc" @click="onClickIcon('prefix')" size="22"></uni-icons>
|
||||
<slot name="left">
|
||||
</slot>
|
||||
<!-- #ifdef MP-ALIPAY -->
|
||||
<textarea :enableNative="enableNative" v-if="type === 'textarea'" class="uni-easyinput__content-textarea" :class="{ 'input-padding': inputBorder }" :name="name" :value="val" :placeholder="placeholder" :placeholderStyle="placeholderStyle" :disabled="disabled" placeholder-class="uni-easyinput__placeholder-class" :maxlength="inputMaxlength" :focus="focused" :autoHeight="autoHeight" :cursor-spacing="cursorSpacing" :adjust-position="adjustPosition" @input="onInput" @blur="_Blur" @focus="_Focus" @confirm="onConfirm" @keyboardheightchange="onkeyboardheightchange"></textarea>
|
||||
<input :enableNative="enableNative" v-else :type="type === 'password' ? 'text' : type" class="uni-easyinput__content-input" :style="inputStyle" :name="name" :value="val" :password="!showPassword && type === 'password'" :placeholder="placeholder" :placeholderStyle="placeholderStyle" placeholder-class="uni-easyinput__placeholder-class" :disabled="disabled" :maxlength="inputMaxlength" :focus="focused" :confirmType="confirmType" :cursor-spacing="cursorSpacing" :adjust-position="adjustPosition" @focus="_Focus" @blur="_Blur" @input="onInput" @confirm="onConfirm" @keyboardheightchange="onkeyboardheightchange" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-ALIPAY -->
|
||||
<textarea v-if="type === 'textarea'" class="uni-easyinput__content-textarea" :class="{ 'input-padding': inputBorder }" :name="name" :value="val" :placeholder="placeholder" :placeholderStyle="placeholderStyle" :disabled="disabled" placeholder-class="uni-easyinput__placeholder-class" :maxlength="inputMaxlength" :focus="focused" :autoHeight="autoHeight" :cursor-spacing="cursorSpacing" :adjust-position="adjustPosition" @input="onInput" @blur="_Blur" @focus="_Focus" @confirm="onConfirm" @keyboardheightchange="onkeyboardheightchange"></textarea>
|
||||
<input v-else :type="type === 'password' ? 'text' : type" class="uni-easyinput__content-input" :style="inputStyle" :name="name" :value="val" :password="!showPassword && type === 'password'" :placeholder="placeholder" :placeholderStyle="placeholderStyle" placeholder-class="uni-easyinput__placeholder-class" :disabled="disabled" :maxlength="inputMaxlength" :focus="focused" :confirmType="confirmType" :cursor-spacing="cursorSpacing" :adjust-position="adjustPosition" @focus="_Focus" @blur="_Blur" @input="onInput" @confirm="onConfirm" @keyboardheightchange="onkeyboardheightchange" />
|
||||
<!-- #endif -->
|
||||
|
||||
<template v-if="type === 'password' && passwordIcon">
|
||||
<!-- 开启密码时显示小眼睛 -->
|
||||
<uni-icons v-if="isVal" class="content-clear-icon" :class="{ 'is-textarea-icon': type === 'textarea' }" :type="showPassword ? 'eye-slash-filled' : 'eye-filled'" :size="22" :color="focusShow ? primaryColor : '#c0c4cc'" @click="onEyes"></uni-icons>
|
||||
</template>
|
||||
<template v-if="suffixIcon">
|
||||
<uni-icons v-if="suffixIcon" class="content-clear-icon" :type="suffixIcon" color="#c0c4cc" @click="onClickIcon('suffix')" size="22"></uni-icons>
|
||||
</template>
|
||||
<template v-else>
|
||||
<uni-icons v-if="clearable && isVal && !disabled && type !== 'textarea'" class="content-clear-icon" :class="{ 'is-textarea-icon': type === 'textarea' }" type="clear" :size="clearSize" :color="msg ? '#dd524d' : focusShow ? primaryColor : '#c0c4cc'" @click="onClear"></uni-icons>
|
||||
</template>
|
||||
<slot name="right"></slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Easyinput 输入框
|
||||
* @description 此组件可以实现表单的输入与校验,包括 "text" 和 "textarea" 类型。
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=3455
|
||||
* @property {String} value 输入内容
|
||||
* @property {String } type 输入框的类型(默认text) password/text/textarea/..
|
||||
* @value text 文本输入键盘
|
||||
* @value textarea 多行文本输入键盘
|
||||
* @value password 密码输入键盘
|
||||
* @value number 数字输入键盘,注意iOS上app-vue弹出的数字键盘并非9宫格方式
|
||||
* @value idcard 身份证输入键盘,信、支付宝、百度、QQ小程序
|
||||
* @value digit 带小数点的数字键盘 ,App的nvue页面、微信、支付宝、百度、头条、QQ小程序支持
|
||||
* @property {Boolean} clearable 是否显示右侧清空内容的图标控件,点击可清空输入框内容(默认true)
|
||||
* @property {Boolean} autoHeight 是否自动增高输入区域,type为textarea时有效(默认true)
|
||||
* @property {String } placeholder 输入框的提示文字
|
||||
* @property {String } placeholderStyle placeholder的样式(内联样式,字符串),如"color: #ddd"
|
||||
* @property {Boolean} focus 是否自动获得焦点(默认false)
|
||||
* @property {Boolean} disabled 是否禁用(默认false)
|
||||
* @property {Number } maxlength 最大输入长度,设置为 -1 的时候不限制最大长度(默认140)
|
||||
* @property {String } confirmType 设置键盘右下角按钮的文字,仅在type="text"时生效(默认done)
|
||||
* @property {Number } clearSize 清除图标的大小,单位px(默认15)
|
||||
* @property {String} prefixIcon 输入框头部图标
|
||||
* @property {String} suffixIcon 输入框尾部图标
|
||||
* @property {String} primaryColor 设置主题色(默认#2979ff)
|
||||
* @property {Boolean} trim 是否自动去除两端的空格
|
||||
* @property {Boolean} cursorSpacing 指定光标与键盘的距离,单位 px
|
||||
* @property {Boolean} ajust-position 当键盘弹起时,是否上推内容,默认值:true
|
||||
* @value both 去除两端空格
|
||||
* @value left 去除左侧空格
|
||||
* @value right 去除右侧空格
|
||||
* @value start 去除左侧空格
|
||||
* @value end 去除右侧空格
|
||||
* @value all 去除全部空格
|
||||
* @value none 不去除空格
|
||||
* @property {Boolean} inputBorder 是否显示input输入框的边框(默认true)
|
||||
* @property {Boolean} passwordIcon type=password时是否显示小眼睛图标
|
||||
* @property {Object} styles 自定义颜色
|
||||
* @event {Function} input 输入框内容发生变化时触发
|
||||
* @event {Function} focus 输入框获得焦点时触发
|
||||
* @event {Function} blur 输入框失去焦点时触发
|
||||
* @event {Function} confirm 点击完成按钮时触发
|
||||
* @event {Function} iconClick 点击图标时触发
|
||||
* @example <uni-easyinput v-model="mobile"></uni-easyinput>
|
||||
*/
|
||||
function obj2strClass(obj) {
|
||||
let classess = '';
|
||||
for (let key in obj) {
|
||||
const val = obj[key];
|
||||
if (val) {
|
||||
classess += `${key} `;
|
||||
}
|
||||
}
|
||||
return classess;
|
||||
}
|
||||
|
||||
function obj2strStyle(obj) {
|
||||
let style = '';
|
||||
for (let key in obj) {
|
||||
const val = obj[key];
|
||||
style += `${key}:${val};`;
|
||||
}
|
||||
return style;
|
||||
}
|
||||
export default {
|
||||
name: 'uni-easyinput',
|
||||
emits: [
|
||||
'click',
|
||||
'iconClick',
|
||||
'update:modelValue',
|
||||
'input',
|
||||
'focus',
|
||||
'blur',
|
||||
'confirm',
|
||||
'clear',
|
||||
'eyes',
|
||||
'change',
|
||||
'keyboardheightchange'
|
||||
],
|
||||
model: {
|
||||
prop: 'modelValue',
|
||||
event: 'update:modelValue'
|
||||
},
|
||||
options: {
|
||||
// #ifdef MP-TOUTIAO
|
||||
virtualHost: false,
|
||||
// #endif
|
||||
// #ifndef MP-TOUTIAO
|
||||
virtualHost: true
|
||||
// #endif
|
||||
},
|
||||
inject: {
|
||||
form: {
|
||||
from: 'uniForm',
|
||||
default: null
|
||||
},
|
||||
formItem: {
|
||||
from: 'uniFormItem',
|
||||
default: null
|
||||
}
|
||||
},
|
||||
props: {
|
||||
name: String,
|
||||
value: [Number, String],
|
||||
modelValue: [Number, String],
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
autoHeight: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ' '
|
||||
},
|
||||
placeholderStyle: String,
|
||||
focus: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
maxlength: {
|
||||
type: [Number, String],
|
||||
default: 140
|
||||
},
|
||||
confirmType: {
|
||||
type: String,
|
||||
default: 'done'
|
||||
},
|
||||
clearSize: {
|
||||
type: [Number, String],
|
||||
default: 24
|
||||
},
|
||||
inputBorder: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
prefixIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
suffixIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
trim: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
cursorSpacing: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
passwordIcon: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
adjustPosition: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
primaryColor: {
|
||||
type: String,
|
||||
default: '#2979ff'
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
color: '#333',
|
||||
backgroundColor: '#fff',
|
||||
disableColor: '#F7F6F6',
|
||||
borderColor: '#e5e5e5'
|
||||
};
|
||||
}
|
||||
},
|
||||
errorMessage: {
|
||||
type: [String, Boolean],
|
||||
default: ''
|
||||
},
|
||||
// #ifdef MP-ALIPAY
|
||||
enableNative: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
focused: false,
|
||||
val: '',
|
||||
showMsg: '',
|
||||
border: false,
|
||||
isFirstBorder: false,
|
||||
showClearIcon: false,
|
||||
showPassword: false,
|
||||
focusShow: false,
|
||||
localMsg: '',
|
||||
isEnter: false // 用于判断当前是否是使用回车操作
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// 输入框内是否有值
|
||||
isVal() {
|
||||
const val = this.val;
|
||||
// fixed by mehaotian 处理值为0的情况,字符串0不在处理范围
|
||||
if (val || val === 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
msg() {
|
||||
// console.log('computed', this.form, this.formItem);
|
||||
// if (this.form) {
|
||||
// return this.errorMessage || this.formItem.errMsg;
|
||||
// }
|
||||
// TODO 处理头条 formItem 中 errMsg 不更新的问题
|
||||
return this.localMsg || this.errorMessage;
|
||||
},
|
||||
// 因为uniapp的input组件的maxlength组件必须要数值,这里转为数值,用户可以传入字符串数值
|
||||
inputMaxlength() {
|
||||
return Number(this.maxlength);
|
||||
},
|
||||
|
||||
// 处理外层样式的style
|
||||
boxStyle() {
|
||||
return `color:${
|
||||
this.inputBorder && this.msg ? '#e43d33' : this.styles.color
|
||||
};`;
|
||||
},
|
||||
// input 内容的类和样式处理
|
||||
inputContentClass() {
|
||||
return obj2strClass({
|
||||
'is-input-border': this.inputBorder,
|
||||
'is-input-error-border': this.inputBorder && this.msg,
|
||||
'is-textarea': this.type === 'textarea',
|
||||
'is-disabled': this.disabled,
|
||||
'is-focused': this.focusShow
|
||||
});
|
||||
},
|
||||
inputContentStyle() {
|
||||
const focusColor = this.focusShow ?
|
||||
this.primaryColor :
|
||||
this.styles.borderColor;
|
||||
const borderColor =
|
||||
this.inputBorder && this.msg ? '#dd524d' : focusColor;
|
||||
return obj2strStyle({
|
||||
'border-color': borderColor || '#e5e5e5',
|
||||
'background-color': this.disabled ?
|
||||
this.styles.disableColor : this.styles.backgroundColor
|
||||
});
|
||||
},
|
||||
// input右侧样式
|
||||
inputStyle() {
|
||||
const paddingRight =
|
||||
this.type === 'password' || this.clearable || this.prefixIcon ?
|
||||
'' :
|
||||
'10px';
|
||||
return obj2strStyle({
|
||||
'padding-right': paddingRight,
|
||||
'padding-left': this.prefixIcon ? '' : '10px'
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(newVal) {
|
||||
// fix by mehaotian 解决 值为null的情况下,input报错的bug
|
||||
if (newVal === null) {
|
||||
this.val = '';
|
||||
return
|
||||
}
|
||||
this.val = newVal;
|
||||
},
|
||||
modelValue(newVal) {
|
||||
if (newVal === null) {
|
||||
this.val = '';
|
||||
return
|
||||
}
|
||||
this.val = newVal;
|
||||
},
|
||||
focus(newVal) {
|
||||
this.$nextTick(() => {
|
||||
this.focused = this.focus;
|
||||
this.focusShow = this.focus;
|
||||
});
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
// TODO 处理头条vue3 computed 不监听 inject 更改的问题(formItem.errMsg)
|
||||
if (this.form && this.formItem) {
|
||||
this.$watch('formItem.errMsg', newVal => {
|
||||
this.localMsg = newVal;
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.focused = this.focus;
|
||||
this.focusShow = this.focus;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 初始化变量值
|
||||
*/
|
||||
init() {
|
||||
if (this.value || this.value === 0) {
|
||||
this.val = this.value;
|
||||
} else if (
|
||||
this.modelValue ||
|
||||
this.modelValue === 0 ||
|
||||
this.modelValue === ''
|
||||
) {
|
||||
this.val = this.modelValue;
|
||||
} else {
|
||||
// fix by ht 如果初始值为null,则input报错,待框架修复
|
||||
this.val = '';
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 点击图标时触发
|
||||
* @param {Object} type
|
||||
*/
|
||||
onClickIcon(type) {
|
||||
this.$emit('iconClick', type);
|
||||
},
|
||||
|
||||
/**
|
||||
* 显示隐藏内容,密码框时生效
|
||||
*/
|
||||
onEyes() {
|
||||
this.showPassword = !this.showPassword;
|
||||
this.$emit('eyes', this.showPassword);
|
||||
},
|
||||
|
||||
/**
|
||||
* 输入时触发
|
||||
* @param {Object} event
|
||||
*/
|
||||
onInput(event) {
|
||||
let value = event.detail.value;
|
||||
// 判断是否去除空格
|
||||
if (this.trim) {
|
||||
if (typeof this.trim === 'boolean' && this.trim) {
|
||||
value = this.trimStr(value);
|
||||
}
|
||||
if (typeof this.trim === 'string') {
|
||||
value = this.trimStr(value, this.trim);
|
||||
}
|
||||
}
|
||||
if (this.errMsg) this.errMsg = '';
|
||||
this.val = value;
|
||||
// TODO 兼容 vue2
|
||||
this.$emit('input', value);
|
||||
// TODO 兼容 vue3
|
||||
this.$emit('update:modelValue', value);
|
||||
},
|
||||
|
||||
/**
|
||||
* 外部调用方法
|
||||
* 获取焦点时触发
|
||||
* @param {Object} event
|
||||
*/
|
||||
onFocus() {
|
||||
this.$nextTick(() => {
|
||||
this.focused = true;
|
||||
});
|
||||
this.$emit('focus', null);
|
||||
},
|
||||
|
||||
_Focus(event) {
|
||||
this.focusShow = true;
|
||||
this.$emit('focus', event);
|
||||
},
|
||||
|
||||
/**
|
||||
* 外部调用方法
|
||||
* 失去焦点时触发
|
||||
* @param {Object} event
|
||||
*/
|
||||
onBlur() {
|
||||
this.focused = false;
|
||||
this.$emit('blur', null);
|
||||
},
|
||||
_Blur(event) {
|
||||
let value = event.detail.value;
|
||||
this.focusShow = false;
|
||||
this.$emit('blur', event);
|
||||
// 根据类型返回值,在event中获取的值理论上讲都是string
|
||||
if (this.isEnter === false) {
|
||||
this.$emit('change', this.val);
|
||||
}
|
||||
// 失去焦点时参与表单校验
|
||||
if (this.form && this.formItem) {
|
||||
const { validateTrigger } = this.form;
|
||||
if (validateTrigger === 'blur') {
|
||||
this.formItem.onFieldChange();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 按下键盘的发送键
|
||||
* @param {Object} e
|
||||
*/
|
||||
onConfirm(e) {
|
||||
this.$emit('confirm', this.val);
|
||||
this.isEnter = true;
|
||||
this.$emit('change', this.val);
|
||||
this.$nextTick(() => {
|
||||
this.isEnter = false;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 清理内容
|
||||
* @param {Object} event
|
||||
*/
|
||||
onClear(event) {
|
||||
this.val = '';
|
||||
// TODO 兼容 vue2
|
||||
this.$emit('input', '');
|
||||
// TODO 兼容 vue2
|
||||
// TODO 兼容 vue3
|
||||
this.$emit('update:modelValue', '');
|
||||
// 点击叉号触发
|
||||
this.$emit('clear');
|
||||
},
|
||||
|
||||
/**
|
||||
* 键盘高度发生变化的时候触发此事件
|
||||
* 兼容性:微信小程序2.7.0+、App 3.1.0+
|
||||
* @param {Object} event
|
||||
*/
|
||||
onkeyboardheightchange(event) {
|
||||
this.$emit('keyboardheightchange', event);
|
||||
},
|
||||
|
||||
/**
|
||||
* 去除空格
|
||||
*/
|
||||
trimStr(str, pos = 'both') {
|
||||
if (pos === 'both') {
|
||||
return str.trim();
|
||||
} else if (pos === 'left') {
|
||||
return str.trimLeft();
|
||||
} else if (pos === 'right') {
|
||||
return str.trimRight();
|
||||
} else if (pos === 'start') {
|
||||
return str.trimStart();
|
||||
} else if (pos === 'end') {
|
||||
return str.trimEnd();
|
||||
} else if (pos === 'all') {
|
||||
return str.replace(/\s+/g, '');
|
||||
} else if (pos === 'none') {
|
||||
return str;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
$uni-error: #e43d33;
|
||||
$uni-border-1: #dcdfe6 !default;
|
||||
|
||||
.uni-easyinput {
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.uni-easyinput__content {
|
||||
flex: 1;
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
// min-height: 36px;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
// 处理border动画刚开始显示黑色的问题
|
||||
border-color: #fff;
|
||||
transition-property: border-color;
|
||||
transition-duration: 0.3s;
|
||||
}
|
||||
|
||||
.uni-easyinput__content-input {
|
||||
/* #ifndef APP-NVUE */
|
||||
width: auto;
|
||||
/* #endif */
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
line-height: 1;
|
||||
font-size: 14px;
|
||||
height: 35px;
|
||||
// min-height: 36px;
|
||||
|
||||
/*ifdef H5*/
|
||||
& ::-ms-reveal {
|
||||
display: none;
|
||||
}
|
||||
|
||||
& ::-ms-clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
& ::-o-clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*endif*/
|
||||
}
|
||||
|
||||
.uni-easyinput__placeholder-class {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
// font-weight: 200;
|
||||
}
|
||||
|
||||
.is-textarea {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.is-textarea-icon {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.uni-easyinput__content-textarea {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
line-height: 1.5;
|
||||
font-size: 14px;
|
||||
margin: 6px;
|
||||
margin-left: 0;
|
||||
height: 80px;
|
||||
min-height: 80px;
|
||||
/* #ifndef APP-NVUE */
|
||||
min-height: 80px;
|
||||
width: auto;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.input-padding {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.content-clear-icon {
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.label-icon {
|
||||
margin-right: 5px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
// 显示边框
|
||||
.is-input-border {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
border: 1px solid $uni-border-1;
|
||||
border-radius: 4px;
|
||||
/* #ifdef MP-ALIPAY */
|
||||
overflow: hidden;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-error-message {
|
||||
position: absolute;
|
||||
bottom: -17px;
|
||||
left: 0;
|
||||
line-height: 12px;
|
||||
color: $uni-error;
|
||||
font-size: 12px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.uni-error-msg--boeder {
|
||||
position: relative;
|
||||
bottom: 0;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.is-input-error-border {
|
||||
border-color: $uni-error;
|
||||
|
||||
.uni-easyinput__placeholder-class {
|
||||
color: mix(#fff, $uni-error, 50%);
|
||||
}
|
||||
}
|
||||
|
||||
.uni-easyinput--border {
|
||||
margin-bottom: 0;
|
||||
padding: 10px 15px;
|
||||
// padding-bottom: 0;
|
||||
border-top: 1px #eee solid;
|
||||
}
|
||||
|
||||
.uni-easyinput-error {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.is-first-border {
|
||||
/* #ifndef APP-NVUE */
|
||||
border: none;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
border-width: 0;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.is-disabled {
|
||||
background-color: #f7f6f6;
|
||||
color: #d5d5d5;
|
||||
|
||||
.uni-easyinput__placeholder-class {
|
||||
color: #d5d5d5;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
88
uni_modules/uni-easyinput/package.json
Normal file
88
uni_modules/uni-easyinput/package.json
Normal file
@ -0,0 +1,88 @@
|
||||
{
|
||||
"id": "uni-easyinput",
|
||||
"displayName": "uni-easyinput 增强输入框",
|
||||
"version": "1.1.19",
|
||||
"description": "Easyinput 组件是对原生input组件的增强",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"uniui",
|
||||
"input",
|
||||
"uni-easyinput",
|
||||
"输入框"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uni-scss",
|
||||
"uni-icons"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y",
|
||||
"alipay": "n"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
uni_modules/uni-easyinput/readme.md
Normal file
11
uni_modules/uni-easyinput/readme.md
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
|
||||
### Easyinput 增强输入框
|
||||
> **组件名:uni-easyinput**
|
||||
> 代码块: `uEasyinput`
|
||||
|
||||
|
||||
easyinput 组件是对原生input组件的增强 ,是专门为配合表单组件[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)而设计的,easyinput 内置了边框,图标等,同时包含 input 所有功能
|
||||
|
||||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-easyinput)
|
||||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
39
uni_modules/uni-number-box/changelog.md
Normal file
39
uni_modules/uni-number-box/changelog.md
Normal file
@ -0,0 +1,39 @@
|
||||
## 1.2.8(2024-04-26)
|
||||
- 修复 在vue2下H5黑边的bug
|
||||
## 1.2.7(2024-04-26)
|
||||
- 修复 在vue2手动输入后失焦导致清空数值的严重bug
|
||||
## 1.2.6(2024-02-22)
|
||||
- 新增 设置宽度属性width(单位:px)
|
||||
## 1.2.5(2024-02-21)
|
||||
- 修复 step步长小于1时,键盘类型为number的bug
|
||||
## 1.2.4(2024-02-02)
|
||||
- 修复 加减号垂直位置偏移样式问题
|
||||
## 1.2.3(2023-05-23)
|
||||
- 更新示例工程
|
||||
## 1.2.2(2023-05-08)
|
||||
- 修复 change 事件执行顺序错误的问题
|
||||
## 1.2.1(2021-11-22)
|
||||
- 修复 vue3中某些scss变量无法找到的问题
|
||||
## 1.2.0(2021-11-19)
|
||||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-number-box](https://uniapp.dcloud.io/component/uniui/uni-number-box)
|
||||
## 1.1.2(2021-11-09)
|
||||
- 新增 提供组件设计资源,组件样式调整
|
||||
## 1.1.1(2021-07-30)
|
||||
- 优化 vue3下事件警告的问题
|
||||
## 1.1.0(2021-07-13)
|
||||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||
## 1.0.7(2021-05-12)
|
||||
- 新增 组件示例地址
|
||||
## 1.0.6(2021-04-20)
|
||||
- 修复 uni-number-box 浮点数运算不精确的 bug
|
||||
- 修复 uni-number-box change 事件触发不正确的 bug
|
||||
- 新增 uni-number-box v-model 双向绑定
|
||||
## 1.0.5(2021-02-05)
|
||||
- 调整为uni_modules目录规范
|
||||
|
||||
## 1.0.7(2021-02-05)
|
||||
- 调整为uni_modules目录规范
|
||||
- 新增 支持 v-model
|
||||
- 新增 支持 focus、blur 事件
|
||||
- 新增 支持 PC 端
|
@ -0,0 +1,232 @@
|
||||
<template>
|
||||
<view class="uni-numbox">
|
||||
<view @click="_calcValue('minus')" class="uni-numbox__minus uni-numbox-btns" :style="{background}">
|
||||
<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue <= min || disabled }"
|
||||
:style="{color}">-</text>
|
||||
</view>
|
||||
<input :disabled="disabled" @focus="_onFocus" @blur="_onBlur" class="uni-numbox__value"
|
||||
:type="step<1?'digit':'number'" v-model="inputValue" :style="{background, color, width:widthWithPx}" />
|
||||
<view @click="_calcValue('plus')" class="uni-numbox__plus uni-numbox-btns" :style="{background}">
|
||||
<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue >= max || disabled }"
|
||||
:style="{color}">+</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
/**
|
||||
* NumberBox 数字输入框
|
||||
* @description 带加减按钮的数字输入框
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=31
|
||||
* @property {Number} value 输入框当前值
|
||||
* @property {Number} min 最小值
|
||||
* @property {Number} max 最大值
|
||||
* @property {Number} step 每次点击改变的间隔大小
|
||||
* @property {String} background 背景色
|
||||
* @property {String} color 字体颜色(前景色)
|
||||
* @property {Number} width 输入框宽度(单位:px)
|
||||
* @property {Boolean} disabled = [true|false] 是否为禁用状态
|
||||
* @event {Function} change 输入框值改变时触发的事件,参数为输入框当前的 value
|
||||
* @event {Function} focus 输入框聚焦时触发的事件,参数为 event 对象
|
||||
* @event {Function} blur 输入框失焦时触发的事件,参数为 event 对象
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: "UniNumberBox",
|
||||
emits: ['change', 'input', 'update:modelValue', 'blur', 'focus'],
|
||||
props: {
|
||||
value: {
|
||||
type: [Number, String],
|
||||
default: 1
|
||||
},
|
||||
modelValue: {
|
||||
type: [Number, String],
|
||||
default: 1
|
||||
},
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
background: {
|
||||
type: String,
|
||||
default: '#f5f5f5'
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#333'
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
default: 40,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
inputValue: 0
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
this.inputValue = +val;
|
||||
},
|
||||
modelValue(val) {
|
||||
this.inputValue = +val;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
widthWithPx() {
|
||||
return this.width + 'px';
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.value === 1) {
|
||||
this.inputValue = +this.modelValue;
|
||||
}
|
||||
if (this.modelValue === 1) {
|
||||
this.inputValue = +this.value;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
_calcValue(type) {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
const scale = this._getDecimalScale();
|
||||
let value = this.inputValue * scale;
|
||||
let step = this.step * scale;
|
||||
if (type === "minus") {
|
||||
value -= step;
|
||||
if (value < (this.min * scale)) {
|
||||
return;
|
||||
}
|
||||
if (value > (this.max * scale)) {
|
||||
value = this.max * scale
|
||||
}
|
||||
}
|
||||
|
||||
if (type === "plus") {
|
||||
value += step;
|
||||
if (value > (this.max * scale)) {
|
||||
return;
|
||||
}
|
||||
if (value < (this.min * scale)) {
|
||||
value = this.min * scale
|
||||
}
|
||||
}
|
||||
|
||||
this.inputValue = (value / scale).toFixed(String(scale).length - 1);
|
||||
// TODO vue2 兼容
|
||||
this.$emit("input", +this.inputValue);
|
||||
// TODO vue3 兼容
|
||||
this.$emit("update:modelValue", +this.inputValue);
|
||||
this.$emit("change", +this.inputValue);
|
||||
},
|
||||
_getDecimalScale() {
|
||||
|
||||
let scale = 1;
|
||||
// 浮点型
|
||||
if (~~this.step !== this.step) {
|
||||
scale = Math.pow(10, String(this.step).split(".")[1].length);
|
||||
}
|
||||
return scale;
|
||||
},
|
||||
_onBlur(event) {
|
||||
this.$emit('blur', event)
|
||||
let value = event.detail.value;
|
||||
if (isNaN(value)) {
|
||||
this.inputValue = this.value;
|
||||
return;
|
||||
}
|
||||
value = +value;
|
||||
if (value > this.max) {
|
||||
value = this.max;
|
||||
} else if (value < this.min) {
|
||||
value = this.min;
|
||||
}
|
||||
const scale = this._getDecimalScale();
|
||||
this.inputValue = value.toFixed(String(scale).length - 1);
|
||||
this.$emit("input", +this.inputValue);
|
||||
this.$emit("update:modelValue", +this.inputValue);
|
||||
this.$emit("change", +this.inputValue);
|
||||
},
|
||||
_onFocus(event) {
|
||||
this.$emit('focus', event)
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
$box-height: 26px;
|
||||
$bg: #f5f5f5;
|
||||
$br: 2px;
|
||||
$color: #333;
|
||||
|
||||
.uni-numbox {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.uni-numbox-btns {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 8px;
|
||||
background-color: $bg;
|
||||
/* #ifdef H5 */
|
||||
cursor: pointer;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-numbox__value {
|
||||
margin: 0 2px;
|
||||
background-color: $bg;
|
||||
width: 40px;
|
||||
height: $box-height;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
border-width: 0;
|
||||
color: $color;
|
||||
}
|
||||
|
||||
.uni-numbox__minus {
|
||||
border-top-left-radius: $br;
|
||||
border-bottom-left-radius: $br;
|
||||
}
|
||||
|
||||
.uni-numbox__plus {
|
||||
border-top-right-radius: $br;
|
||||
border-bottom-right-radius: $br;
|
||||
}
|
||||
|
||||
.uni-numbox--text {
|
||||
// fix nvue
|
||||
line-height: 20px;
|
||||
margin-bottom: 2px;
|
||||
font-size: 20px;
|
||||
font-weight: 300;
|
||||
color: $color;
|
||||
}
|
||||
|
||||
.uni-numbox .uni-numbox--disabled {
|
||||
color: #c0c0c0 !important;
|
||||
/* #ifdef H5 */
|
||||
cursor: not-allowed;
|
||||
/* #endif */
|
||||
}
|
||||
</style>
|
83
uni_modules/uni-number-box/package.json
Normal file
83
uni_modules/uni-number-box/package.json
Normal file
@ -0,0 +1,83 @@
|
||||
{
|
||||
"id": "uni-number-box",
|
||||
"displayName": "uni-number-box 数字输入框",
|
||||
"version": "1.2.8",
|
||||
"description": "NumberBox 带加减按钮的数字输入框组件,用户可以控制每次点击增加的数值,支持小数。",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"uniui",
|
||||
"数字输入框"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": ["uni-scss"],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y",
|
||||
"alipay": "n"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
13
uni_modules/uni-number-box/readme.md
Normal file
13
uni_modules/uni-number-box/readme.md
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
|
||||
## NumberBox 数字输入框
|
||||
> **组件名:uni-number-box**
|
||||
> 代码块: `uNumberBox`
|
||||
|
||||
|
||||
带加减按钮的数字输入框。
|
||||
|
||||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-number-box)
|
||||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||
|
||||
|
403
utils/util.js
403
utils/util.js
@ -1,191 +1,216 @@
|
||||
// 验证手机号码
|
||||
export function validatePhoneNumber(data) {
|
||||
var reg = /^1[3-9]\d{9}$/
|
||||
return reg.test(data)
|
||||
}
|
||||
|
||||
export function lastfour(num) {
|
||||
// 截取后4位
|
||||
let lastFourDigits = num.slice(-4);
|
||||
return lastFourDigits
|
||||
}
|
||||
|
||||
export function isValidBankCard(cardNumber) {
|
||||
const reg = /^(\d{16}|\d{19})$/
|
||||
// 使用正则表达式测试银行卡号
|
||||
return reg.test(cardNumber)
|
||||
}
|
||||
|
||||
export function formatTime(time) {
|
||||
if (typeof time !== 'number' || time < 0) {
|
||||
return time
|
||||
}
|
||||
|
||||
var hour = parseInt(time / 3600)
|
||||
time = time % 3600
|
||||
var minute = parseInt(time / 60)
|
||||
time = time % 60
|
||||
var second = time
|
||||
|
||||
return ([hour, minute, second]).map(function(n) {
|
||||
n = n.toString()
|
||||
return n[1] ? n : '0' + n
|
||||
}).join(':')
|
||||
}
|
||||
|
||||
export function formatDateTime(date, fmt = 'yyyy-MM-dd hh:mm:ss') {
|
||||
if(!date) {
|
||||
return ''
|
||||
}
|
||||
if (typeof (date) === 'number') {
|
||||
date = new Date(date)
|
||||
}
|
||||
var o = {
|
||||
"M+": date.getMonth() + 1, //月份
|
||||
"d+": date.getDate(), //日
|
||||
"h+": date.getHours(), //小时
|
||||
"m+": date.getMinutes(), //分
|
||||
"s+": date.getSeconds(), //秒
|
||||
"q+": Math.floor((date.getMonth() + 3) / 3), //季度
|
||||
"S": date.getMilliseconds() //毫秒
|
||||
}
|
||||
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length))
|
||||
for (var k in o)
|
||||
if (new RegExp("(" + k + ")").test(fmt))
|
||||
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)))
|
||||
return fmt
|
||||
}
|
||||
|
||||
export function formatLocation(longitude, latitude) {
|
||||
if (typeof longitude === 'string' && typeof latitude === 'string') {
|
||||
longitude = parseFloat(longitude)
|
||||
latitude = parseFloat(latitude)
|
||||
}
|
||||
|
||||
longitude = longitude.toFixed(2)
|
||||
latitude = latitude.toFixed(2)
|
||||
|
||||
return {
|
||||
longitude: longitude.toString().split('.'),
|
||||
latitude: latitude.toString().split('.')
|
||||
}
|
||||
}
|
||||
|
||||
var dateUtils = {
|
||||
UNITS: {
|
||||
'年': 31557600000,
|
||||
'月': 2629800000,
|
||||
'天': 86400000,
|
||||
'小时': 3600000,
|
||||
'分钟': 60000,
|
||||
'秒': 1000
|
||||
},
|
||||
humanize: function(milliseconds) {
|
||||
var humanize = '';
|
||||
for (var key in this.UNITS) {
|
||||
if (milliseconds >= this.UNITS[key]) {
|
||||
humanize = Math.floor(milliseconds / this.UNITS[key]) + key + '前';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return humanize || '刚刚';
|
||||
},
|
||||
format: function(dateStr) {
|
||||
var date = this.parse(dateStr)
|
||||
var diff = Date.now() - date.getTime();
|
||||
if (diff < this.UNITS['天']) {
|
||||
return this.humanize(diff);
|
||||
}
|
||||
var _format = function(number) {
|
||||
return (number < 10 ? ('0' + number) : number);
|
||||
};
|
||||
return date.getFullYear() + '/' + _format(date.getMonth() + 1) + '/' + _format(date.getDate()) + '-' +
|
||||
_format(date.getHours()) + ':' + _format(date.getMinutes());
|
||||
},
|
||||
parse: function(str) { //将"yyyy-mm-dd HH:MM:ss"格式的字符串,转化为一个Date对象
|
||||
var a = str.split(/[^0-9]/);
|
||||
return new Date(a[0], a[1] - 1, a[2], a[3], a[4], a[5]);
|
||||
}
|
||||
};
|
||||
|
||||
// 返回上一页
|
||||
export function prePage(page = null){
|
||||
let pages = getCurrentPages();
|
||||
//console.log('pages:',pages);
|
||||
let prePage = pages[pages.length - 2];
|
||||
if (page !== null) {
|
||||
prePage = pages[page];
|
||||
}
|
||||
// #ifdef H5
|
||||
//return prePage;
|
||||
// #endif
|
||||
return prePage;
|
||||
}
|
||||
|
||||
export function kmUnit(m){
|
||||
var v;
|
||||
if(typeof m === 'number' && !isNaN(m)){
|
||||
if (m >= 1000) {
|
||||
v = (m / 1000).toFixed(2) + 'km'
|
||||
} else {
|
||||
v = m + 'm'
|
||||
}
|
||||
}else{
|
||||
v = '0m'
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
export function isWeixin() {
|
||||
if (navigator && navigator.userAgent && navigator.userAgent.toLowerCase().indexOf('micromessenger') !== -1) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 验证手机号码
|
||||
export function validatePhoneNumber(data) {
|
||||
var reg = /^1[3-9]\d{9}$/
|
||||
return reg.test(data)
|
||||
}
|
||||
|
||||
export function lastfour(num) {
|
||||
// 截取后4位
|
||||
let lastFourDigits = num.slice(-4);
|
||||
return lastFourDigits
|
||||
}
|
||||
|
||||
export function isValidBankCard(cardNumber) {
|
||||
const reg = /^(\d{16}|\d{19})$/
|
||||
// 使用正则表达式测试银行卡号
|
||||
return reg.test(cardNumber)
|
||||
}
|
||||
|
||||
export function formatTime(time) {
|
||||
if (typeof time !== 'number' || time < 0) {
|
||||
return time
|
||||
}
|
||||
|
||||
var hour = parseInt(time / 3600)
|
||||
time = time % 3600
|
||||
var minute = parseInt(time / 60)
|
||||
time = time % 60
|
||||
var second = time
|
||||
|
||||
return ([hour, minute, second]).map(function(n) {
|
||||
n = n.toString()
|
||||
return n[1] ? n : '0' + n
|
||||
}).join(':')
|
||||
}
|
||||
|
||||
export function formatDateTime(date, fmt = 'yyyy-MM-dd hh:mm:ss') {
|
||||
if (!date) {
|
||||
return ''
|
||||
}
|
||||
if (typeof(date) === 'number') {
|
||||
date = new Date(date)
|
||||
}
|
||||
var o = {
|
||||
"M+": date.getMonth() + 1, //月份
|
||||
"d+": date.getDate(), //日
|
||||
"h+": date.getHours(), //小时
|
||||
"m+": date.getMinutes(), //分
|
||||
"s+": date.getSeconds(), //秒
|
||||
"q+": Math.floor((date.getMonth() + 3) / 3), //季度
|
||||
"S": date.getMilliseconds() //毫秒
|
||||
}
|
||||
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length))
|
||||
for (var k in o)
|
||||
if (new RegExp("(" + k + ")").test(fmt))
|
||||
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)))
|
||||
return fmt
|
||||
}
|
||||
|
||||
export function timestampToDate(timestamp) {
|
||||
let date = new Date(timestamp);
|
||||
let year = date.getFullYear();
|
||||
let month = ("0" + (date.getMonth() + 1)).slice(-2);
|
||||
let day = ("0" + date.getDate()).slice(-2);
|
||||
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
|
||||
export function formatLocation(longitude, latitude) {
|
||||
if (typeof longitude === 'string' && typeof latitude === 'string') {
|
||||
longitude = parseFloat(longitude)
|
||||
latitude = parseFloat(latitude)
|
||||
}
|
||||
|
||||
longitude = longitude.toFixed(2)
|
||||
latitude = latitude.toFixed(2)
|
||||
|
||||
return {
|
||||
longitude: longitude.toString().split('.'),
|
||||
latitude: latitude.toString().split('.')
|
||||
}
|
||||
}
|
||||
|
||||
var dateUtils = {
|
||||
UNITS: {
|
||||
'年': 31557600000,
|
||||
'月': 2629800000,
|
||||
'天': 86400000,
|
||||
'小时': 3600000,
|
||||
'分钟': 60000,
|
||||
'秒': 1000
|
||||
},
|
||||
humanize: function(milliseconds) {
|
||||
var humanize = '';
|
||||
for (var key in this.UNITS) {
|
||||
if (milliseconds >= this.UNITS[key]) {
|
||||
humanize = Math.floor(milliseconds / this.UNITS[key]) + key + '前';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return humanize || '刚刚';
|
||||
},
|
||||
format: function(dateStr) {
|
||||
var date = this.parse(dateStr)
|
||||
var diff = Date.now() - date.getTime();
|
||||
if (diff < this.UNITS['天']) {
|
||||
return this.humanize(diff);
|
||||
}
|
||||
var _format = function(number) {
|
||||
return (number < 10 ? ('0' + number) : number);
|
||||
};
|
||||
return date.getFullYear() + '/' + _format(date.getMonth() + 1) + '/' + _format(date.getDate()) + '-' +
|
||||
_format(date.getHours()) + ':' + _format(date.getMinutes());
|
||||
},
|
||||
parse: function(str) { //将"yyyy-mm-dd HH:MM:ss"格式的字符串,转化为一个Date对象
|
||||
var a = str.split(/[^0-9]/);
|
||||
return new Date(a[0], a[1] - 1, a[2], a[3], a[4], a[5]);
|
||||
}
|
||||
};
|
||||
|
||||
// 返回上一页
|
||||
export function prePage(page = null) {
|
||||
let pages = getCurrentPages();
|
||||
//console.log('pages:',pages);
|
||||
let prePage = pages[pages.length - 2];
|
||||
if (page !== null) {
|
||||
prePage = pages[page];
|
||||
}
|
||||
// #ifdef H5
|
||||
//return prePage;
|
||||
// #endif
|
||||
return prePage;
|
||||
}
|
||||
|
||||
export function kmUnit(m) {
|
||||
var v;
|
||||
if (typeof m === 'number' && !isNaN(m)) {
|
||||
if (m >= 1000) {
|
||||
v = (m / 1000).toFixed(2) + 'km'
|
||||
} else {
|
||||
v = m + 'm'
|
||||
}
|
||||
} else {
|
||||
v = '0m'
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
export function isWeixin() {
|
||||
if (navigator && navigator.userAgent && navigator.userAgent.toLowerCase().indexOf('micromessenger') !== -1) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export function parseQuery() {
|
||||
let res = {}
|
||||
|
||||
// #ifdef H5
|
||||
const query = (location.href.split('?')[1] || '').trim().replace(/^(\?|#|&)/, '')
|
||||
|
||||
if (!query) {
|
||||
return res
|
||||
}
|
||||
|
||||
query.split('&').forEach(param => {
|
||||
const parts = param.replace(/\+/g, ' ').split('=')
|
||||
const key = decodeURIComponent(parts.shift())
|
||||
const val = parts.length > 0 ? decodeURIComponent(parts.join('=')) : null
|
||||
|
||||
if (res[key] === undefined) {
|
||||
res[key] = val
|
||||
} else if (Array.isArray(res[key])) {
|
||||
res[key].push(val)
|
||||
} else {
|
||||
res[key] = [res[key], val]
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
var pages = getCurrentPages() //获取加载的页面
|
||||
var currentPage = pages[pages.length - 1] //获取当前页面的对象
|
||||
var url = currentPage.route //当前页面url
|
||||
res = currentPage.options //如果要获取url中所带的参数可以查看options
|
||||
// #endif
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
export function urlDecode(query) {
|
||||
if (!query) return null
|
||||
let hash, object = {}
|
||||
const hashes = query.slice(query.indexOf('?') + 1).split('&')
|
||||
for (let i = 0; i < hashes.length; i++) {
|
||||
hash = hashes[i].split('=')
|
||||
object[hash[0]] = hash[1]
|
||||
}
|
||||
|
||||
return object;
|
||||
let res = {}
|
||||
|
||||
// #ifdef H5
|
||||
const query = (location.href.split('?')[1] || '').trim().replace(/^(\?|#|&)/, '')
|
||||
|
||||
if (!query) {
|
||||
return res
|
||||
}
|
||||
|
||||
query.split('&').forEach(param => {
|
||||
const parts = param.replace(/\+/g, ' ').split('=')
|
||||
const key = decodeURIComponent(parts.shift())
|
||||
const val = parts.length > 0 ? decodeURIComponent(parts.join('=')) : null
|
||||
|
||||
if (res[key] === undefined) {
|
||||
res[key] = val
|
||||
} else if (Array.isArray(res[key])) {
|
||||
res[key].push(val)
|
||||
} else {
|
||||
res[key] = [res[key], val]
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
var pages = getCurrentPages() //获取加载的页面
|
||||
var currentPage = pages[pages.length - 1] //获取当前页面的对象
|
||||
var url = currentPage.route //当前页面url
|
||||
res = currentPage.options //如果要获取url中所带的参数可以查看options
|
||||
// #endif
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
export function urlDecode(query) {
|
||||
if (!query) return null
|
||||
let hash, object = {}
|
||||
const hashes = query.slice(query.indexOf('?') + 1).split('&')
|
||||
for (let i = 0; i < hashes.length; i++) {
|
||||
hash = hashes[i].split('=')
|
||||
object[hash[0]] = hash[1]
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
//根据名称返回是图片还是pdf
|
||||
export function getFileType(filename) {
|
||||
const lowercaseFilename = filename.toLowerCase();
|
||||
|
||||
if (lowercaseFilename.endsWith('.jpg') || lowercaseFilename.endsWith('.jpeg') || lowercaseFilename.endsWith(
|
||||
'.png') || lowercaseFilename.endsWith('.gif')) {
|
||||
return 'image';
|
||||
} else if (lowercaseFilename.endsWith('.pdf')) {
|
||||
return 'pdf';
|
||||
} else if (lowercaseFilename.endsWith('.xls') || lowercaseFilename.endsWith('.xlsx')) {
|
||||
return 'excel';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user