Commit 8495761ef179cc8229081518bebd3e54050c5805

Authored by lxf
1 parent c9a5591a

feat: 飞牛小程序初试版本

Showing 64 changed files with 6267 additions and 645 deletions   Show diff stats
1 /unpackage 1 /unpackage
2 /node_modules 2 /node_modules
3 -.DS_Store  
4 \ No newline at end of file 3 \ No newline at end of file
  4 +.DS_Store
  5 +.idea
.prettierignore 0 → 100644
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +/dist/*
  2 +.local
  3 +.hbuilderx
  4 +common
  5 +components
  6 +uni_modules
  7 +mixins
  8 +iconfont
  9 +/node_modules/**
  10 +
  11 +**/*.svg
  12 +**/*.sh
  13 +
  14 +/public/*
  15 +stats.html
.prettierrc.js 0 → 100644
@@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
  1 +module.exports = {
  2 + // 行尾换行方式
  3 + endOfLine: 'lf',
  4 + // Tab空格数
  5 + tabWidth: 2,
  6 + // 使用Tab缩进
  7 + useTabs: false,
  8 + // 换行字符数
  9 + printWidth: 190,
  10 + // 开启 eslint 支持
  11 + eslintIntegration: true,
  12 + // 字符串单引号
  13 + singleQuote: true,
  14 + // 行尾分号
  15 + semi: true,
  16 + // 尾逗号 none es5 all
  17 + trailingComma: 'all',
  18 + // 大括号空格
  19 + bracketSpacing: true,
  20 + // 箭头函数参数只有一个时省略小括号
  21 + arrowParens: 'avoid',
  22 + // 标签闭合位置对齐
  23 + bracketSpacing: true,
  24 + ignorePath: '.prettierignore'
  25 +};
@@ -8,7 +8,7 @@ import { onAuthAppBack, openAuthMiniApp } from 'dingtalk-design-libs/biz/openAut @@ -8,7 +8,7 @@ import { onAuthAppBack, openAuthMiniApp } from 'dingtalk-design-libs/biz/openAut
8 8
9 export default { 9 export default {
10 computed: { 10 computed: {
11 - ...mapState(['authed','userInfo']), 11 + ...mapState(['authed', 'userInfo']),
12 }, 12 },
13 onLaunch(options) { 13 onLaunch(options) {
14 const systemInfo = uni.getSystemInfoSync(); 14 const systemInfo = uni.getSystemInfoSync();
@@ -19,21 +19,13 @@ export default { @@ -19,21 +19,13 @@ export default {
19 // 设置小程序来源,企业微信小程序或微信小程序 19 // 设置小程序来源,企业微信小程序或微信小程序
20 this.$store.commit('SET_ORIGIN', origin); 20 this.$store.commit('SET_ORIGIN', origin);
21 this.$store.commit('SET_SCENE', options.scene); 21 this.$store.commit('SET_SCENE', options.scene);
22 - this.$u.api.dict.all().then(response => {  
23 - cache.put('DICT', response.result);  
24 - this.$store.commit('SET_DICT', response.result);  
25 - });  
26 - this.$u.api.district.all().then(response => {  
27 - cache.put('DISTRICT', response.result);  
28 - this.$store.commit('SET_DISTRICT', response.result);  
29 - });  
30 if (!this.authed) { 22 if (!this.authed) {
31 if (origin === 'QY_FREGHT_MA') { 23 if (origin === 'QY_FREGHT_MA') {
32 wx.qy.login({ 24 wx.qy.login({
33 suiteId: config.suiteId, 25 suiteId: config.suiteId,
34 - success: (res) => { 26 + success: res => {
35 if (res.code) { 27 if (res.code) {
36 - uni.$u.api.login.loginByCode({ code: res.code }).then((response) => { 28 + uni.$u.api.login.loginByCode({ code: res.code }).then(response => {
37 if (!response.result) return this.handleLogin(); 29 if (!response.result) return this.handleLogin();
38 const result = response.result || {}; 30 const result = response.result || {};
39 this.$store.commit('SET_AUTHED', result.hasBind); 31 this.$store.commit('SET_AUTHED', result.hasBind);
@@ -43,24 +35,28 @@ export default { @@ -43,24 +35,28 @@ export default {
43 uni.$u.api.user.detail().then(res => { 35 uni.$u.api.user.detail().then(res => {
44 this.$store.commit('SET_FREGHT_INFO', res.result); 36 this.$store.commit('SET_FREGHT_INFO', res.result);
45 }); 37 });
  38 + this.loadCache();
46 } 39 }
47 - }) 40 + });
48 } 41 }
49 }, 42 },
50 fail: () => { 43 fail: () => {
51 this.handleLogin(); 44 this.handleLogin();
52 - } 45 + },
53 }); 46 });
54 } else { 47 } else {
55 this.handleLogin(); 48 this.handleLogin();
56 } 49 }
  50 + } else {
  51 + this.loadCache();
57 } 52 }
58 // 监听刷新权限 53 // 监听刷新权限
59 - uni.$on('refresh-permission', () =>{ 54 + uni.$on('refresh-permission', () => {
60 this.getPermission(); 55 this.getPermission();
  56 + this.loadCache();
61 }); 57 });
62 // 监听检测更新 58 // 监听检测更新
63 - uni.$on('refresh-version', (params) =>{ 59 + uni.$on('refresh-version', params => {
64 const { notifyType = 'toast' } = params || {}; 60 const { notifyType = 'toast' } = params || {};
65 this.handleRefreshVersion(notifyType); 61 this.handleRefreshVersion(notifyType);
66 }); 62 });
@@ -70,7 +66,7 @@ export default { @@ -70,7 +66,7 @@ export default {
70 onShow(options) { 66 onShow(options) {
71 // #ifdef MP-DINGTALK 67 // #ifdef MP-DINGTALK
72 // 监听钉钉统一授权小程序返回结果的方法 68 // 监听钉钉统一授权小程序返回结果的方法
73 - onAuthAppBack(options, (data) => { 69 + onAuthAppBack(options, data => {
74 const { status, result } = data || {}; 70 const { status, result } = data || {};
75 if (status === 'ok' && result && result.authCode) { 71 if (status === 'ok' && result && result.authCode) {
76 uni.$u.api.login.dingtalk({ authCode: result.authCode, corpId: dd.corpId }).then(response => { 72 uni.$u.api.login.dingtalk({ authCode: result.authCode, corpId: dd.corpId }).then(response => {
@@ -90,9 +86,22 @@ export default { @@ -90,9 +86,22 @@ export default {
90 // #endif 86 // #endif
91 }, 87 },
92 methods: { 88 methods: {
  89 + loadCache() {
  90 + uni.$u.api.user.detail().then(res => {
  91 + this.$store.commit('SET_FREGHT_INFO', res.result);
  92 + });
  93 + this.$u.api.dict.all().then(response => {
  94 + cache.put('DICT', response.result);
  95 + this.$store.commit('SET_DICT', response.result);
  96 + });
  97 + this.$u.api.district.all().then(response => {
  98 + cache.put('DISTRICT', response.result);
  99 + this.$store.commit('SET_DISTRICT', response.result);
  100 + });
  101 + },
93 // 检测更新 102 // 检测更新
94 handleRefreshVersion(notifyType) { 103 handleRefreshVersion(notifyType) {
95 - const showToast = (options) => { 104 + const showToast = options => {
96 if (notifyType === 'silent') return; // 静默 105 if (notifyType === 'silent') return; // 静默
97 wx.showToast(options); 106 wx.showToast(options);
98 }; 107 };
@@ -111,31 +120,34 @@ export default { @@ -111,31 +120,34 @@ export default {
111 if (res.confirm) { 120 if (res.confirm) {
112 updateManager.applyUpdate(); 121 updateManager.applyUpdate();
113 } 122 }
114 - } 123 + },
115 }); 124 });
116 }); 125 });
117 updateManager.onUpdateFailed(() => { 126 updateManager.onUpdateFailed(() => {
118 // 新版本下载失败 127 // 新版本下载失败
119 showToast({ title: '网络状况不佳,稍后再试', icon: 'none', duration: 2000 }); 128 showToast({ title: '网络状况不佳,稍后再试', icon: 'none', duration: 2000 });
120 - }) 129 + });
121 } else { 130 } else {
122 showToast({ title: '当前已是最新版本', icon: 'none', duration: 2000 }); 131 showToast({ title: '当前已是最新版本', icon: 'none', duration: 2000 });
123 - }  
124 - }) 132 + }
  133 + });
125 } else { 134 } else {
126 showToast({ title: `当前${wx.getSystemInfoSync()?.environment === 'wxwork' ? '企业' : ''}微信版本过低,请升级到最新版本后重试`, icon: 'none', duration: 3000 }); 135 showToast({ title: `当前${wx.getSystemInfoSync()?.environment === 'wxwork' ? '企业' : ''}微信版本过低,请升级到最新版本后重试`, icon: 'none', duration: 3000 });
127 } 136 }
128 }, 137 },
129 // 查询权限 138 // 查询权限
130 getPermission() { 139 getPermission() {
131 - return new Promise((resolve) => {  
132 - uni.$u.api.user.getPermission({ systemCode: 'dispatch-helper-ma', userId: this.userInfo.userId }).then((response = {}) => {  
133 - const { result = [] } = response;  
134 - this.$store.commit('SET_PERMISSION', result);  
135 - resolve(result);  
136 - }).catch(() => {  
137 - resolve([]);  
138 - }); 140 + return new Promise(resolve => {
  141 + uni.$u.api.user
  142 + .getPermission({ systemCode: 'freight-web', userId: this.userInfo.username })
  143 + .then((response = {}) => {
  144 + const { result = [] } = response;
  145 + this.$store.commit('SET_PERMISSION', result);
  146 + resolve(result);
  147 + })
  148 + .catch(() => {
  149 + resolve([]);
  150 + });
139 }); 151 });
140 }, 152 },
141 handleLogin() { 153 handleLogin() {
@@ -149,40 +161,39 @@ export default { @@ -149,40 +161,39 @@ export default {
149 const result = response.result || {}; 161 const result = response.result || {};
150 this.$store.commit('SET_AUTHED', result.hasBind); 162 this.$store.commit('SET_AUTHED', result.hasBind);
151 this.$store.commit('SET_USER_INFO', result); 163 this.$store.commit('SET_USER_INFO', result);
152 - this.getPermission();  
153 - if (result.hasBind) {  
154 - uni.$u.api.user.detail().then(res => {  
155 - this.$store.commit('SET_FREGHT_INFO', res.result);  
156 - });  
157 - } 164 + uni.$emit('refresh-permission');
158 }); 165 });
159 } 166 }
160 - } 167 + },
161 }); 168 });
162 // #endif 169 // #endif
163 // #ifdef MP-DINGTALK 170 // #ifdef MP-DINGTALK
164 // 打开钉钉统一授权小程序 171 // 打开钉钉统一授权小程序
165 openAuthMiniApp({ 172 openAuthMiniApp({
166 - path: 'pages/home/home', //不要改,这里是小程序dingwlanwvdmrtjjwdmd下的一个页面地址 173 + path: 'pages/home/home', //不要改,这里是小程序dingwlanwvdmrtjjwdmd下的一个页面地址
167 panelHeight: 'percent50', 174 panelHeight: 'percent50',
168 - extraData:{ 175 + extraData: {
169 clientId: config.clientId, // 应用ID(唯一标识) 176 clientId: config.clientId, // 应用ID(唯一标识)
170 rpcScope: 'Contact.User.Read', 177 rpcScope: 'Contact.User.Read',
171 fieldScope: 'Contact.User.mobile', 178 fieldScope: 'Contact.User.mobile',
172 - type:0, 179 + type: 0,
173 ext: JSON.stringify({}), 180 ext: JSON.stringify({}),
174 - from:''  
175 - } 181 + from: '',
  182 + },
176 }); 183 });
177 // #endif 184 // #endif
178 - }  
179 - }  
180 -} 185 + },
  186 + },
  187 +};
181 </script> 188 </script>
182 189
183 <style lang="scss"> 190 <style lang="scss">
184 -@import "@/uni_modules/uview-ui/index.scss"; 191 +@import '@/uni_modules/uview-ui/index.scss';
185 @import '~styles/common.scss'; 192 @import '~styles/common.scss';
186 @import './iconfont/iconfont.css'; 193 @import './iconfont/iconfont.css';
187 @import '~styles/common.scss'; 194 @import '~styles/common.scss';
  195 +
  196 +.u-radio + .u-radio {
  197 + margin-left: 40upx !important;
  198 +}
188 </style> 199 </style>
1 import config from '@/config/index.js'; 1 import config from '@/config/index.js';
2 2
3 -const bossAPI = '/boss-service-api';  
4 -const freightAPI = '/dispatch-helper-ma-api'; 3 +const freightAPI = '/freight-web-api';
  4 +const freightAdmin = '/freight-service-api';
5 const authAPI = '/auth-service-api'; 5 const authAPI = '/auth-service-api';
6 -const dispatchMaApi = 'dispatch-ma-api';  
7 -const tmsWebApi = 'tms-web-api';  
8 -const driverAPI = '/driver-app-api'; 6 +const dispatchMaApi = '/dispatch-ma-api';
  7 +const tmsWebApi = '/tms-web-api';
9 const omsServiceApi = '/oms-service-api' 8 const omsServiceApi = '/oms-service-api'
10 const tmsServiceApi = '/tms-service-api'; 9 const tmsServiceApi = '/tms-service-api';
11 const consignorAPI = '/consignor-app-api'; 10 const consignorAPI = '/consignor-app-api';
@@ -14,15 +13,15 @@ module.exports = (vm) =&gt; { @@ -14,15 +13,15 @@ module.exports = (vm) =&gt; {
14 vm.$u.api = { 13 vm.$u.api = {
15 // 配置参数 14 // 配置参数
16 config: { 15 config: {
17 - getVehicleConfig: params => vm.$u.http.get(freightAPI + '/vehicle/getVehicleConfig', { params }), 16 + getVehicleConfig: params => vm.$u.http.get(freightAPI + '/vehicle/getVehicleConfig', { params }),
18 }, 17 },
19 // 数据字典 18 // 数据字典
20 dict: { 19 dict: {
21 - all: params => vm.$u.http.get(consignorAPI + '/dict/getAll', { params, custom: { auth: false } }), 20 + all: params => vm.$u.http.get(tmsWebApi + '/dataDictionary/queryAll', { params, custom: { auth: true } }),
22 }, 21 },
23 // 行政区划 22 // 行政区划
24 district: { 23 district: {
25 - all: params => vm.$u.http.get(consignorAPI + '/district/commonOption', { params, custom: { auth: false } }), 24 + all: params => vm.$u.http.get(tmsWebApi + '/district/commonOption', { params, custom: { auth: true } }),
26 }, 25 },
27 // 货主地址 26 // 货主地址
28 addressHistory: { 27 addressHistory: {
@@ -36,7 +35,7 @@ module.exports = (vm) =&gt; { @@ -36,7 +35,7 @@ module.exports = (vm) =&gt; {
36 // 发送手机验证码 35 // 发送手机验证码
37 send: (params) => vm.$u.http.get(freightAPI + '/maLogin/sendVc', { params, custom: { auth: false } }), 36 send: (params) => vm.$u.http.get(freightAPI + '/maLogin/sendVc', { params, custom: { auth: false } }),
38 // 绑定手机号 37 // 绑定手机号
39 - bind: (data) => vm.$u.http.post(freightAPI + '/maLogin/wxbind', data, { custom: { auth: false } }), 38 + bind: (data) => vm.$u.http.post(freightAPI + '/maLogin/vcWxbind', data, { custom: { auth: false } }),
40 // 解除绑定 39 // 解除绑定
41 unbind: (data) => vm.$u.http.post(freightAPI + '/user/consignor/unbindWx', data), 40 unbind: (data) => vm.$u.http.post(freightAPI + '/user/consignor/unbindWx', data),
42 // 微信一键登录 41 // 微信一键登录
@@ -58,24 +57,24 @@ module.exports = (vm) =&gt; { @@ -58,24 +57,24 @@ module.exports = (vm) =&gt; {
58 user: { 57 user: {
59 // 根据企业名称获取企业详细信息 58 // 根据企业名称获取企业详细信息
60 getCompanyDetail: (params) => vm.$u.http.get(freightAPI + '/user/getCompanyDetail', { params }), 59 getCompanyDetail: (params) => vm.$u.http.get(freightAPI + '/user/getCompanyDetail', { params }),
61 - detail: params => vm.$u.http.get(freightAPI + '/user/getDetail', { params }),  
62 - getPermission: params => vm.$u.http.get(authAPI + '/permission/getPermission', { params }), 60 + detail: params => vm.$u.http.get(freightAPI + '/user/getDetail', { params }),
  61 + getPermission: params => vm.$u.http.get(authAPI + '/permission/getPermission', { params }),
63 }, 62 },
64 // 联系人 63 // 联系人
65 contact: { 64 contact: {
66 // 选择器数据源 65 // 选择器数据源
67 - select: params => vm.$u.http.get(freightAPI + '/consignorContact/commonSelect', { params }), 66 + select: params => vm.$u.http.get(freightAPI + '/consignorContact/commonSelect', { params }),
  67 + },
  68 + // 常用地址
  69 + address: {
  70 + page: params => vm.$u.http.get(freightAPI + '/address/page', { params }),
  71 + detail: params => vm.$u.http.get(freightAPI + '/address/getDetail', { params }),
  72 + add: (data) => vm.$u.http.post(freightAPI + '/address/add', data),
  73 + modify: (data) => vm.$u.http.post(freightAPI + '/address/modify', data),
  74 + delete: (data) => vm.$u.http.post(freightAPI + '/address/delete', data),
68 }, 75 },
69 - // 常用地址  
70 - address: {  
71 - page: params => vm.$u.http.get(freightAPI + '/address/page', { params }),  
72 - detail: params => vm.$u.http.get(freightAPI + '/address/getDetail', { params }),  
73 - add: (data) => vm.$u.http.post(freightAPI + '/address/add', data),  
74 - modify: (data) => vm.$u.http.post(freightAPI + '/address/modify', data),  
75 - delete: (data) => vm.$u.http.post(freightAPI + '/address/delete', data),  
76 - },  
77 // 查询筛选接口 76 // 查询筛选接口
78 - filter: { 77 + filter: {
79 org: params => vm.$u.http.get(dispatchMaApi + '/org/commonSelect', { params }), 78 org: params => vm.$u.http.get(dispatchMaApi + '/org/commonSelect', { params }),
80 user: params => vm.$u.http.get(tmsWebApi + '/user/commonSelect', { params }), // 用户选择器 79 user: params => vm.$u.http.get(tmsWebApi + '/user/commonSelect', { params }), // 用户选择器
81 getCommonSelect: params => vm.$u.http.get(dispatchMaApi + '/customer/getCommonSelect', { params }), 80 getCommonSelect: params => vm.$u.http.get(dispatchMaApi + '/customer/getCommonSelect', { params }),
@@ -90,6 +89,67 @@ module.exports = (vm) =&gt; { @@ -90,6 +89,67 @@ module.exports = (vm) =&gt; {
90 getBelongCustomer: params => vm.$u.http.get(omsServiceApi + '/orderConfig/selectCustomer', { params }), // 获取专属客户 89 getBelongCustomer: params => vm.$u.http.get(omsServiceApi + '/orderConfig/selectCustomer', { params }), // 获取专属客户
91 statisticsUser: params => vm.$u.http.get(freightAPI + '/pushcartEmployee/page', { params }), // 获取推车员工 90 statisticsUser: params => vm.$u.http.get(freightAPI + '/pushcartEmployee/page', { params }), // 获取推车员工
92 tmsOrg: params => vm.$u.http.get(tmsWebApi + '/org/commonSelect', { params }), 91 tmsOrg: params => vm.$u.http.get(tmsWebApi + '/org/commonSelect', { params }),
  92 + projectCode: params => vm.$u.http.get(freightAPI + '/freightProject/commonSelect', { params }),// 项目
  93 + payeeCommonSelect: params => vm.$u.http.get(freightAPI + '/freightEnterpriseCollectDriver/payeeCommonSelect', { params }), // 代收人
  94 + driver: params => vm.$u.http.get(tmsServiceApi + '/driver/commonSelect', { params }), // 司机选择器
  95 + vehicle: params => vm.$u.http.get(tmsWebApi + '/vehicle/commonSelect', { params }), // 车辆选择器
  96 + goodsName: p => vm.$u.http.get(freightAPI + '/freightEnterpriseGoods/commonSelect', { params:{...p,goodsName:p.query }}).then(res=>{
  97 + return {
  98 + ...res,
  99 + result:res.result.map(i => {
  100 + return {
  101 + name:i.goodsName,
  102 + code:i.id,
  103 + id:i.id
  104 + }
  105 + })
  106 + }
  107 + }), // 货物选择器
  108 + },
  109 + // 申请支付
  110 + freightPayApply: {
  111 + page: params => vm.$u.http.post(freightAPI + '/freightPayApply/page', params),
  112 + getApplyDetailByIds: params => vm.$u.http.post(freightAPI + '/freightPayApply/getApplyDetailByIds', params), // 明细
  113 + apply: params => vm.$u.http.post(freightAPI + '/freightPayApply/apply', params,{custom: {toast:true}}), // 申请
  114 + cancelApply: params => vm.$u.http.post(freightAPI + '/freightPayApply/cancelApply', params,{custom: {toast:true}}), // 取消申请
  115 + audit: params => vm.$u.http.post(freightAPI + '/freightPayApply/audit', params,{custom: {toast:true}}), // 审核
  116 + getCount: params => vm.$u.http.get(freightAPI + '/freightPayApply/getCount', {params}), // 总数
  117 + },
  118 + // 订单管理-网货货运-new
  119 + freightOrder: {
  120 + add: params => vm.$u.http.post(freightAPI + '/freightOrder/maAdd', params,{custom: {toast:true}}), // 下单
  121 + getDistance: params => vm.$u.http.get(freightAPI + '/freightOrder/getDistance', {params}), // 获取距离
  122 + page: params => vm.$u.http.post( freightAPI + '/freightOrder/page', params ), // 分页查询
  123 + currentFreight: params => vm.$u.http.get( freightAdmin + '/freightEnterprise/getDetailByCurrentFreight', params ), // 获取企业配置相关详情
  124 + getServiceAmount: params => vm.$u.http.get( freightAPI + '/freightOrder/getServiceAmount', {params}), // 订单服务费
  125 + enterpriseCollectDriverPage: params => vm.$u.http.get( freightAPI + '/freightEnterpriseCollectDriver/page', params), // 网货企业代收用户分页查询
  126 + download: params => vm.$u.http.get( freightAPI + '/freightOrder/download', params), // 模板下载
  127 + downloadStartCar: params => vm.$u.http.get( freightAPI + '/freightOrder/orderDepartAndArriveDownload', params), // 模板下载
  128 + importStartCar: params => vm.$u.http.get( freightAPI + '/freightOrder/importOrderDepartAndArrive', params), // 导入
  129 + import: params => vm.$u.http.get( freightAPI + '/freightOrder/import', params), // 导入
  130 + depart: params => vm.$u.http.post( freightAPI + '/freightOrder/depart', params), // 发车
  131 + arrive: params => vm.$u.http.post( freightAPI + '/freightOrder/arrive', params), // 到达
  132 + sign: params => vm.$u.http.get( freightAPI + '/freightOrder/sign', params), // 签收
  133 + cancel: params => vm.$u.http.post( freightAPI + '/freightOrder/cancel', params), // 取消
  134 + delete: params => vm.$u.http.post( freightAPI + '/freightOrder/delete', params), // 删除
  135 + assignVehicle: params => vm.$u.http.post( freightAPI + '/freightOrder/assignVehicle', params), // 充值指派
  136 + asyncPayee: params => vm.$u.http.get( freightAPI + '/freightOrder/syncPayee', params), // 同步收款人
  137 + modifyPayee: params => vm.$u.http.post( freightAPI + '/freightOrder/modifyPayee', params), // 修改收款人
  138 + getPayeeInfo: params => vm.$u.http.get( freightAPI + '/freightOrder/getPayeeInfo', params), // 获取收款人
  139 + modifyCustomerOrderCode: params => vm.$u.http.post( freightAPI + '/freightOrder/modifyCustomerOrderCode', params), // 修改内部单号
  140 + modifyAddress: params => vm.$u.http.get( freightAPI + '/freightOrder/modifyAddress', params), // 更改地址
  141 + modifyGoods: params => vm.$u.http.post( freightAPI + '/freightOrder/modifyGoods', params), // 更改货物信息
  142 + adjustAmount: params => vm.$u.http.post( freightAPI + '/freightOrder/adjustAmount', params), // 更改运费
  143 + modifyReceiptAttachment: params => vm.$u.http.post( freightAdmin + '/woss/freightOrder/modifyReceiptAttachment', params), // 修改回单附件
  144 + count: params => vm.$u.http.post( freightAPI + '/freightOrder/count', params), // 状态数量
  145 + getDetail: params => vm.$u.http.get( freightAPI + '/freightOrder/getDetail', {params}), // 订单详情
  146 + checkDepartureTime: params => vm.$u.http.get( freightAPI + '/freightOrder/checkDepartureTime', params), // 校验选择的运单发车时间是否一致
  147 + getStartLatestAddress: params => vm.$u.http.get( freightAPI + '/freightOrder/getStartLatestAddress', params), //
  148 + getEndLatestAddress: params => vm.$u.http.get( freightAPI + '/freightOrder/getEndLatestAddress', params), //
  149 + payeeBindBankCardNo: params => vm.$u.http.get( freightAPI + '/freightOrder/payeeBindBankCardNo', params), //
  150 + getSensitiveByOrderCode:params => vm.$u.http.get( freightAdmin + '/freightOrder/getSensitiveByOrderCode', {params}),
  151 + buildMaQrcode:params => vm.$u.http.get( freightAdmin + '/woss/freightOrder/buildMaQrcode', {params}),
  152 + supplementTrailerVehicle: params => vm.$u.http.get( freightAPI + '/freightOrder/supplementTrailerVehicle', params), // 绑定车挂
93 }, 153 },
94 }; 154 };
95 -}  
96 \ No newline at end of file 155 \ No newline at end of file
  156 +}
components/card/payee.vue 0 → 100644
@@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
  1 +<template>
  2 + <view class="payee">
  3 + <view :class="haveAction ? '' : 'action'">
  4 + {{ item.dueBank ? item.dueBank +'/' : '收款信息' }}{{ item.dueBankCardNo ? item.dueBankCardNo +'/' : '' }}{{
  5 + item.openingBank && item.openingBankBranch ? item.openingBank + item.openingBankBranch : item.openingBank || item.openingBankBranch || ''
  6 + }}
  7 + </view>
  8 + <view v-if="haveAction" class="action" @tap="toSelect">
  9 + <u-text text="更换" suffix-icon="arrow-right"></u-text>
  10 + </view>
  11 + </view>
  12 +</template>
  13 +<script>
  14 +export default {
  15 + name: 'payee',
  16 + props: {
  17 + value:{
  18 + type: Object,
  19 + default(){
  20 + return {}
  21 + },
  22 + },
  23 + haveAction: {
  24 + type: Boolean,
  25 + default: false,
  26 + },
  27 + },
  28 + watch:{
  29 + value: {
  30 + handler(val){
  31 + this.item = val;
  32 + }
  33 + }
  34 + },
  35 + data() {
  36 + return {
  37 + item: this.value
  38 + };
  39 + },
  40 + methods: {
  41 + toSelect() {
  42 + uni.$once('select-payee', item=>{
  43 + this.item = item;
  44 + this.$emit('input',item);
  45 + });
  46 + uni.navigateTo({ url: '/pages/global/search-payee' });
  47 + },
  48 + setItem(item){
  49 + this.item = item;
  50 + }
  51 + },
  52 +};
  53 +</script>
  54 +
  55 +<style scoped lang="scss">
  56 +.payee {
  57 + display: flex;
  58 + justify-content: space-between;
  59 + font-size: 24upx;
  60 + padding: $padding-sm;
  61 + border-radius: $radius-sm;
  62 + background: #f6f8fb;
  63 + .action {
  64 + color: #2673fb;
  65 + min-width: 70rpx;
  66 + float: right;
  67 + }
  68 + margin-bottom: $padding-sm;
  69 +}
  70 +</style>
components/field/field-copy.vue 0 → 100644
@@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
  1 +<template>
  2 + <view class="field-copy" @click.stop="onCopy">
  3 + <slot></slot>
  4 + <view class="img">
  5 + <image src="/static/copy-icon.png"></image>
  6 + </view>
  7 + </view>
  8 +</template>
  9 +
  10 +<script>
  11 +export default {
  12 + name:'fieldCopy',
  13 + props: {
  14 + value: [String, Number]
  15 + },
  16 + methods: {
  17 + // 复制
  18 + onCopy: async function () {
  19 + if (this.value) {
  20 + uni.setClipboardData({
  21 + data: this.value,
  22 + success: function () {
  23 + uni.showToast({ icon: 'success', title: '已复制' });
  24 + },
  25 + });
  26 + }
  27 + },
  28 + },
  29 +};
  30 +</script>
  31 +
  32 +<style lang="scss">
  33 +.field-copy {
  34 + display: inline-block;
  35 + min-width: 40upx;
  36 + .img {
  37 + display: inline-block;
  38 + width: 26rpx;
  39 + height: 26rpx;
  40 + margin-left: 8rpx;
  41 + image {
  42 + width: 100%;
  43 + height: 100%;
  44 + vertical-align: middle;
  45 + }
  46 + }
  47 +}
  48 +</style>
components/keyboard/keyboard-bill.vue 0 → 100644
@@ -0,0 +1,174 @@ @@ -0,0 +1,174 @@
  1 +<template>
  2 + <tui-bottom-popup :show="visible" @close="onClose">
  3 + <view class="keyboard-bill">
  4 + <view class="keyboard-bill__keyboard">
  5 + <view v-for="word in wordText" :key="word" class="key" hover-class="active" hover-start-time="20" hover-stay-time="70" @click="onInput(word)">{{ word }}</view>
  6 + <view v-for="number in numberText" :key="number" class="key" hover-class="active" hover-start-time="20" hover-stay-time="70" @click="onInput(number)">{{ number }}</view>
  7 + </view>
  8 + <view class="keyboard-bill__footer">
  9 + <view class="left">
  10 + <view class="btn delete" hover-class="active" hover-start-time="20" hover-stay-time="70" @click="onDelete">删除</view>
  11 + <view class="btn paste" hover-class="active" hover-start-time="20" hover-stay-time="70" @click="onPaste">粘贴</view>
  12 + </view>
  13 + <view class="btn confirm" hover-class="active" hover-start-time="20" hover-stay-time="70" @click="onConfirm">{{ confirmText }}</view>
  14 + </view>
  15 + </view>
  16 + </tui-bottom-popup>
  17 +</template>
  18 +
  19 +<script>
  20 +export default {
  21 + name: 'keyboard-bill',
  22 + props: {
  23 + value: String,
  24 + visible: Boolean,
  25 + confirmText: {
  26 + type: String,
  27 + default: '确定'
  28 + },
  29 + },
  30 + data: function() {
  31 + return {
  32 + model: [],
  33 + numberText: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
  34 + wordText: ['J', 'D'],
  35 + };
  36 + },
  37 + computed: {
  38 + modelText: function() {
  39 + return this.model.join('');
  40 + }
  41 + },
  42 + watch: {
  43 + value: function(val) {
  44 + this.model = `${val || ''}`.split('') || [];
  45 + },
  46 + },
  47 + methods: {
  48 + onClose: function() {
  49 + this.$emit('visible', false);
  50 + },
  51 + onInput: function(key) {
  52 + this.model.push(key);
  53 + this.$emit('input', this.modelText);
  54 + },
  55 + onDelete: function() {
  56 + this.model.pop();
  57 + this.$emit('input', this.modelText);
  58 + },
  59 + onPaste: function() {
  60 + uni.getClipboardData({
  61 + success: (res) => {
  62 + this.$emit('input', res.data);
  63 + }
  64 + });
  65 + },
  66 + onConfirm: function() {
  67 + this.$emit('confirm', this.modelText);
  68 + }
  69 + }
  70 +};
  71 +</script>
  72 +
  73 +<style lang="scss">
  74 +.keyboard-bill {
  75 + background-color: $color-white;
  76 + &__keyboard {
  77 + padding: 10upx 10upx 0;
  78 + box-sizing: border-box;
  79 + transition: all .3s;
  80 + display: flex;
  81 + flex-wrap: wrap;
  82 + justify-content: space-between;
  83 + background-color: $color-field;
  84 + .key {
  85 + width: 175upx;
  86 + height: 175upx;
  87 + border-radius: 10upx;
  88 + display: flex;
  89 + align-items: center;
  90 + justify-content: center;
  91 + color: $color-black;
  92 + position: relative;
  93 + margin-bottom: $padding-xs;
  94 + background-color: $color-white;
  95 + font-size: $font-lg;
  96 + &.delete, &.confirm {
  97 + width: 160upx;
  98 + }
  99 + &.confirm {
  100 + background-color: $color-primary;
  101 + color: $color-white;
  102 + }
  103 + &.active {
  104 + background-color: darken($color-white, 15%);
  105 + }
  106 + &::after {
  107 + padding: 0;
  108 + margin: 0;
  109 + border: none;
  110 + content: "";
  111 + pointer-events: none; /* 防止点击触发 */
  112 + box-sizing: border-box;
  113 + position: absolute;
  114 + width: 200%;
  115 + height: 200%;
  116 + left: 0;
  117 + top: 0;
  118 + border: 1upx solid $color-border;
  119 + border-radius: 20upx;
  120 + transform: scale(0.5);
  121 + transform-origin: 0 0;
  122 + }
  123 + }
  124 + }
  125 + &__footer {
  126 + display: flex;
  127 + align-items: center;
  128 + justify-content: space-between;
  129 + padding: $padding-md 10upx;
  130 + .left {
  131 + display: flex;
  132 + align-items: center;
  133 + }
  134 + .btn {
  135 + font-size: $font-md;
  136 + padding: $padding-md;
  137 + width: 200upx;
  138 + box-sizing: border-box;
  139 + border-radius: 10upx;
  140 + position: relative;
  141 + display: flex;
  142 + align-items: center;
  143 + justify-content: center;
  144 + &::after {
  145 + padding: 0;
  146 + margin: 0;
  147 + border: none;
  148 + content: "";
  149 + pointer-events: none; /* 防止点击触发 */
  150 + box-sizing: border-box;
  151 + position: absolute;
  152 + width: 200%;
  153 + height: 200%;
  154 + left: 0;
  155 + top: 0;
  156 + border: 1upx solid $color-border;
  157 + border-radius: 20upx;
  158 + transform: scale(0.5);
  159 + transform-origin: 0 0;
  160 + }
  161 + &.confirm {
  162 + background-color: $color-primary;
  163 + color: $color-white;
  164 + }
  165 + &.paste {
  166 + margin-left: $padding-sm;
  167 + }
  168 + &.active {
  169 + background-color: darken($color-white, 15%);
  170 + }
  171 + }
  172 + }
  173 +}
  174 +</style>
components/keyboard/keyboard-waybill.vue 0 → 100644
@@ -0,0 +1,174 @@ @@ -0,0 +1,174 @@
  1 +<template>
  2 + <tui-bottom-popup :show="visible" @close="onClose">
  3 + <view class="keyboard-waybill">
  4 + <view class="keyboard-waybill__keyboard">
  5 + <view v-for="word in wordText" :key="word" class="key" hover-class="active" hover-start-time="20" hover-stay-time="70" @click="onInput(word)">{{ word }}</view>
  6 + <view v-for="number in numberText" :key="number" class="key" hover-class="active" hover-start-time="20" hover-stay-time="70" @click="onInput(number)">{{ number }}</view>
  7 + </view>
  8 + <view class="keyboard-waybill__footer">
  9 + <view class="left">
  10 + <view class="btn delete" hover-class="active" hover-start-time="20" hover-stay-time="70" @click="onDelete">删除</view>
  11 + <view class="btn paste" hover-class="active" hover-start-time="20" hover-stay-time="70" @click="onPaste">粘贴</view>
  12 + </view>
  13 + <view class="btn confirm" hover-class="active" hover-start-time="20" hover-stay-time="70" @click="onConfirm">{{ confirmText }}</view>
  14 + </view>
  15 + </view>
  16 + </tui-bottom-popup>
  17 +</template>
  18 +
  19 +<script>
  20 +export default {
  21 + name: 'keyboard-waybill',
  22 + props: {
  23 + value: String,
  24 + visible: Boolean,
  25 + confirmText: {
  26 + type: String,
  27 + default: '确定'
  28 + },
  29 + },
  30 + data: function() {
  31 + return {
  32 + model: [],
  33 + numberText: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
  34 + wordText: ['Y', 'P'],
  35 + };
  36 + },
  37 + computed: {
  38 + modelText: function() {
  39 + return this.model.join('');
  40 + }
  41 + },
  42 + watch: {
  43 + value: function(val) {
  44 + this.model = `${val || ''}`.split('') || [];
  45 + },
  46 + },
  47 + methods: {
  48 + onClose: function() {
  49 + this.$emit('visible', false);
  50 + },
  51 + onInput: function(key) {
  52 + this.model.push(key);
  53 + this.$emit('input', this.modelText);
  54 + },
  55 + onDelete: function() {
  56 + this.model.pop();
  57 + this.$emit('input', this.modelText);
  58 + },
  59 + onPaste: function() {
  60 + uni.getClipboardData({
  61 + success: (res) => {
  62 + this.$emit('input', res.data);
  63 + }
  64 + });
  65 + },
  66 + onConfirm: function() {
  67 + this.$emit('confirm', this.modelText);
  68 + }
  69 + }
  70 +};
  71 +</script>
  72 +
  73 +<style lang="scss">
  74 +.keyboard-waybill {
  75 + background-color: $color-white;
  76 + &__keyboard {
  77 + padding: 10upx 10upx 0;
  78 + box-sizing: border-box;
  79 + transition: all .3s;
  80 + display: flex;
  81 + flex-wrap: wrap;
  82 + justify-content: space-between;
  83 + background-color: $color-field;
  84 + .key {
  85 + width: 175upx;
  86 + height: 175upx;
  87 + border-radius: 10upx;
  88 + display: flex;
  89 + align-items: center;
  90 + justify-content: center;
  91 + color: $color-black;
  92 + position: relative;
  93 + margin-bottom: $padding-xs;
  94 + background-color: $color-white;
  95 + font-size: $font-lg;
  96 + &.delete, &.confirm {
  97 + width: 160upx;
  98 + }
  99 + &.confirm {
  100 + background-color: $color-primary;
  101 + color: $color-white;
  102 + }
  103 + &.active {
  104 + background-color: darken($color-white, 15%);
  105 + }
  106 + &::after {
  107 + padding: 0;
  108 + margin: 0;
  109 + border: none;
  110 + content: "";
  111 + pointer-events: none; /* 防止点击触发 */
  112 + box-sizing: border-box;
  113 + position: absolute;
  114 + width: 200%;
  115 + height: 200%;
  116 + left: 0;
  117 + top: 0;
  118 + border: 1upx solid $color-border;
  119 + border-radius: 20upx;
  120 + transform: scale(0.5);
  121 + transform-origin: 0 0;
  122 + }
  123 + }
  124 + }
  125 + &__footer {
  126 + display: flex;
  127 + align-items: center;
  128 + justify-content: space-between;
  129 + padding: $padding-md 10upx;
  130 + .left {
  131 + display: flex;
  132 + align-items: center;
  133 + }
  134 + .btn {
  135 + font-size: $font-md;
  136 + padding: $padding-md;
  137 + width: 200upx;
  138 + box-sizing: border-box;
  139 + border-radius: 10upx;
  140 + position: relative;
  141 + display: flex;
  142 + align-items: center;
  143 + justify-content: center;
  144 + &::after {
  145 + padding: 0;
  146 + margin: 0;
  147 + border: none;
  148 + content: "";
  149 + pointer-events: none; /* 防止点击触发 */
  150 + box-sizing: border-box;
  151 + position: absolute;
  152 + width: 200%;
  153 + height: 200%;
  154 + left: 0;
  155 + top: 0;
  156 + border: 1upx solid $color-border;
  157 + border-radius: 20upx;
  158 + transform: scale(0.5);
  159 + transform-origin: 0 0;
  160 + }
  161 + &.confirm {
  162 + background-color: $color-primary;
  163 + color: $color-white;
  164 + }
  165 + &.paste {
  166 + margin-left: $padding-sm;
  167 + }
  168 + &.active {
  169 + background-color: darken($color-white, 15%);
  170 + }
  171 + }
  172 + }
  173 +}
  174 +</style>
components/list.vue
@@ -169,4 +169,4 @@ export default { @@ -169,4 +169,4 @@ export default {
169 }, 169 },
170 } 170 }
171 } 171 }
172 -</script>  
173 \ No newline at end of file 172 \ No newline at end of file
  173 +</script>
components/popup/popup-platenumber.vue 0 → 100644
@@ -0,0 +1,376 @@ @@ -0,0 +1,376 @@
  1 +<template>
  2 + <tui-bottom-popup :show="visible" @close="onClose">
  3 + <div class="popup-platenumber">
  4 + <div class="popup-platenumber__header">
  5 + <u-button v-if="limit.includes('normal')" :type="type === 'normal' ? 'primary' : undefined" @click="type = 'normal'">普通车牌</u-button>
  6 + <u-button v-if="limit.includes('new')" :type="type === 'new' ? 'primary' : undefined" @click="type = 'new'">新能源车牌</u-button>
  7 + <u-button v-if="limit.includes('trailer')" :type="type === 'trailer' ? 'primary' : undefined" @click="type = 'trailer'">挂车牌</u-button>
  8 + </div>
  9 + <div class="popup-platenumber__body">
  10 + <div class="input-box" :class="{ active: currentInputIndex == 0 }" @click="currentInputIndex = 0">{{ currentInputValue[0] }}</div>
  11 + <div class="input-box" :class="{ active: currentInputIndex == 1 }" @click="currentInputIndex = 1">{{ currentInputValue[1] }}</div>
  12 + <div class="split-dot"></div>
  13 + <div class="input-box" :class="{ active: currentInputIndex == 2 }" @click="currentInputIndex = 2">{{ currentInputValue[2] }}</div>
  14 + <div class="input-box" :class="{ active: currentInputIndex == 3 }" @click="currentInputIndex = 3">{{ currentInputValue[3] }}</div>
  15 + <div class="input-box" :class="{ active: currentInputIndex == 4 }" @click="currentInputIndex = 4">{{ currentInputValue[4] }}</div>
  16 + <div class="input-box" :class="{ active: currentInputIndex == 5 }" @click="currentInputIndex = 5">{{ currentInputValue[5] }}</div>
  17 + <div v-if="['normal', 'new'].includes(type)" class="input-box" :class="{ active: currentInputIndex == 6 }" @click="currentInputIndex = 6">{{ currentInputValue[6] }}</div>
  18 + <div v-if="type == 'new'" class="input-box" :class="{ active: currentInputIndex == 7 }" @click="currentInputIndex = 7">{{ currentInputValue[7] }}</div>
  19 + <div v-if="type == 'trailer'" class="input-box">挂</div>
  20 + </div>
  21 + <div class="popup-platenumber__keyboard">
  22 + <template v-if="inputType == 1">
  23 + <div class="key-text" v-for="key of provinceText" :key="key" @click="onChoose(key)">{{ key }}</div>
  24 + <div class="key-text fill-block"></div>
  25 + </template>
  26 + <template v-if="inputType >= 3">
  27 + <div class="key-text" v-for="key of numberText" :key="key" @click="onChoose(key)">{{ key }}</div>
  28 + </template>
  29 + <template v-if="inputType >= 2">
  30 + <div class="key-text" v-for="key of wordText" :key="key" @click="onChoose(key)">{{ key }}</div>
  31 + </template>
  32 + <template v-if="[2, 3, 4].includes(inputType)">
  33 + <span v-for="num of 6" :key="num" class="key-text fill-block"></span>
  34 + </template>
  35 + <template v-if="inputType === 2">
  36 + <span v-for="num of 10" :key="num" class="key-text fill-block"></span>
  37 + </template>
  38 + </div>
  39 + <div class="popup-platenumber__footer" v-safe-bottom>
  40 + <div class="popup-platenumber__footer-left">
  41 + <u-button @click="onClose">取消</u-button>
  42 + <u-button @click="onReset">清空</u-button>
  43 + </div>
  44 + <div class="popup-platenumber__footer-right">
  45 + <u-button @click="onDelete">删除</u-button>
  46 + <u-button type="primary" @click="onConfirm">完成</u-button>
  47 + </div>
  48 + </div>
  49 + </div>
  50 + </tui-bottom-popup>
  51 +</template>
  52 +
  53 +<script>
  54 +
  55 +export default {
  56 + name: 'PopupPlatenumber',
  57 + components: {
  58 + },
  59 + props: {
  60 + visible: Boolean,
  61 + value: {
  62 + type: String,
  63 + default: '',
  64 + },
  65 + limit: {
  66 + type: Array,
  67 + default: () => ['normal', 'new', 'trailer'],
  68 + },
  69 + },
  70 + data() {
  71 + return {
  72 + type: this.limit[0], // 车牌类型
  73 + currentInputIndex: 0, // 当前编辑的输入框
  74 + currentInputValue: ['', '', '', '', '', '', ''],
  75 + provinceText: [
  76 + '京',
  77 + '冀',
  78 + '沪',
  79 + '津',
  80 + '晋',
  81 + '蒙',
  82 + '辽',
  83 + '吉',
  84 + '黑',
  85 + '苏',
  86 + '浙',
  87 + '皖',
  88 + '闽',
  89 + '赣',
  90 + '鲁',
  91 + '豫',
  92 + '鄂',
  93 + '湘',
  94 + '粤',
  95 + '桂',
  96 + '琼',
  97 + '渝',
  98 + '川',
  99 + '贵',
  100 + '云',
  101 + '青',
  102 + '藏',
  103 + '陕',
  104 + '甘',
  105 + '宁',
  106 + '新',
  107 + ],
  108 + numberText: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
  109 + wordText: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
  110 + lastWordText: ['挂'],
  111 + };
  112 + },
  113 + computed: {
  114 + // 输入框类型
  115 + inputType({ type, limit, currentInputIndex }) {
  116 + const options = {
  117 + 0: 1,
  118 + 1: 2,
  119 + 2: 3,
  120 + 3: 3,
  121 + 4: 3,
  122 + 5: 3,
  123 + 6: limit.includes('trailer') && type !== 'new' ? 4 : 3,
  124 + 7: limit.includes('trailer') ? 4 : 3,
  125 + };
  126 + return options[currentInputIndex] || 1;
  127 + },
  128 + },
  129 + watch: {
  130 + limit(value) {
  131 + this.type = value ? value[0] : 'normal';
  132 + },
  133 + type(value) {
  134 + this.onReset(value);
  135 + },
  136 + value(val) {
  137 + if (val) {
  138 + this.initPlate();
  139 + } else {
  140 + this.onReset();
  141 + }
  142 + },
  143 + },
  144 + mounted() {
  145 + this.initPlate();
  146 + },
  147 + methods: {
  148 + onReset() {
  149 + const type = this.type;
  150 + this.currentInputIndex = 0;
  151 + if (type === 'normal') {
  152 + // 普通车牌
  153 + this.currentInputValue = ['', '', '', '', '', '', ''];
  154 + } else if (type === 'new') {
  155 + // 新能源车牌
  156 + this.currentInputValue = ['', '', '', '', '', '', '', ''];
  157 + } else if (type === 'trailer') {
  158 + // 挂车牌
  159 + this.currentInputValue = ['', '', '', '', '', ''];
  160 + }
  161 + },
  162 + initPlate() {
  163 + const plateKey = this.value.split('');
  164 + const isTrailer = plateKey[plateKey.length - 1] === '挂';
  165 + if (plateKey.length === 7) {
  166 + this.type = 'normal';
  167 + if (isTrailer) {
  168 + this.type = 'trailer';
  169 + }
  170 + } else if (plateKey.length === 8) {
  171 + this.type = 'new';
  172 + }
  173 + this.$nextTick(() => {
  174 + if (isTrailer) {
  175 + this.type = 'trailer';
  176 + const trailerKeys = plateKey.filter(key => key !== '挂');
  177 + this.currentInputValue = trailerKeys;
  178 + this.currentInputIndex = trailerKeys.length === 0 ? trailerKeys.length : trailerKeys.length - 1;
  179 + } else {
  180 + this.currentInputValue = plateKey;
  181 + this.currentInputIndex = plateKey.length === 0 ? plateKey.length : plateKey.length - 1;
  182 + }
  183 + });
  184 + },
  185 + onClose() {
  186 + this.$emit('update:visible', false);
  187 + },
  188 + onChoose(value) {
  189 + this.$set(this.currentInputValue, this.currentInputIndex, value);
  190 + if (this.type == 'normal' && this.currentInputIndex < 6) {
  191 + this.currentInputIndex++;
  192 + }
  193 + if (this.type == 'new' && this.currentInputIndex < 7) {
  194 + this.currentInputIndex++;
  195 + }
  196 + if (this.type == 'trailer' && this.currentInputIndex < 5) {
  197 + this.currentInputIndex++;
  198 + }
  199 + },
  200 + onDelete() {
  201 + if (this.currentInputIndex === 0) {
  202 + // 首位
  203 + this.$set(this.currentInputValue, this.currentInputIndex, '');
  204 + } else if (this.currentInputIndex === this.currentInputValue.length - 1) {
  205 + // 末位
  206 + if (this.currentInputValue[this.currentInputIndex] !== '') {
  207 + this.$set(this.currentInputValue, this.currentInputIndex, '');
  208 + } else {
  209 + this.currentInputIndex--;
  210 + this.$set(this.currentInputValue, this.currentInputIndex, '');
  211 + }
  212 + } else {
  213 + // 中间位
  214 + this.currentInputIndex--;
  215 + this.$set(this.currentInputValue, this.currentInputIndex, '');
  216 + }
  217 + },
  218 + onConfirm() {
  219 + const plate = this.currentInputValue.join('');
  220 + let err = false;
  221 + if (this.type === 'normal' && plate.length !== 7) {
  222 + err = true;
  223 + } else if (this.type === 'new' && plate.length !== 8) {
  224 + err = true;
  225 + } else if (this.type === 'trailer' && plate.length !== 6) {
  226 + err = true;
  227 + }
  228 + if (plate.length <= 0) {
  229 + err = false;
  230 + }
  231 + if (err) {
  232 + api.toast({ msg: '请输入完整的车牌号码' });
  233 + } else {
  234 + if (this.type === 'trailer') {
  235 + const trailerPlate = [...this.currentInputValue, '挂'].join('');
  236 + this.$emit('input', trailerPlate === '挂' ? '' : trailerPlate);
  237 + this.$emit('confirm', trailerPlate === '挂' ? '' : trailerPlate);
  238 + } else {
  239 + this.$emit('input', plate);
  240 + this.$emit('confirm', plate);
  241 + }
  242 + this.onClose();
  243 + }
  244 + },
  245 + },
  246 +};
  247 +</script>
  248 +
  249 +<style lang="scss">
  250 +.popup-platenumber {
  251 + background-color: $color-white;
  252 + &__header {
  253 + display: flex;
  254 + align-items: center;
  255 + padding: $padding-sm;
  256 + padding-top: 20px;
  257 + .u-button {
  258 + box-sizing: border-box;
  259 + padding: 2px 8px;
  260 + width: 90px;
  261 + height: 28px;
  262 + border-radius: 7px;
  263 + white-space: nowrap;
  264 + word-break: break-all;
  265 + color: $color-text;
  266 + background: #eaeaea;
  267 + margin-right: $padding-base;
  268 + &--primary {
  269 + background: #fede47;
  270 + color: #604300;
  271 + }
  272 + }
  273 + }
  274 + &__body {
  275 + box-sizing: border-box;
  276 + padding: $padding-sm;
  277 + display: flex;
  278 + justify-content: space-between;
  279 + align-items: center;
  280 + .split-dot {
  281 + width: 4px;
  282 + height: 4px;
  283 + background: $color-text-minor;
  284 + border-radius: 50%;
  285 + }
  286 + .input-box {
  287 + border-radius: $radius-md;
  288 + height: $padding-md * 2;
  289 + width: $padding-md * 2;
  290 + min-width: $padding-md * 2;
  291 + box-sizing: border-box;
  292 + display: inline-flex;
  293 + align-items: center;
  294 + justify-content: center;
  295 + border: 1px solid $color-border;
  296 + font-weight: bold;
  297 + font-size: $font-lg;
  298 + &.active {
  299 + border-color: $color-blue;
  300 + box-shadow: 0 0 4px rgba($color-blue, 0.5);
  301 + }
  302 + }
  303 + }
  304 + &__keyboard {
  305 + padding: $padding-sm;
  306 + box-sizing: border-box;
  307 + transition: all 0.3s;
  308 + display: flex;
  309 + flex-wrap: wrap;
  310 + justify-content: space-between;
  311 + background-color: $color-bg-base;
  312 + .key-text {
  313 + display: block;
  314 + background: $color-white;
  315 + border-radius: $radius-md;
  316 + width: $padding-md * 2;
  317 + height: $padding-md * 2;
  318 + margin: $padding-base 0;
  319 + font-size: $font-md;
  320 + display: flex;
  321 + align-items: center;
  322 + justify-content: center;
  323 + position: relative;
  324 + border: 1px solid $color-border;
  325 + &.fill-block {
  326 + width: $padding-md * 2;
  327 + height: $padding-md * 2;
  328 + background: none;
  329 + box-shadow: none;
  330 + border-color: transparent;
  331 + }
  332 + }
  333 + }
  334 + &__footer {
  335 + display: flex;
  336 + justify-content: space-between;
  337 + background: $color-white;
  338 + box-sizing: border-box;
  339 + padding: $padding-sm;
  340 + padding-bottom: 20px;
  341 + .u-button {
  342 + box-sizing: border-box;
  343 + padding: 2px 8px;
  344 + width: 70px;
  345 + height: 32px;
  346 + border-radius: 7px;
  347 + white-space: nowrap;
  348 + word-break: break-all;
  349 + color: $color-white;
  350 + background: #333333;
  351 + &--primary {
  352 + background: #fede47;
  353 + color: #604300;
  354 + }
  355 + }
  356 + &-left,
  357 + &-right {
  358 + display: flex;
  359 + align-items: center;
  360 + .u-button {
  361 + padding: $padding-base $padding-md;
  362 + }
  363 + }
  364 + &-left {
  365 + .u-button {
  366 + margin-right: $padding-xs;
  367 + }
  368 + }
  369 + &-right {
  370 + .u-button {
  371 + margin-left: $padding-xs;
  372 + }
  373 + }
  374 + }
  375 +}
  376 +</style>
config/request.js
@@ -4,9 +4,9 @@ const apiHost = config.apiHost; @@ -4,9 +4,9 @@ const apiHost = config.apiHost;
4 const systemInfo = wx.getSystemInfoSync(); 4 const systemInfo = wx.getSystemInfoSync();
5 5
6 // 此vm参数为页面的实例,可以通过它引用vuex中的变量 6 // 此vm参数为页面的实例,可以通过它引用vuex中的变量
7 -module.exports = (vm) => { 7 +module.exports = vm => {
8 // 初始化请求配置 8 // 初始化请求配置
9 - uni.$u.http.setConfig((config) => { 9 + uni.$u.http.setConfig(config => {
10 /* config 为默认全局配置*/ 10 /* config 为默认全局配置*/
11 config.baseURL = apiHost; /* 根域名 */ 11 config.baseURL = apiHost; /* 根域名 */
12 config.header = { 12 config.header = {
@@ -20,63 +20,72 @@ module.exports = (vm) =&gt; { @@ -20,63 +20,72 @@ module.exports = (vm) =&gt; {
20 platform: 'mp', // 当前运行平台 20 platform: 'mp', // 当前运行平台
21 }; 21 };
22 return config; 22 return config;
23 - }) 23 + });
24 24
25 // 请求拦截 25 // 请求拦截
26 - uni.$u.http.interceptors.request.use((config) => { // 可使用async await 做异步操作  
27 - if (config.custom.auth === false) {  
28 - delete config.header['Authorization'];  
29 - } else {  
30 - config.header['Authorization'] = `Bearer ${vm.$store.state?.userInfo?.accessToken}`;  
31 - }  
32 - return config;  
33 - }, config => { // 可使用async await 做异步操作  
34 - return Promise.reject(config)  
35 - }) 26 + uni.$u.http.interceptors.request.use(
  27 + config => {
  28 + // 可使用async await 做异步操作
  29 + if (config.custom.auth === false) {
  30 + delete config.header['Authorization'];
  31 + } else {
  32 + config.header['Authorization'] = `Bearer ${vm.$store.state?.userInfo?.accessToken}`;
  33 + }
  34 + // config.header['Authorization'] = `Bearer 814aec36-60b1-4b47-a0fa-b909501f3e48`;
  35 + return config;
  36 + },
  37 + config => {
  38 + // 可使用async await 做异步操作
  39 + return Promise.reject(config);
  40 + },
  41 + );
36 42
37 // 响应拦截 43 // 响应拦截
38 - uni.$u.http.interceptors.response.use((response) => {  
39 - const { data = {}, statusCode, config } = response;  
40 - const { success, message = '', businessException, errorCode } = data;  
41 - if (config && config.interceptors === false) {  
42 - // 请求配置不做返回拦截的情况  
43 - return response;  
44 - } else {  
45 - if (success) {  
46 - return data; 44 + uni.$u.http.interceptors.response.use(
  45 + response => {
  46 + const { data = {}, statusCode, config } = response;
  47 + const { success, message = '', businessException, errorCode } = data;
  48 + if (config && config.interceptors === false) {
  49 + // 请求配置不做返回拦截的情况
  50 + return response;
47 } else { 51 } else {
48 - if (`${errorCode}` === '401') {  
49 - console.error(`【${errorCode}】登录过期`);  
50 - store.commit('SET_AUTHED', false);  
51 - setTimeout(() => {  
52 - uni.reLaunch({ url: '/pages/login/login' });  
53 - }, 1200);  
54 - return Promise.reject(message);  
55 - }  
56 - if (businessException && !(config && config.custom && config.custom.toast)) {  
57 - uni.showToast({ icon: 'none', title: message || `[${errorCode}]系统异常`, duration: 3000 });  
58 - } else if (!(config && config.custom && config.custom.toast)) {  
59 - if (config.toast !== false) {  
60 - if (`${errorCode}`.substr(0, 1) === '5') {  
61 - uni.showToast({ icon: 'none', title: `[${errorCode}]系统异常`, duration: 3000 });  
62 - } else {  
63 - uni.showToast({ icon: 'none', title: message || `[${errorCode}]系统异常`, duration: 3000 }); 52 + if (success) {
  53 + return data;
  54 + } else {
  55 + if (`${errorCode}` === '401') {
  56 + console.error(`【${errorCode}】登录过期`);
  57 + store.commit('SET_AUTHED', false);
  58 + setTimeout(() => {
  59 + uni.reLaunch({ url: '/pages/login/login' });
  60 + }, 200);
  61 + return Promise.reject(message);
  62 + }
  63 + if (businessException && !(config && config.custom && config.custom.toast)) {
  64 + uni.showToast({ icon: 'none', title: message || `[${errorCode}]系统异常`, duration: 3000 });
  65 + } else if (!(config && config.custom && config.custom.toast)) {
  66 + if (config.toast !== false) {
  67 + if (`${errorCode}`.substr(0, 1) === '5') {
  68 + uni.showToast({ icon: 'none', title: `[${errorCode}]系统异常`, duration: 3000 });
  69 + } else {
  70 + uni.showToast({ icon: 'none', title: message || `[${errorCode}]系统异常`, duration: 3000 });
  71 + }
64 } 72 }
65 } 73 }
  74 + return Promise.reject(message);
66 } 75 }
67 - return Promise.reject(message);  
68 } 76 }
69 - }  
70 - }, (response) => {  
71 - // 对响应错误做点什么 (statusCode !== 200)  
72 - const { statusCode } = response;  
73 - if (statusCode === 401) {  
74 - console.error(`【${statusCode}】登录过期`);  
75 - store.commit('SET_AUTHED', false);  
76 - setTimeout(() => {  
77 - uni.reLaunch({ url: '/pages/login/login' });  
78 - }, 1200);  
79 - }  
80 - return Promise.reject(response);  
81 - });  
82 -} 77 + },
  78 + response => {
  79 + // 对响应错误做点什么 (statusCode !== 200)
  80 + const { statusCode } = response;
  81 + if (statusCode === 401) {
  82 + console.error(`【${statusCode}】登录过期`);
  83 + store.commit('SET_AUTHED', false);
  84 + setTimeout(() => {
  85 + uni.reLaunch({ url: '/pages/login/login' });
  86 + }, 1200);
  87 + }
  88 + return Promise.reject(response);
  89 + },
  90 + );
  91 +};
@@ -10,11 +10,7 @@ Vue.prototype.formatImagePath = formatImagePath; @@ -10,11 +10,7 @@ Vue.prototype.formatImagePath = formatImagePath;
10 import uView from '@/uni_modules/uview-ui'; 10 import uView from '@/uni_modules/uview-ui';
11 Vue.use(uView); 11 Vue.use(uView);
12 12
13 -let colorPrimary = '#2673FB';  
14 -  
15 -// #ifdef MP-DINGTALK  
16 -colorPrimary = '#3296FA';  
17 -// #endif 13 +let colorPrimary = '#1E7B6B';
18 14
19 uni.$u.setConfig({ 15 uni.$u.setConfig({
20 config: { 16 config: {
@@ -28,5 +28,8 @@ @@ -28,5 +28,8 @@
28 } 28 }
29 } 29 }
30 } 30 }
  31 + },
  32 + "devDependencies": {
  33 + "prettier": "3.3.2"
31 } 34 }
32 } 35 }
@@ -5,31 +5,97 @@ @@ -5,31 +5,97 @@
5 "style": { 5 "style": {
6 "navigationBarTitleText": "首页" 6 "navigationBarTitleText": "首页"
7 } 7 }
8 - },  
9 - { 8 + },{
10 "path": "pages/login/login", 9 "path": "pages/login/login",
11 "style": { 10 "style": {
12 "navigationBarTitleText": "登录" 11 "navigationBarTitleText": "登录"
13 } 12 }
14 }, 13 },
15 - {  
16 - "path": "pages/login/code",  
17 - "style": {  
18 - "navigationBarTitleText": "验证码"  
19 - }  
20 - },  
21 { 14 {
22 - "path": "pages/my/my", 15 + "path": "pages/login/code",
  16 + "style": {
  17 + "navigationBarTitleText": "验证码"
  18 + }
  19 + },{
  20 + "path": "pages/order/index",
  21 + "style": {
  22 + "navigationBarTitleText": "订单",
  23 + "enablePullDownRefresh": true
  24 + }
  25 + },{
  26 + "path": "pages/order/detail",
  27 + "style": {
  28 + "navigationBarTitleText": "详情"
  29 + }
  30 + },{
  31 + "path": "pages/order/filter",
  32 + "style": {
  33 + "navigationBarTitleText": "筛选器"
  34 + }
  35 + },{
  36 + "path": "pages/order/add",
  37 + "style": {
  38 + "navigationBarTitleText": "创建订单"
  39 + }
  40 + },{
  41 + "path": "pages/order/start-car",
  42 + "style": {
  43 + "navigationBarTitleText": "确认发车"
  44 + }
  45 + },{
  46 + "path": "pages/order/arrival-car",
  47 + "style": {
  48 + "navigationBarTitleText": "确认到达"
  49 + }
  50 + },
  51 + {
  52 + "path": "pages/order/change-fee",
  53 + "style": {
  54 + "navigationBarTitleText": "更改运费"
  55 + }
  56 + },
  57 + {
  58 + "path": "pages/order/again-assign",
23 "style": { 59 "style": {
24 - "navigationBarTitleText": "我的",  
25 - "navigationStyle": "custom" 60 + "navigationBarTitleText": "重新指派"
  61 + }
  62 + },
  63 + {
  64 + "path": "pages/order/upload-receipt",
  65 + "style": {
  66 + "navigationBarTitleText": "上传回单"
  67 + }
  68 + },
  69 + {
  70 + "path": "pages/order/change-goods",
  71 + "style": {
  72 + "navigationBarTitleText": "货物信息"
  73 + }
  74 + },
  75 + {
  76 + "path": "pages/settlement/index",
  77 + "style": {
  78 + "navigationBarTitleText": "支付申请",
  79 + "enablePullDownRefresh": true
  80 + }
  81 + },
  82 + {
  83 + "path": "pages/settlement/filter",
  84 + "style": {
  85 + "navigationBarTitleText": "筛选器"
  86 + }
  87 + },
  88 + {
  89 + "path": "pages/me/index",
  90 + "style": {
  91 + "navigationBarTitleText": "我的"
26 } 92 }
27 } 93 }
28 ], 94 ],
29 "subPackages": [ 95 "subPackages": [
30 { 96 {
31 - "root":"pages/common",  
32 - "pages":[ 97 + "root":"pages/common",
  98 + "pages":[
33 { 99 {
34 "path": "select-contact", 100 "path": "select-contact",
35 "style": { 101 "style": {
@@ -45,12 +111,24 @@ @@ -45,12 +111,24 @@
45 { 111 {
46 "path": "webview" 112 "path": "webview"
47 } 113 }
48 - ]  
49 - }, 114 + ]
  115 + },
50 { 116 {
51 "root":"pages/global", 117 "root":"pages/global",
52 "pages": [ 118 "pages": [
53 { 119 {
  120 + "path": "search-payee",
  121 + "style": {
  122 + "navigationBarTitleText": "代收人"
  123 + }
  124 + },
  125 + {
  126 + "path": "search-dict",
  127 + "style": {
  128 + "navigationBarTitleText": "数据字典"
  129 + }
  130 + },
  131 + {
54 "path": "search-common", 132 "path": "search-common",
55 "style": { 133 "style": {
56 "navigationBarTitleText": "区域" 134 "navigationBarTitleText": "区域"
@@ -97,54 +175,44 @@ @@ -97,54 +175,44 @@
97 ], 175 ],
98 "globalStyle": { 176 "globalStyle": {
99 "navigationBarTextStyle": "white", 177 "navigationBarTextStyle": "white",
100 - "navigationBarTitleText": "则一请车助手",  
101 - "navigationBarBackgroundColor": "#2673FB",  
102 - "backgroundColor": "#2673FB" 178 + "navigationBarTitleText": "则一飞牛货主",
  179 + "navigationBarBackgroundColor": "#1E7B6B",
  180 + "backgroundColor": "#1E7B6B"
103 }, 181 },
104 "condition": { 182 "condition": {
105 "current": 0, 183 "current": 0,
106 "list": [ 184 "list": [
107 { 185 {
108 - "name": "首页",  
109 - "path": "/pages/index"  
110 - },  
111 - {  
112 - "name": "登录",  
113 - "path": "/pages/login/login"  
114 - } 186 + "name": "首页",
  187 + "path": "/pages/index"
  188 + },
  189 + {
  190 + "name": "登录",
  191 + "path": "/pages/login/login"
  192 + }
115 ] 193 ]
116 }, 194 },
117 "tabBar": { 195 "tabBar": {
118 "color": "#8c8c8c", 196 "color": "#8c8c8c",
119 "fontSize": "100upx", 197 "fontSize": "100upx",
120 - // #ifdef MP-DINGTALK  
121 - "selectedColor": "#3296FA",  
122 - // #endif  
123 - // #ifndef MP-DINGTALK  
124 - "selectedColor": "#2673FB",  
125 - // #endif 198 + "selectedColor": "#1E7B6B",
126 "backgroundColor": "#FFFFFF", 199 "backgroundColor": "#FFFFFF",
127 "list": [ 200 "list": [
128 { 201 {
129 - "pagePath": "pages/index",  
130 - "iconPath": "static/tabbar/inquiry.png",  
131 - // #ifdef MP-DINGTALK  
132 - "selectedIconPath": "static/tabbar/inquiry-active-dingtalk.png",  
133 - // #endif  
134 - // #ifndef MP-DINGTALK  
135 - "selectedIconPath": "static/tabbar/inquiry-active.png",  
136 - // #endif  
137 - "text": "首页" 202 + "pagePath": "pages/order/index",
  203 + "iconPath": "static/tabbar/order.png",
  204 + "selectedIconPath": "static/tabbar/order-active.png",
  205 + "text": "订单"
138 }, 206 },
139 { 207 {
140 - "pagePath": "pages/my/my",  
141 - "iconPath": "static/tabbar/my.png",  
142 - // #ifdef MP-DINGTALK  
143 - "selectedIconPath": "static/tabbar/my-active-dingtalk.png",  
144 - // #endif  
145 - // #ifndef MP-DINGTALK  
146 - "selectedIconPath": "static/tabbar/my-active.png",  
147 - // #endif 208 + "pagePath": "pages/settlement/index",
  209 + "iconPath": "static/tabbar/settlement.png",
  210 + "selectedIconPath": "static/tabbar/settlement-active.png",
  211 + "text": "结算"
  212 + },{
  213 + "pagePath": "pages/me/index",
  214 + "iconPath": "static/tabbar/me.png",
  215 + "selectedIconPath": "static/tabbar/me-active.png",
148 "text": "我的" 216 "text": "我的"
149 } 217 }
150 ] 218 ]
@@ -156,15 +224,15 @@ @@ -156,15 +224,15 @@
156 "^List": "@/components/list.vue", 224 "^List": "@/components/list.vue",
157 "^Empty": "@/components/empty.vue", 225 "^Empty": "@/components/empty.vue",
158 "^PullRefresh": "@/components/pull-refresh.vue", 226 "^PullRefresh": "@/components/pull-refresh.vue",
159 - "^Waypoints": "@/components/waypoints.vue", 227 + "^Waypoints": "@/components/waypoints.vue",
160 "^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue", 228 "^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue",
161 "^action-(.*)": "@/components/action/action-$1.vue", 229 "^action-(.*)": "@/components/action/action-$1.vue",
162 "^card-(.*)": "@/components/card/card-$1.vue", 230 "^card-(.*)": "@/components/card/card-$1.vue",
163 "^keyboard-(.*)": "@/components/keyboard/keyboard-$1.vue", 231 "^keyboard-(.*)": "@/components/keyboard/keyboard-$1.vue",
164 "^chart-(.*)": "@/components/chart/chart-$1.vue", 232 "^chart-(.*)": "@/components/chart/chart-$1.vue",
165 - "^form-(.*)": "@/components/form/form-$1.vue",  
166 - "^popup-(.*)": "@/components/popup/popup-$1.vue",  
167 - "^picker-(.*)": "@/components/picker/picker-$1.vue", 233 + "^form-(.*)": "@/components/form/form-$1.vue",
  234 + "^popup-(.*)": "@/components/popup/popup-$1.vue",
  235 + "^picker-(.*)": "@/components/picker/picker-$1.vue",
168 "^render-(.*)": "@/components/render/render-$1.vue", 236 "^render-(.*)": "@/components/render/render-$1.vue",
169 "^select-(.*)": "@/components/select/select-$1.vue", 237 "^select-(.*)": "@/components/select/select-$1.vue",
170 "^upload-(.*)": "@/components/upload/upload-$1.vue", 238 "^upload-(.*)": "@/components/upload/upload-$1.vue",
@@ -175,13 +243,13 @@ @@ -175,13 +243,13 @@
175 "^search-bar": "@/components/business/search-bar.vue", 243 "^search-bar": "@/components/business/search-bar.vue",
176 "^search-tabs": "@/components/business/search-tabs.vue", 244 "^search-tabs": "@/components/business/search-tabs.vue",
177 "^z-(.*)": "@/components/zee/z-$1.vue", 245 "^z-(.*)": "@/components/zee/z-$1.vue",
178 - "^view-item": "@/components/business/view-item", 246 + "^view-item": "@/components/business/view-item",
179 "^count-down": "@/components/business/count-down", 247 "^count-down": "@/components/business/count-down",
180 "^modal-input-line": "@/components/business/modal-input-line", 248 "^modal-input-line": "@/components/business/modal-input-line",
181 "^view-image": "@/components/viewer/view-image", 249 "^view-image": "@/components/viewer/view-image",
182 "^input-(.*)": "@/components/business/input/input-$1.vue", 250 "^input-(.*)": "@/components/business/input/input-$1.vue",
183 - "^f2": "@/components/f2/f2.vue",  
184 - "^l-(.*)": "@/uni_modules/lime-painter/components/l-$1/l-$1.vue" 251 + "^f2": "@/components/f2/f2.vue",
  252 + "^l-(.*)": "@/uni_modules/lime-painter/components/l-$1/l-$1.vue"
185 } 253 }
186 } 254 }
187 -}  
188 \ No newline at end of file 255 \ No newline at end of file
  256 +}
pages/common/webview.vue
1 <template> 1 <template>
2 - <web-view :src="src" @message="onMessage"></web-view> 2 + <view>
  3 + <web-view v-if="src" :src="src" @message="onMessage"></web-view>
  4 + </view>
3 </template> 5 </template>
4 6
5 <script> 7 <script>
  8 +import { parse, urlParam } from '@/utils/param';
  9 +
6 export default { 10 export default {
7 - data() {  
8 - return {  
9 - src: ''  
10 - }  
11 - },  
12 - onLoad() {  
13 - const params = this.$params || {};  
14 - const url = params.url;  
15 - let query = '';  
16 - try {  
17 - query = JSON.parse(params.query);  
18 - } catch(e) {  
19 - query = '';  
20 - }  
21 - let src = url;  
22 - if (params.query) {  
23 - src += uni.$u.queryParams(query);  
24 - }  
25 - this.src = src;  
26 - },  
27 - methods: {  
28 - onMessage(e) {  
29 - uni.$emit('webview-message', e.detail.data);  
30 - }  
31 - } 11 + data: function() {
  12 + return {
  13 + src: ''
  14 + }
  15 + },
  16 + onLoad: function(option) {
  17 + let query = {};
  18 + try {
  19 + query = JSON.parse(option.query || {}) || {};
  20 + } catch (e) {
  21 + query = {};
  22 + }
  23 + const url = `${option.url}${urlParam(query)}`;
  24 + this.src = option.encode ? encodeURI(url) : url;
  25 + },
  26 + methods: {
  27 + onMessage(e) {
  28 + const { type, data, message } = e.detail.data[0] || {};
  29 + if (type === 'back') {
  30 + uni.navigateBack();
  31 + } else if (type === 'select') {
  32 + uni.$emit('webview-select', data);
  33 + // uni.navigateBack();
  34 + } else if (type === 'toast') {
  35 + uni.showToast({ title: message, icon: 'none' });
  36 + }
  37 + }
  38 + }
32 } 39 }
33 </script> 40 </script>
pages/global/search-common.vue
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 <search-bar v-model="searchForm.query" placeholder="请输入搜索关键词" auto @confirm="onSearch" /> 4 <search-bar v-model="searchForm.query" placeholder="请输入搜索关键词" auto @confirm="onSearch" />
5 </template> 5 </template>
6 <template #content> 6 <template #content>
7 - <List ref="list" v-model="list" :api="searchAPI" :addOption='addOption'> 7 + <List ref="list" v-model="list" :api="searchAPI" :addOption="addOption">
8 <template v-for="(item, index) in list"> 8 <template v-for="(item, index) in list">
9 <zui-cell :key="index" @click="onSelect(item, index)"> 9 <zui-cell :key="index" @click="onSelect(item, index)">
10 <template #title>{{ item[label] }}</template> 10 <template #title>{{ item[label] }}</template>
@@ -24,21 +24,21 @@ export default { @@ -24,21 +24,21 @@ export default {
24 data() { 24 data() {
25 return { 25 return {
26 searchForm: { 26 searchForm: {
27 - query: '' 27 + query: '',
28 }, 28 },
29 list: [], 29 list: [],
30 label: 'name', 30 label: 'name',
31 value: null, 31 value: null,
32 dict: null, 32 dict: null,
33 isAdd: true, 33 isAdd: true,
34 - url: 'org',  
35 - } 34 + urlType: 'org',
  35 + };
36 }, 36 },
37 onLoad(option) { 37 onLoad(option) {
38 if (option.label) this.label = option.label; 38 if (option.label) this.label = option.label;
39 if (option.value) this.value = option.value; 39 if (option.value) this.value = option.value;
40 if (option.dict) this.dict = option.dict; 40 if (option.dict) this.dict = option.dict;
41 - if (option.url) this.url = option.url; 41 + if (option.url) this.urlType = option.url;
42 if (!option.url) { 42 if (!option.url) {
43 uni.navigateBack(); 43 uni.navigateBack();
44 } 44 }
@@ -50,11 +50,11 @@ export default { @@ -50,11 +50,11 @@ export default {
50 searchAPI(params) { 50 searchAPI(params) {
51 const $params = this.$params; 51 const $params = this.$params;
52 let searchParams = { ...params, ...this.searchForm }; 52 let searchParams = { ...params, ...this.searchForm };
53 - if($params.params){  
54 - let obj = JSON.parse($params.params)  
55 - searchParams = { ...params, ...this.searchForm, ...obj } 53 + if ($params.params) {
  54 + let obj = JSON.parse($params.params);
  55 + searchParams = { ...params, ...this.searchForm, ...obj };
56 } 56 }
57 - return uni.$u.api.filter[this.url](searchParams); 57 + return uni.$u.api.filter[this.urlType](searchParams);
58 }, 58 },
59 onSelect(item) { 59 onSelect(item) {
60 const $params = this.$params; 60 const $params = this.$params;
@@ -63,10 +63,10 @@ export default { @@ -63,10 +63,10 @@ export default {
63 uni.navigateBack(); 63 uni.navigateBack();
64 } 64 }
65 }, 65 },
66 - addOption(list){  
67 - let obj = { code: '', name: '不限', id: '', }; 66 + addOption(list) {
  67 + let obj = { code: '', name: '不限', id: '' };
68 let hash = {}; 68 let hash = {};
69 - let options = [obj, ...list].reduce((result, item) => { 69 + let options = [...list].reduce((result, item) => {
70 let hashKey = `${item.id || item.code || item.username}` || '_empty'; 70 let hashKey = `${item.id || item.code || item.username}` || '_empty';
71 if (!hash[hashKey]) { 71 if (!hash[hashKey]) {
72 hash[hashKey] = true; 72 hash[hashKey] = true;
@@ -77,7 +77,7 @@ export default { @@ -77,7 +77,7 @@ export default {
77 return result; // 返回结果数组 77 return result; // 返回结果数组
78 }, []); 78 }, []);
79 this.$emit('input', options); 79 this.$emit('input', options);
80 - }  
81 - }  
82 -} 80 + },
  81 + },
  82 +};
83 </script> 83 </script>
pages/global/search-dict.vue 0 → 100644
@@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
  1 +<template>
  2 + <Page name="search">
  3 + <template #content>
  4 + <template v-for="(item, index) in list">
  5 + <zui-cell :key="index" @click="onSelect(item, index)">
  6 + <template #title>{{ item.valueName }}</template>
  7 + </zui-cell>
  8 + </template>
  9 + </template>
  10 + </Page>
  11 +</template>
  12 +
  13 +<script>
  14 +import { mapGetters } from 'vuex';
  15 +export default {
  16 + data() {
  17 + return {
  18 + list: [],
  19 + excludes: [],
  20 + title: '字典',
  21 + dict: '',
  22 + };
  23 + },
  24 + onLoad(option) {
  25 + if (option.title) this.title = option.title;
  26 + if (option.dict) this.dict = option.dict;
  27 + if (option.excludes) this.excludes = option.excludes.split(',');
  28 + uni.setNavigationBarTitle({ title: option.title });
  29 + this.initData();
  30 + },
  31 + computed: {
  32 + ...mapGetters(['dictList']),
  33 + },
  34 + methods: {
  35 + initData() {
  36 + const matchDictList = this.dictList(this.dict) || [];
  37 + this.list = matchDictList.filter(i => i.valueCode && i.valueName && !this.excludes.includes(i.valueCode));
  38 + // this.list = [{ valueCode: '', valueName: '不限' }, ...need];
  39 + },
  40 + onSelect(item) {
  41 + uni.$emit('select-dict', item.valueName == '不限' && !item.valueCode ? { valueCode: '', valueName: '' } : item);
  42 + uni.navigateBack();
  43 + },
  44 + },
  45 +};
  46 +</script>
pages/global/search-payee.vue 0 → 100644
@@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
  1 +<template>
  2 + <Page name="search-payee" flank>
  3 + <template #header>
  4 + <search-bar v-model="query" placeholder="搜索手机号或姓名" auto @confirm="onSearch" />
  5 + </template>
  6 + <template #content>
  7 + <List ref="list" v-model="list" :api="searchAPI">
  8 + <template v-for="(item, index) in list">
  9 + <view class="card" :key="index" @tap="choseIndex = index">
  10 + <view class="title">
  11 + <view>
  12 + <text style="color: #999999; margin-right: 30upx">收款人</text>
  13 + <text>{{ item.name }}</text>
  14 + <text>{{ item.mobile }}</text>
  15 + </view>
  16 + <view style="float: right" :class="{ action: choseIndex === index }">
  17 + <u-icon v-if="choseIndex !== index" name="checkmark-circle"></u-icon>
  18 + <u-icon v-else name="checkmark-circle-fill"></u-icon>
  19 + </view>
  20 + </view>
  21 + <payee :value="item"></payee>
  22 + </view>
  23 + </template>
  24 + </List>
  25 + </template>
  26 + <template #footer>
  27 + <u-button type="primary" @click="onSelect">确定</u-button>
  28 + </template>
  29 + </Page>
  30 +</template>
  31 +
  32 +<script>
  33 +import payee from '../../components/card/payee.vue';
  34 +import UText from '../../uni_modules/uview-ui/components/u-text/u-text.vue';
  35 +export default {
  36 + name: 'change-payee',
  37 + components: { UText, payee },
  38 + data() {
  39 + return {
  40 + choseIndex: '',
  41 + list: [],
  42 + query: '',
  43 + };
  44 + },
  45 + methods: {
  46 + searchAPI(params) {
  47 + return uni.$u.api.filter.payeeCommonSelect({ query: this.query, ...params });
  48 + },
  49 + onSelect() {
  50 + let item = this.list[this.choseIndex];
  51 + uni.$emit('select-payee', item);
  52 + uni.navigateBack();
  53 + },
  54 + },
  55 +};
  56 +</script>
  57 +
  58 +<style lang="scss">
  59 +.page-search-payee {
  60 + &__header {
  61 + padding: 15rpx 22rpx !important;
  62 + }
  63 + &__footer {
  64 + background: $color-white;
  65 + }
  66 + .title {
  67 + padding-bottom: $padding-md;
  68 + display: flex;
  69 + justify-content: space-between;
  70 + }
  71 + .card {
  72 + padding: $padding-md;
  73 + border-radius: $radius-md;
  74 + margin-bottom: $padding-md;
  75 + background: $color-white;
  76 + .action {
  77 + color: $color-primary;
  78 + }
  79 + }
  80 +}
  81 +</style>
pages/index.vue
1 <template> 1 <template>
2 - <Page ref="page" name="home">  
3 - <template #content>  
4 - 这是首页  
5 - </template>  
6 - </Page> 2 + <view> </view>
7 </template> 3 </template>
8 4
9 <script> 5 <script>
10 export default { 6 export default {
11 -  
12 -} 7 + onReady() {
  8 + uni.switchTab({ url: '/pages/order/index' });
  9 + },
  10 +};
13 </script> 11 </script>
14 12
15 -<style lang="scss">  
16 -  
17 -</style>  
18 \ No newline at end of file 13 \ No newline at end of file
  14 +<style lang="scss"></style>
pages/login/code.vue
1 <template> 1 <template>
2 <view class="page-code"> 2 <view class="page-code">
3 <view class="page-code__logo"> 3 <view class="page-code__logo">
4 - <image :src="formatImagePath('truck-load', 'svg')" mode="aspectFit"></image> 4 + <image src="/static/logo.png" mode="aspectFit"></image>
5 </view> 5 </view>
6 <view class="page-code__title"> 6 <view class="page-code__title">
7 <view>请输入验证码</view> 7 <view>请输入验证码</view>
@@ -19,7 +19,9 @@ @@ -19,7 +19,9 @@
19 </u-cell> 19 </u-cell>
20 </view> 20 </view>
21 <view class="page-code__button"> 21 <view class="page-code__button">
22 - <u-button shape="circle" type="primary" hover-class="active" open-type="getUserInfo" lang="zh_CN" :disabled="!isValidated" :loading="submitting" @getuserinfo="onGetUserInfo">授权登录</u-button> 22 + <u-button shape="circle" type="primary" hover-class="active" open-type="getUserInfo" lang="zh_CN" :disabled="!isValidated" :loading="submitting" @getuserinfo="onGetUserInfo"
  23 + >授权登录</u-button
  24 + >
23 </view> 25 </view>
24 </view> 26 </view>
25 </template> 27 </template>
@@ -41,7 +43,7 @@ export default { @@ -41,7 +43,7 @@ export default {
41 computed: { 43 computed: {
42 isValidated() { 44 isValidated() {
43 return !!this.form.verificationCode; 45 return !!this.form.verificationCode;
44 - } 46 + },
45 }, 47 },
46 onLoad() { 48 onLoad() {
47 this.form.mobile = this.$params.mobile; 49 this.form.mobile = this.$params.mobile;
@@ -70,7 +72,7 @@ export default { @@ -70,7 +72,7 @@ export default {
70 if (code) { 72 if (code) {
71 this.code = code; 73 this.code = code;
72 } 74 }
73 - } 75 + },
74 }); 76 });
75 }, 77 },
76 onCodeChange(text) { 78 onCodeChange(text) {
@@ -83,12 +85,15 @@ export default { @@ -83,12 +85,15 @@ export default {
83 } 85 }
84 if (!this.sendding) { 86 if (!this.sendding) {
85 this.sendding = true; 87 this.sendding = true;
86 - uni.$u.api.login.send({ mobile: this.form.mobile }).then(() => {  
87 - uni.showToast({ title: '验证码已发送', icon: 'none' });  
88 - this.$refs.code.start();  
89 - }).finally(() => {  
90 - this.sendding = false;  
91 - }); 88 + uni.$u.api.login
  89 + .send({ mobile: this.form.mobile })
  90 + .then(() => {
  91 + uni.showToast({ title: '验证码已发送', icon: 'none' });
  92 + this.$refs.code.start();
  93 + })
  94 + .finally(() => {
  95 + this.sendding = false;
  96 + });
92 } 97 }
93 } else { 98 } else {
94 uni.showToast({ title: '倒计时结束后再发送', icon: 'none' }); 99 uni.showToast({ title: '倒计时结束后再发送', icon: 'none' });
@@ -103,20 +108,24 @@ export default { @@ -103,20 +108,24 @@ export default {
103 }; 108 };
104 if (!this.submitting) { 109 if (!this.submitting) {
105 this.submitting = true; 110 this.submitting = true;
106 - uni.$u.api.login.bind(data).then((response) => {  
107 - const result = response.result || {};  
108 - this.$store.commit('SET_AUTHED', result.hasBind);  
109 - this.$store.commit('SET_USER_INFO', result);  
110 - uni.showToast({ title: '登录成功', icon: 'none' });  
111 - uni.$emit('refresh-permission');  
112 - setTimeout(() => {  
113 - uni.switchTab({ url: '/pages/index' });  
114 - }, 1500);  
115 - }).catch(() => {  
116 - this.generateWeChatAuthCode();  
117 - }).finally(() => {  
118 - this.submitting = false;  
119 - }); 111 + uni.$u.api.login
  112 + .bind(data)
  113 + .then(response => {
  114 + const result = response.result || {};
  115 + this.$store.commit('SET_AUTHED', result.hasBind);
  116 + this.$store.commit('SET_USER_INFO', result);
  117 + uni.showToast({ title: '登录成功', icon: 'none' });
  118 + uni.$emit('refresh-permission');
  119 + setTimeout(() => {
  120 + uni.switchTab({ url: '/pages/order/index' });
  121 + }, 1500);
  122 + })
  123 + .catch(() => {
  124 + this.generateWeChatAuthCode();
  125 + })
  126 + .finally(() => {
  127 + this.submitting = false;
  128 + });
120 } 129 }
121 }, 130 },
122 // 获取授权信息 131 // 获取授权信息
@@ -137,7 +146,7 @@ export default { @@ -137,7 +146,7 @@ export default {
137 }); 146 });
138 } 147 }
139 }, 148 },
140 - } 149 + },
141 }; 150 };
142 </script> 151 </script>
143 152
pages/login/login.vue
1 <template> 1 <template>
2 <view class="page-login"> 2 <view class="page-login">
3 <view class="page-login__logo"> 3 <view class="page-login__logo">
4 - <image :src="formatImagePath('truck-load', 'svg')" mode="aspectFit"></image> 4 + <image src="/static/logo.png" mode="aspectFit"></image>
5 </view> 5 </view>
6 <view class="page-login__title"> 6 <view class="page-login__title">
7 <view>您好,</view> 7 <view>您好,</view>
@@ -27,15 +27,15 @@ @@ -27,15 +27,15 @@
27 </u-button> 27 </u-button>
28 </view> 28 </view>
29 <!-- #endif --> 29 <!-- #endif -->
30 - <view class="page-login__check">  
31 - <u-checkbox-group v-model="checked" placement="column">  
32 - <u-checkbox name="checked" />  
33 - </u-checkbox-group>  
34 - <text>勾选即代表您同意</text>  
35 - <text class="link" @click="openPolicy">《用户协议》</text>  
36 - <text>以及</text>  
37 - <text class="link" @click="openPrivacy">《隐私政策》</text>  
38 - </view> 30 + <!-- <view class="page-login__check">-->
  31 + <!-- <u-checkbox-group v-model="checked" placement="column">-->
  32 + <!-- <u-checkbox name="checked" />-->
  33 + <!-- </u-checkbox-group>-->
  34 + <!-- <text>勾选即代表您同意</text>-->
  35 + <!-- <text class="link" @click="openPolicy">《用户协议》</text>-->
  36 + <!-- <text>以及</text>-->
  37 + <!-- <text class="link" @click="openPrivacy">《隐私政策》</text>-->
  38 + <!-- </view>-->
39 <!-- #ifdef MP-WEIXIN --> 39 <!-- #ifdef MP-WEIXIN -->
40 <view class="page-login__wechat"> 40 <view class="page-login__wechat">
41 <u-button type="primary" plain shape="circle" open-type="getPhoneNumber" :loading="submitting" loading-text="登录中..." @getphonenumber="onGetPhoneNumber"> 41 <u-button type="primary" plain shape="circle" open-type="getPhoneNumber" :loading="submitting" loading-text="登录中..." @getphonenumber="onGetPhoneNumber">
@@ -63,7 +63,7 @@ export default { @@ -63,7 +63,7 @@ export default {
63 code: '', 63 code: '',
64 sendding: false, 64 sendding: false,
65 submitting: false, 65 submitting: false,
66 - checked: [] 66 + checked: [],
67 }; 67 };
68 }, 68 },
69 computed: { 69 computed: {
@@ -72,12 +72,12 @@ export default { @@ -72,12 +72,12 @@ export default {
72 }), 72 }),
73 isValidated() { 73 isValidated() {
74 //校验手机号和位数 74 //校验手机号和位数
75 - let patt = /^[1][3-9][\d]{9}/ 75 + let patt = /^[1][3-9][\d]{9}/;
76 return patt.test(this.form.mobile); 76 return patt.test(this.form.mobile);
77 }, 77 },
78 isChecked() { 78 isChecked() {
79 - return this.checked.includes('checked');  
80 - } 79 + return true; // this.checked.includes('checked');
  80 + },
81 }, 81 },
82 onLoad() { 82 onLoad() {
83 this.generateWeChatAuthCode(); 83 this.generateWeChatAuthCode();
@@ -95,9 +95,9 @@ export default { @@ -95,9 +95,9 @@ export default {
95 if (code) { 95 if (code) {
96 this.code = code; 96 this.code = code;
97 } else { 97 } else {
98 - return uni.showToast({ icon:'none', title:'微信授权失败' }); 98 + return uni.showToast({ icon: 'none', title: '微信授权失败' });
99 } 99 }
100 - } 100 + },
101 }); 101 });
102 }, 102 },
103 // 用户协议 103 // 用户协议
@@ -116,62 +116,69 @@ export default { @@ -116,62 +116,69 @@ export default {
116 }, 116 },
117 // 发送验证码并打开验证码页面 117 // 发送验证码并打开验证码页面
118 sendCode() { 118 sendCode() {
119 - if (!this.isChecked) {  
120 - return uni.showToast({ icon:'none', title:'请您阅读并勾选《用户协议》和《隐私政策》' });  
121 - } 119 + // if (!this.isChecked) {
  120 + // return uni.showToast({ icon: 'none', title: '请您阅读并勾选《用户协议》和《隐私政策》' });
  121 + // }
122 if (!this.sendding) { 122 if (!this.sendding) {
123 this.sendding = true; 123 this.sendding = true;
124 - uni.$u.api.login.send({ mobile: this.form.mobile, origin: this.origin}).then(() => {  
125 - uni.$u.route({ url: '/pages/login/code', params: { mobile: this.form.mobile } });  
126 - }).finally(() => {  
127 - this.sendding = false;  
128 - }); 124 + uni.$u.api.login
  125 + .send({ mobile: this.form.mobile, origin: this.origin })
  126 + .then(() => {
  127 + uni.$u.route({ url: '/pages/login/code', params: { mobile: this.form.mobile } });
  128 + })
  129 + .finally(() => {
  130 + this.sendding = false;
  131 + });
129 } 132 }
130 }, 133 },
131 // 获取当前登录用户手机号成功后自动登录 134 // 获取当前登录用户手机号成功后自动登录
132 onGetPhoneNumber(e) { 135 onGetPhoneNumber(e) {
133 if (!this.isChecked) { 136 if (!this.isChecked) {
134 - return uni.showToast({ icon:'none', title:'请您阅读并勾选《用户协议》和《隐私政策》' }); 137 + return uni.showToast({ icon: 'none', title: '请您阅读并勾选《用户协议》和《隐私政策》' });
135 } 138 }
136 if (!this.submitting) { 139 if (!this.submitting) {
137 this.submitting = true; 140 this.submitting = true;
138 - uni.$u.api.login.wxbind({ code: this.code, mobileCode: e.detail.code, encryptedData: e.detail.encryptedData, iv: e.detail.iv, origin: this.origin }).then((response) => {  
139 - const result = response.result || {};  
140 - this.$store.commit('SET_AUTHED', result.hasBind);  
141 - this.$store.commit('SET_USER_INFO', result);  
142 - uni.showToast({ title: '登录成功', icon: 'none' });  
143 - uni.$emit('refresh-permission');  
144 - setTimeout(() => {  
145 - uni.switchTab({ url: '/pages/index' });  
146 - }, 1500);  
147 - }).catch(() => {  
148 - this.generateWeChatAuthCode();  
149 - }).finally(() => {  
150 - this.submitting = false;  
151 - }); 141 + uni.$u.api.login
  142 + .wxbind({ code: this.code, mobileCode: e.detail.code, encryptedData: e.detail.encryptedData, iv: e.detail.iv, origin: this.origin })
  143 + .then(response => {
  144 + const result = response.result || {};
  145 + this.$store.commit('SET_AUTHED', result.hasBind);
  146 + this.$store.commit('SET_USER_INFO', result);
  147 + uni.showToast({ title: '登录成功', icon: 'none' });
  148 + uni.$emit('refresh-permission');
  149 + setTimeout(() => {
  150 + uni.switchTab({ url: '/pages/index' });
  151 + }, 1500);
  152 + })
  153 + .catch(() => {
  154 + this.generateWeChatAuthCode();
  155 + })
  156 + .finally(() => {
  157 + this.submitting = false;
  158 + });
152 } 159 }
153 }, 160 },
154 // 处理钉钉授权登录 161 // 处理钉钉授权登录
155 handleDingTalkLogin() { 162 handleDingTalkLogin() {
156 - if (!this.isChecked) {  
157 - return uni.showToast({ icon:'none', title:'请您阅读并勾选《用户协议》和《隐私政策》' });  
158 - } 163 + // if (!this.isChecked) {
  164 + // return uni.showToast({ icon: 'none', title: '请您阅读并勾选《用户协议》和《隐私政策》' });
  165 + // }
159 // #ifdef MP-DINGTALK 166 // #ifdef MP-DINGTALK
160 openAuthMiniApp({ 167 openAuthMiniApp({
161 - path: 'pages/home/home', //不要改,这里是小程序dingwlanwvdmrtjjwdmd下的一个页面地址 168 + path: 'pages/home/home', //不要改,这里是小程序dingwlanwvdmrtjjwdmd下的一个页面地址
162 panelHeight: 'percent50', 169 panelHeight: 'percent50',
163 - extraData:{ 170 + extraData: {
164 clientId: 'suiteyaqgg5vsf9ktnhec', // 应用ID(唯一标识) 171 clientId: 'suiteyaqgg5vsf9ktnhec', // 应用ID(唯一标识)
165 rpcScope: 'Contact.User.Read', 172 rpcScope: 'Contact.User.Read',
166 fieldScope: 'Contact.User.mobile', 173 fieldScope: 'Contact.User.mobile',
167 - type:0, 174 + type: 0,
168 ext: JSON.stringify({}), 175 ext: JSON.stringify({}),
169 - from:''  
170 - } 176 + from: '',
  177 + },
171 }); 178 });
172 // #endif 179 // #endif
173 - }  
174 - } 180 + },
  181 + },
175 }; 182 };
176 </script> 183 </script>
177 184
pages/me/index.vue 0 → 100644
@@ -0,0 +1,301 @@ @@ -0,0 +1,301 @@
  1 +<template>
  2 + <Page name="my" flank>
  3 + <template #content>
  4 + <view class="page-my__background"></view>
  5 + <view class="page-my__info">
  6 + <view class="page-my__info-avatar">
  7 + <view class="avatar">
  8 + <image v-if="freightInfo.headImgUrl" class="image" :src="freightInfo.headImgUrl" mode="aspectFill" />
  9 + <!-- #ifdef MP-WEIXIN -->
  10 + <open-data v-else type="userAvatarUrl"></open-data>
  11 + <!-- #endif -->
  12 + <!-- #ifndef MP-WEIXIN -->
  13 + <!-- #ifdef MP-DINGTALK -->
  14 + <image class="image" :src="formatImagePath('dingtalk', 'svg')" mode="aspectFill"></image>
  15 + <!-- #endif -->
  16 + <!-- #ifndef MP-DINGTALK -->
  17 + <image class="image" :src="formatImagePath('avatar-none', 'svg')" mode="aspectFill"></image>
  18 + <!-- #endif -->
  19 + <!-- #endif -->
  20 + </view>
  21 + </view>
  22 + <view class="page-my__info-content">
  23 + <view class="name">
  24 + <text v-if="freightInfo.name">{{ freightInfo.name }}{{ mobileFilter(freightInfo.mobile) }}</text>
  25 + <!-- #ifdef MP-WEIXIN -->
  26 + <open-data v-else type="userNickName"></open-data>
  27 + <!-- #endif -->
  28 + <!-- #ifndef MP-WEIXIN -->
  29 + <text>钉钉用户</text>
  30 + <!-- #endif -->
  31 + </view>
  32 + <view class="mobile">
  33 + {{ freightInfo.enterpriseName }}
  34 + </view>
  35 + <view class="mobile">
  36 + <render-dict v-if="freightInfo.job" v-else dict="FREIGHT_ENTERPRISE_EMPLOYEE_JOB" :value="freightInfo.job"></render-dict>
  37 + <text v-else-if="freightInfo.enterpriseAdmin">管理员</text>
  38 + </view>
  39 + <!-- #ifdef MP-WEIXIN -->
  40 + <view class="refresh-version" @click.stop="handleRefreshVersion">
  41 + <view :class="[loading && 'loading']"><u-icon name="reload" size="20" /></view>
  42 + <text>检测更新</text>
  43 + </view>
  44 + <!-- #endif -->
  45 + </view>
  46 + </view>
  47 + <view class="page-my__login">
  48 + <template v-if="authed">
  49 + <u-button shape="circle" @click="handleLogout">退出登录</u-button>
  50 + </template>
  51 + <template v-else>
  52 + <u-button shape="circle" @click="handleLogin">立即登录</u-button>
  53 + </template>
  54 + </view>
  55 + <view class="card-version">
  56 + <text class="cell-version">SDK: {{ versionInfo.SDKVersion }}</text>
  57 + <text class="cell-version">wechat: {{ versionInfo.version }}</text>
  58 + <text class="cell-version" v-if="version">version: {{ version }}</text>
  59 + </view>
  60 + </template>
  61 + </Page>
  62 +</template>
  63 +
  64 +<script>
  65 +import cache from '@/utils/cache';
  66 +import { mapState, mapGetters } from 'vuex';
  67 +import { version } from '@/config';
  68 +
  69 +export default {
  70 + data() {
  71 + return {
  72 + loading: false,
  73 + versionInfo: uni.getSystemInfoSync(),
  74 + };
  75 + },
  76 + computed: {
  77 + ...mapState(['authed']),
  78 + ...mapGetters(['userInfo', 'freightInfo']),
  79 + version() {
  80 + return version;
  81 + },
  82 + },
  83 + methods: {
  84 + mobileFilter(value = '') {
  85 + if (!value) return '';
  86 + let reg = /^(\d{3})\d*(\d{4})$/;
  87 + return value.replace(/^(\d{3})\d*(\d{4})$/, '$1****$2');
  88 + },
  89 + // 登录
  90 + handleLogin() {
  91 + uni.navigateTo({ url: '/pages/login/login' });
  92 + },
  93 + // 退出登录
  94 + handleLogout() {
  95 + if (this.authed) {
  96 + uni.showModal({
  97 + title: '提示',
  98 + content: '确定退出登录吗?',
  99 + confirmColor: '#f5222d',
  100 + // #ifdef MP-DINGTALK
  101 + confirmButtonText: '确定',
  102 + cancelButtonText: '取消',
  103 + // #endif
  104 + success: res => {
  105 + if (res.confirm) {
  106 + // uni.$u.api.login.unbind().then(success => {
  107 + // if (success) {
  108 + uni.showToast({ title: '退出成功', icon: 'none' });
  109 + this.$store.commit('LOGOUT');
  110 + uni.reLaunch({ url: '/pages/login/login' });
  111 + // }
  112 + // });
  113 + }
  114 + },
  115 + });
  116 + } else {
  117 + uni.showToast({ title: '您还未登录', icon: 'none' });
  118 + }
  119 + },
  120 + // 检测更新
  121 + handleRefreshVersion() {
  122 + uni.$emit('refresh-version');
  123 + this.loading = true;
  124 + setTimeout(() => {
  125 + this.loading = false;
  126 + }, 2000);
  127 + },
  128 + },
  129 +};
  130 +</script>
  131 +
  132 +<style lang="scss">
  133 +.page-my {
  134 + box-sizing: border-box;
  135 + overflow-x: hidden;
  136 + &__info {
  137 + padding-top: $padding-md * 6;
  138 + padding-bottom: $padding-md * 3;
  139 + display: flex;
  140 + text-align: center;
  141 + align-items: center;
  142 + justify-content: space-between;
  143 + .avatar {
  144 + width: 128upx;
  145 + height: 128upx;
  146 + border-radius: 50%;
  147 + overflow: hidden;
  148 + font-size: 0;
  149 + filter: blur(0);
  150 + .image {
  151 + height: 100%;
  152 + width: 100%;
  153 + font-size: 0;
  154 + }
  155 + }
  156 + &-content {
  157 + padding-left: $padding-md;
  158 + flex: auto;
  159 + display: flex;
  160 + flex-direction: column;
  161 + align-items: flex-start;
  162 + position: relative;
  163 + .refresh-version {
  164 + position: absolute;
  165 + right: 0;
  166 + top: 16px;
  167 + display: flex;
  168 + align-items: center;
  169 + font-size: $font-md;
  170 + color: $color-text-minor;
  171 + }
  172 + }
  173 + .name {
  174 + font-weight: bold;
  175 + font-size: $font-lg;
  176 + }
  177 + .mobile {
  178 + color: $color-text-minor;
  179 + }
  180 + }
  181 + &__background {
  182 + position: absolute;
  183 + top: 0;
  184 + left: 0;
  185 + filter: blur(300upx);
  186 + height: 100vh;
  187 + width: 100vw;
  188 + overflow-x: hidden;
  189 + &::before {
  190 + position: absolute;
  191 + content: '';
  192 + top: 600upx;
  193 + left: -100upx;
  194 + height: 300upx;
  195 + width: 300upx;
  196 + transform: rotate(45deg);
  197 + background-color: rgba($color-zy-orange, 0.3);
  198 + }
  199 + &::after {
  200 + position: absolute;
  201 + content: '';
  202 + top: 0upx;
  203 + left: 300upx;
  204 + height: 600upx;
  205 + width: 600upx;
  206 + transform: rotate(45deg);
  207 + background-color: rgba($color-primary, 0.3);
  208 + }
  209 + }
  210 + &__login {
  211 + margin-top: $padding-md * 24;
  212 + .u-button {
  213 + box-shadow: $shadow-normal;
  214 + }
  215 + }
  216 + .button-cell {
  217 + display: flex;
  218 + align-items: center;
  219 + width: 100%;
  220 + border: none;
  221 + background-color: inherit;
  222 + line-height: inherit;
  223 + padding: $padding-sm $padding-md;
  224 + border-radius: 0;
  225 + border-top-left-radius: $radius-md;
  226 + border-top-right-radius: $radius-md;
  227 + box-sizing: border-box;
  228 + &::after {
  229 + display: none;
  230 + }
  231 + &__left-icon {
  232 + display: inline-flex;
  233 + align-items: center;
  234 + justify-content: center;
  235 + color: $color-primary;
  236 + margin-right: $padding-base;
  237 + .u-icon {
  238 + margin-right: $padding-md;
  239 + &__icon {
  240 + font-size: $font-lg !important;
  241 + }
  242 + }
  243 + }
  244 + &__title {
  245 + color: $color-text;
  246 + font-size: $font-md;
  247 + flex: auto;
  248 + text-align: left;
  249 + }
  250 + &__right-icon {
  251 + color: $color-text-caption;
  252 + }
  253 + &__line {
  254 + margin: 0;
  255 + border-bottom-width: 1px;
  256 + border-bottom-style: solid;
  257 + width: 100%;
  258 + transform: scaleY(0.5);
  259 + border-color: rgba(151, 151, 151, 0.2);
  260 + position: absolute;
  261 + bottom: 0;
  262 + right: 0;
  263 + margin-left: $padding-md;
  264 + width: calc(100% - 24rpx);
  265 + }
  266 + &--hover {
  267 + background-color: #f3f4f6;
  268 + }
  269 + }
  270 +
  271 + .loading {
  272 + animation: _loading 1s ease 2;
  273 + }
  274 + @keyframes _loading {
  275 + from {
  276 + transform: rotateZ(0deg);
  277 + }
  278 + to {
  279 + transform: rotateZ(360deg);
  280 + }
  281 + }
  282 + .card-version {
  283 + display: flex;
  284 + align-items: center;
  285 + justify-content: center;
  286 + margin-top: 40rpx;
  287 + font-family:
  288 + PingFangSC,
  289 + PingFang SC;
  290 + font-weight: 400;
  291 + font-size: 22rpx;
  292 + color: #999999;
  293 + line-height: 30rpx;
  294 + text-align: left;
  295 + font-style: normal;
  296 + .cell-version {
  297 + margin: 0 8rpx;
  298 + }
  299 + }
  300 +}
  301 +</style>
pages/my/my.vue
@@ -1,290 +0,0 @@ @@ -1,290 +0,0 @@
1 -<template>  
2 - <Page name="my" flank>  
3 - <template #content>  
4 - <view class="page-my__background"></view>  
5 - <view class="page-my__info">  
6 - <view class="page-my__info-avatar">  
7 - <view class="avatar">  
8 - <image v-if="freightInfo.headImgUrl" class="image" :src="freightInfo.headImgUrl" mode="aspectFill" />  
9 - <!-- #ifdef MP-WEIXIN -->  
10 - <open-data v-else type="userAvatarUrl"></open-data>  
11 - <!-- #endif -->  
12 - <!-- #ifndef MP-WEIXIN -->  
13 - <!-- #ifdef MP-DINGTALK -->  
14 - <image class="image" :src="formatImagePath('dingtalk', 'svg')" mode="aspectFill"></image>  
15 - <!-- #endif -->  
16 - <!-- #ifndef MP-DINGTALK -->  
17 - <image class="image" :src="formatImagePath('avatar-none', 'svg')" mode="aspectFill"></image>  
18 - <!-- #endif -->  
19 - <!-- #endif -->  
20 - </view>  
21 - </view>  
22 - <view class="page-my__info-content">  
23 - <view class="name">  
24 - <text v-if="freightInfo.name">{{ freightInfo.name }}</text>  
25 - <!-- #ifdef MP-WEIXIN -->  
26 - <open-data v-else type="userNickName"></open-data>  
27 - <!-- #endif -->  
28 - <!-- #ifndef MP-WEIXIN -->  
29 - <text>钉钉用户</text>  
30 - <!-- #endif -->  
31 - </view>  
32 - <view class="mobile">  
33 - <render-mobile :value="userInfo.mobile" />  
34 - </view>  
35 - <!-- #ifdef MP-WEIXIN -->  
36 - <view class="refresh-version" @click.stop="handleRefreshVersion">  
37 - <view :class="[loading && 'loading']"><u-icon name="reload" size="20" /></view>  
38 - <text>检测更新</text>  
39 - </view>  
40 - <!-- #endif -->  
41 - </view>  
42 - </view>  
43 - <view class="page-my__login">  
44 - <template v-if="authed">  
45 - <u-button shape="circle" @click="handleLogout">退出登录</u-button>  
46 - </template>  
47 - <template v-else>  
48 - <u-button shape="circle" @click="handleLogin">立即登录</u-button>  
49 - </template>  
50 - </view>  
51 - <view class="card-version">  
52 - <text class="cell-version">SDK: {{versionInfo.SDKVersion}}</text>  
53 - <text class="cell-version">wechat: {{versionInfo.version}}</text>  
54 - <text class="cell-version" v-if="version">version: {{version}}</text>  
55 - </view>  
56 - </template>  
57 - </Page>  
58 -</template>  
59 -  
60 -<script>  
61 -import cache from '@/utils/cache';  
62 -import { mapState, mapGetters } from 'vuex';  
63 -import { version } from '@/config';  
64 -  
65 -export default {  
66 - data() {  
67 - return {  
68 - loading: false,  
69 - versionInfo: uni.getSystemInfoSync(),  
70 - }  
71 - },  
72 - computed: {  
73 - ...mapState(['authed']),  
74 - ...mapGetters(['userInfo', 'freightInfo']),  
75 - version() {  
76 - return version;  
77 - }  
78 - },  
79 - methods: {  
80 - // 登录  
81 - handleLogin() {  
82 - uni.navigateTo({ url: '/pages/login/login' });  
83 - },  
84 - // 退出登录  
85 - handleLogout() {  
86 - if (this.authed) {  
87 - uni.showModal({  
88 - title: '提示',  
89 - content: '确定退出登录吗?',  
90 - confirmColor: '#f5222d',  
91 - // #ifdef MP-DINGTALK  
92 - confirmButtonText: '确定',  
93 - cancelButtonText: '取消',  
94 - // #endif  
95 - success: res => {  
96 - if (res.confirm) {  
97 - // uni.$u.api.login.unbind().then(success => {  
98 - // if (success) {  
99 - uni.showToast({ title: '退出成功', icon: 'none' });  
100 - this.$store.commit('LOGOUT');  
101 - uni.reLaunch({ url: '/pages/login/login' });  
102 - // }  
103 - // });  
104 - }  
105 - }  
106 - });  
107 - } else {  
108 - uni.showToast({ title: '您还未登录', icon: 'none' });  
109 - }  
110 - },  
111 - // 检测更新  
112 - handleRefreshVersion() {  
113 - uni.$emit('refresh-version');  
114 - this.loading = true;  
115 - setTimeout(() =>{  
116 - this.loading = false;  
117 - }, 2000);  
118 - }  
119 - }  
120 -}  
121 -</script>  
122 -  
123 -<style lang="scss">  
124 -.page-my {  
125 - box-sizing: border-box;  
126 - overflow-x: hidden;  
127 - &__info {  
128 - padding-top: $padding-md * 6;  
129 - padding-bottom: $padding-md * 3;  
130 - display: flex;  
131 - text-align: center;  
132 - align-items: center;  
133 - justify-content: space-between;  
134 - .avatar {  
135 - width: 128upx;  
136 - height: 128upx;  
137 - border-radius: 50%;  
138 - overflow: hidden;  
139 - font-size: 0;  
140 - filter: blur(0);  
141 - .image {  
142 - height: 100%;  
143 - width: 100%;  
144 - font-size: 0;  
145 - }  
146 - }  
147 - &-content {  
148 - padding-left: $padding-md;  
149 - flex: auto;  
150 - display: flex;  
151 - flex-direction: column;  
152 - align-items: flex-start;  
153 - position: relative;  
154 - .refresh-version {  
155 - position: absolute;  
156 - right: 0;  
157 - top: 16px;  
158 - display: flex;  
159 - align-items: center;  
160 - font-size: $font-md;  
161 - color: $color-text-minor;  
162 - }  
163 - }  
164 - .name {  
165 - font-weight: bold;  
166 - font-size: $font-lg;  
167 - }  
168 - .mobile {  
169 - color: $color-text-minor;  
170 - }  
171 - }  
172 - &__background {  
173 - position: absolute;  
174 - top: 0;  
175 - left: 0;  
176 - filter: blur(300upx);  
177 - height: 100vh;  
178 - width: 100vw;  
179 - overflow-x: hidden;  
180 - &::before {  
181 - position: absolute;  
182 - content: '';  
183 - top: 600upx;  
184 - left: -100upx;  
185 - height: 300upx;  
186 - width: 300upx;  
187 - transform: rotate(45deg);  
188 - background-color: rgba($color-zy-orange, 0.3);  
189 - }  
190 - &::after {  
191 - position: absolute;  
192 - content: '';  
193 - top: 0upx;  
194 - left: 300upx;  
195 - height: 600upx;  
196 - width: 600upx;  
197 - transform: rotate(45deg);  
198 - background-color: rgba($color-primary, 0.3);  
199 - }  
200 - }  
201 - &__login {  
202 - margin-top: $padding-md * 24;  
203 - .u-button {  
204 - box-shadow: $shadow-normal;  
205 - }  
206 - }  
207 - .button-cell {  
208 - display: flex;  
209 - align-items: center;  
210 - width: 100%;  
211 - border: none;  
212 - background-color: inherit;  
213 - line-height: inherit;  
214 - padding: $padding-sm $padding-md;  
215 - border-radius: 0;  
216 - border-top-left-radius: $radius-md;  
217 - border-top-right-radius: $radius-md;  
218 - box-sizing: border-box;  
219 - &::after {  
220 - display: none;  
221 - }  
222 - &__left-icon {  
223 - display: inline-flex;  
224 - align-items: center;  
225 - justify-content: center;  
226 - color: $color-primary;  
227 - margin-right: $padding-base;  
228 - .u-icon {  
229 - margin-right: $padding-md;  
230 - &__icon {  
231 - font-size: $font-lg !important;  
232 - }  
233 - }  
234 - }  
235 - &__title {  
236 - color: $color-text;  
237 - font-size: $font-md;  
238 - flex: auto;  
239 - text-align: left;  
240 - }  
241 - &__right-icon {  
242 - color: $color-text-caption;  
243 - }  
244 - &__line {  
245 - margin: 0;  
246 - border-bottom-width: 1px;  
247 - border-bottom-style: solid;  
248 - width: 100%;  
249 - transform: scaleY(0.5);  
250 - border-color: rgba(151, 151, 151, 0.2);  
251 - position: absolute;  
252 - bottom: 0;  
253 - right: 0;  
254 - margin-left: $padding-md;  
255 - width: calc(100% - 24rpx);  
256 - }  
257 - &--hover {  
258 - background-color: #f3f4f6;  
259 - }  
260 - }  
261 -  
262 - .loading {  
263 - animation: _loading 1s ease 2;  
264 - }  
265 - @keyframes _loading {  
266 - from {  
267 - transform: rotateZ(0deg);  
268 - }  
269 - to {  
270 - transform: rotateZ(360deg);  
271 - }  
272 - }  
273 - .card-version {  
274 - display: flex;  
275 - align-items: center;  
276 - justify-content: center;  
277 - margin-top: 40rpx;  
278 - font-family: PingFangSC, PingFang SC;  
279 - font-weight: 400;  
280 - font-size: 22rpx;  
281 - color: #999999;  
282 - line-height: 30rpx;  
283 - text-align: left;  
284 - font-style: normal;  
285 - .cell-version {  
286 - margin: 0 8rpx;  
287 - }  
288 - }  
289 -}  
290 -</style>  
291 \ No newline at end of file 0 \ No newline at end of file
pages/order/add.vue 0 → 100644
@@ -0,0 +1,455 @@ @@ -0,0 +1,455 @@
  1 +<template>
  2 + <Page name="order-add" flank>
  3 + <template #content>
  4 + <u-form :model="form" ref="uForm" labelWidth="100">
  5 + <view class="card">
  6 + <u-form-item label="所属项目" required @click="choseProjectCode">
  7 + <u-input v-model="form.projectName" border="none" suffix-icon="arrow-right" placeholder="请选择项目" disabledColor="#ffffff" disabled />
  8 + </u-form-item>
  9 + <u-form-item label="装货时间" @click="showLoadTime = true" required>
  10 + <u-datetime-picker :show="showLoadTime" :value="loadTimeDef" @cancel="showLoadTime = false" @close="showLoadTime = false" @confirm="loadTimeFormat"></u-datetime-picker>
  11 + <u-input v-model="form.loadTime" border="none" suffix-icon="arrow-right" placeholder="请选择时间" disabledColor="#ffffff" disabled />
  12 + </u-form-item>
  13 + <u-form-item label="内部单号">
  14 + <u-input v-model="form.customerOrderCode" border="none" placeholder="请输入,选填" />
  15 + </u-form-item>
  16 + </view>
  17 + <view class="card">
  18 + <u-form-item label="装货地址" required @click="() => selectLocation(0)">
  19 + <u-input :value="form.waypoints[0].address" border="none" suffix-icon="arrow-right" placeholder="请选择" disabledColor="#ffffff" disabled />
  20 + </u-form-item>
  21 + <u-form-item label="卸货地址" required @click="() => selectLocation(1)">
  22 + <u-input v-model="form.waypoints[1].address" border="none" suffix-icon="arrow-right" placeholder="请选择" disabledColor="#ffffff" disabled />
  23 + </u-form-item>
  24 + </view>
  25 + <view class="card">
  26 + <u-form-item label="货物名称" required @click="choseGoodsName">
  27 + <u-input v-model="form.goodsName" border="none" suffix-icon="arrow-right" placeholder="请选择" disabledColor="#ffffff" disabled />
  28 + </u-form-item>
  29 + <u-form-item v-if="showGoodsValue" label="货物价值" required>
  30 + <u-input v-model="form.goodsValue" border="none" type="digit" placeholder="请输入" />
  31 + </u-form-item>
  32 + <u-form-item label="货物件数">
  33 + <u-input v-model="form.goodsPiece" border="none" type="digit" placeholder="请输入,选填" />
  34 + </u-form-item>
  35 + <u-form-item label="货物吨数" required>
  36 + <u-input v-model="form.goodsWeight" border="none" type="digit" placeholder="请输入" />
  37 + </u-form-item>
  38 + <u-form-item label="货物方数">
  39 + <u-input v-model="form.goodsVolume" border="none" type="digit" placeholder="请输入,选填" />
  40 + </u-form-item>
  41 + </view>
  42 + <view class="card">
  43 + <u-form-item label="司机手机" required>
  44 + <u-input v-model="form.mobile" border="none" type="number" placeholder="请输入" @blur="mobileChange" />
  45 + </u-form-item>
  46 + <u-form-item label="司机姓名" required>
  47 + <u-input v-model="form.driverName" border="none" placeholder="请输入" :disabled="!!form.driverId" />
  48 + </u-form-item>
  49 + <view class="payee">
  50 + <payee ref="payee" v-model="payeeModel" :have-action="isCollect" />
  51 + </view>
  52 + <u-form-item label="车牌号" required @click="choseCar('licenseNumber')">
  53 + <u-input v-model="form.licenseNumber" border="none" placeholder="请输入" disabledColor="#ffffff" disabled />
  54 + </u-form-item>
  55 + <u-form-item label="车挂号" @click="choseCar('trailerNumber')">
  56 + <u-input v-model="form.trailerNumber" border="none" placeholder="请输入" disabledColor="#ffffff" disabled />
  57 + </u-form-item>
  58 + </view>
  59 + <view class="card">
  60 + <u-form-item label="应付司机运费">
  61 + <u-input v-model="form.paidAmount" border="none" type="digit" prefix-icon="rmb" placeholder="请输入" @change="computedService" />
  62 + </u-form-item>
  63 + <u-form-item label="油卡" v-if="currentFreight.oilPayFlag">
  64 + <u-input v-model="form.oilAmount" border="none" type="digit" prefix-icon="rmb" placeholder="请输入" @change="computedService" />
  65 + </u-form-item>
  66 + <u-form-item label="预付款" v-if="currentFreight.prePayFlag">
  67 + <u-input v-model="form.prepaidAmount" border="none" type="digit" prefix-icon="rmb" placeholder="请输入" @change="computedService" />
  68 + </u-form-item>
  69 + <u-form-item label="货到款" v-if="currentFreight.arrivalPayFlag">
  70 + <u-input
  71 + v-model="form.deliveryAmount"
  72 + border="none"
  73 + type="digit"
  74 + prefix-icon="rmb"
  75 + :disabled="autoComputedArrival"
  76 + :placeholder="autoComputedArrival ? '自动计算' : '请输入'"
  77 + @change="computedService"
  78 + />
  79 + </u-form-item>
  80 + <u-form-item label="尾款/回单付">
  81 + <u-input
  82 + v-model="form.balancePaymentAmount"
  83 + border="none"
  84 + type="digit"
  85 + prefix-icon="rmb"
  86 + @change="computedService"
  87 + :disabled="!autoComputedArrival"
  88 + :placeholder="!autoComputedArrival ? '自动计算' : '请输入'"
  89 + />
  90 + </u-form-item>
  91 + </view>
  92 + <view class="card" @tap="more = !more">
  93 + <view class="more-action">
  94 + {{ !more ? '展开更多信息' : '收起更多信息' }}
  95 + <view class="sx-img">
  96 + <image v-if="more" class="sx-image up" :src="formatImagePath('down')"></image>
  97 + <image v-else class="sx-image" :src="formatImagePath('down')"></image>
  98 + </view>
  99 + </view>
  100 + </view>
  101 + <template v-if="more">
  102 + <view class="card">
  103 + <u-form-item label="装货联系人">
  104 + <u-input v-model="form.waypoints[0].contactName" border="none" placeholder="请输入,选填" />
  105 + </u-form-item>
  106 + <u-form-item label="装货联系电话">
  107 + <u-input v-model="form.waypoints[0].contactMobile" border="none" placeholder="请输入,选填" />
  108 + </u-form-item>
  109 + </view>
  110 + <view class="card">
  111 + <u-form-item label="卸货联系人">
  112 + <u-input v-model="form.waypoints[1].contactName" border="none" placeholder="请输入,选填" />
  113 + </u-form-item>
  114 + <u-form-item label="卸货联系电话">
  115 + <u-input v-model="form.waypoints[1].contactMobile" border="none" placeholder="请输入,选填" />
  116 + </u-form-item>
  117 + </view>
  118 + <view class="card">
  119 + <u-form-item label="订单备注">
  120 + <u-input v-model="form.remark" border="none" placeholder="请输入,选填" />
  121 + </u-form-item>
  122 + </view>
  123 + </template>
  124 + </u-form>
  125 + </template>
  126 + <template #footer>
  127 + <u-button type="primary" @tap="submitAddFun">下单并指派</u-button>
  128 + </template>
  129 + <u-toast ref="uToast"></u-toast>
  130 + <popup-platenumber :visible="showCar" @update:visible="e => (showCar = e)" @confirm="carConfirm" v-model="carNumber"></popup-platenumber>
  131 + </Page>
  132 +</template>
  133 +<script>
  134 +import { urlParam } from '@/utils/param';
  135 +import dayjs from 'dayjs';
  136 +import payee from '../../components/card/payee.vue';
  137 +import PopupPlatenumber from '../../components/popup/popup-platenumber.vue';
  138 +export default {
  139 + name: 'order-add',
  140 + components: { PopupPlatenumber, payee },
  141 + data() {
  142 + return {
  143 + carNumber: '',
  144 + showLoadTime: false,
  145 + loadTimeDef: new Date(),
  146 + showCar: false,
  147 + typeCar: '',
  148 + more: false,
  149 + radioList: [],
  150 + form: {
  151 + projectCode: '',
  152 + loadTime: '',
  153 + projectName: '',
  154 + customerOrderCode: '',
  155 + goodsName: '',
  156 + goodsValue: '',
  157 + goodsPiece: '',
  158 + goodsWeight: '',
  159 + goodsVolume: '',
  160 + mobile: '',
  161 + driverId: '',
  162 + driverName: '',
  163 + licenseNumber: '',
  164 + trailerNumber: '',
  165 + paidAmount: '',
  166 + oilAmount: '',
  167 + prepaidAmount: '',
  168 + deliveryAmount: '',
  169 + balancePaymentAmount: '',
  170 + distance: '',
  171 + allowDriverSeeFreightAmountNode: '',
  172 + waypoints: [{}, {}],
  173 + },
  174 + payeeModel: {},
  175 + currentFreight: {},
  176 + };
  177 + },
  178 + computed: {
  179 + isCollect() {
  180 + return this.currentFreight.collectByOtherFlag || false;
  181 + },
  182 + autoComputedArrival() {
  183 + // 自动计算货到
  184 + return 'OUT_INVITE_ARRIVAL' === this.currentFreight?.autoComputeFeeType;
  185 + },
  186 + // 获取价值
  187 + showGoodsValue() {
  188 + return this.currentFreight ? this.currentFreight.driverSecurityServiceFlag || this.currentFreight.securityServiceFlag : false;
  189 + },
  190 + },
  191 + onLoad(option) {
  192 + if (option.code) {
  193 + this.initData(option.code);
  194 + }
  195 + this.initConfig();
  196 + },
  197 + methods: {
  198 + initConfig() {
  199 + uni.$u.api.freightOrder.currentFreight({}).then(en => {
  200 + this.currentFreight = en?.result || {};
  201 + this.form.allowDriverSeeFreightAmountNode = this.currentFreight.allowDriverSeeFreightAmountNode;
  202 + });
  203 + uni.$u.api.filter.projectCode({}).then(res => {
  204 + if (res.success && res.result && res.result.length === 1) {
  205 + this.form.projectCode = res.result[0].code;
  206 + this.form.projectName = res.result[0].name;
  207 + }
  208 + });
  209 + },
  210 + initData(code) {
  211 + uni.$u.api.freightOrder.getDetail({ code }).then(res => {
  212 + let detail = res.result || {};
  213 + ['goodsName', 'waypoints', 'allowDriverSeeFreightAmountNode', 'projectCode', 'projectName'].forEach(key => {
  214 + this.form[key] = detail[key];
  215 + });
  216 + this.computedDistance();
  217 + });
  218 + },
  219 + choseProjectCode() {
  220 + uni.$once('select-common', option => {
  221 + this.form.projectCode = option.code;
  222 + this.form.projectName = option.name;
  223 + });
  224 + uni.navigateTo({
  225 + url: `/pages/global/search-common${urlParam({
  226 + mode: 'select',
  227 + url: 'projectCode',
  228 + title: '项目',
  229 + label: 'name',
  230 + value: '',
  231 + params: '{"status":"ENABLE"}',
  232 + })}`,
  233 + });
  234 + },
  235 + choseGoodsName() {
  236 + uni.$once('select-common', option => {
  237 + this.form.goodsName = option.name;
  238 + });
  239 + uni.navigateTo({
  240 + url: `/pages/global/search-common${urlParam({
  241 + mode: 'select',
  242 + url: 'goodsName',
  243 + title: '货物名称',
  244 + label: 'name',
  245 + value: '',
  246 + })}`,
  247 + });
  248 + },
  249 + // 地图选点
  250 + selectLocation(index) {
  251 + uni.$once('webview-select', location => {
  252 + let station = {
  253 + lng: location.lng,
  254 + lat: location.lat,
  255 + provinceCode: location.provinceCode,
  256 + provinceName: location.provinceName,
  257 + cityCode: location.cityCode,
  258 + cityName: location.cityName,
  259 + areaCode: location.areaCode,
  260 + areaName: location.areaName,
  261 + address: (location.provinceName || '') + (location.cityName || '') + (location.areaName || '') + (location.address || ''),
  262 + };
  263 + let waypoints = index === 0 ? [station, this.form.waypoints[1]] : [this.form.waypoints[0], station];
  264 + this.form = {
  265 + ...this.form,
  266 + waypoints,
  267 + };
  268 + this.computedDistance();
  269 + });
  270 + const url = 'https://zeyi-tms-product.oss-cn-hangzhou.aliyuncs.com/webview/location-wx.html';
  271 + const params = {
  272 + lat: this.form.waypoints[index].lat ? Number(this.form.waypoints[index].lat) : '',
  273 + lng: this.form.waypoints[index].lng ? Number(this.form.waypoints[index].lng) : '',
  274 + };
  275 + uni.navigateTo({ url: `/pages/common/webview?url=${url}&query=${JSON.stringify(params)}` });
  276 + },
  277 + computedDistance() {
  278 + if (this.form.waypoints[0].lng && this.form.waypoints[1].lng) {
  279 + uni.$u.api.freightOrder
  280 + .getDistance({
  281 + startLat: this.form.waypoints[0].lat,
  282 + startLng: this.form.waypoints[0].lng,
  283 + endLat: this.form.waypoints[1].lat,
  284 + endLng: this.form.waypoints[1].lng,
  285 + })
  286 + .then(res => {
  287 + this.form.distance = res.result;
  288 + });
  289 + }
  290 + },
  291 + loadTimeFormat({ value }) {
  292 + this.form.loadTime = dayjs(value).format('YYYY-MM-DD HH:mm:ss');
  293 + this.showLoadTime = false;
  294 + },
  295 + mobileChange() {
  296 + if (this.form.mobile && this.form.mobile.length === 11) {
  297 + uni.$u.api.filter.driver({ query: this.form.mobile }).then(res => {
  298 + if (res.success && res.result && res.result.length === 1) {
  299 + this.form.driverId = res.result[0].id;
  300 + this.form.driverName = res.result[0].name;
  301 + this.form.driverMobile = res.result[0].mobile;
  302 + this.payeeModel = res.result[0];
  303 + this.$refs.payee.setItem(this.payeeModel);
  304 + } else {
  305 + this.form.driverId = '';
  306 + this.form.driverName = '';
  307 + this.form.driverMobile = this.form.mobile;
  308 + this.payeeModel = {};
  309 + this.$refs.payee.setItem(this.payeeModel);
  310 + }
  311 + });
  312 + }
  313 + },
  314 + vehicleChange(v) {
  315 + if (this.typeCar === 'licenseNumber') {
  316 + // 车头
  317 + uni.$u.api.filter.vehicle({ query: v, operationModeList: 'OUT_INVITE' }).then(res => {
  318 + if (res.success && res.result && res.result.length === 1) {
  319 + let item = res.result[0];
  320 + this.form.vehicleCode = item.code;
  321 + this.form.specification = item.specification;
  322 + if (item && item.type === 'TRACTOR' && item.vehicleList && item.vehicleList.length > 0) {
  323 + this.form.trailerNumber = item.vehicleList[0].licenseNumber;
  324 + this.form.trailerCode = item.vehicleList[0].code;
  325 + this.form.specification = item.vehicleList[0].specification;
  326 + }
  327 + } else {
  328 + this.form.vehicleCode = '';
  329 + this.form.specification = '';
  330 + this.form.trailerCode = '';
  331 + this.form.trailerNumber = '';
  332 + }
  333 + });
  334 + } else {
  335 + uni.$u.api.filter.vehicle({ query: v, operationModeList: 'OUT_INVITE' }).then(res => {
  336 + if (res.success && res.result && res.result.length === 1) {
  337 + let item = res.result[0];
  338 + this.form.trailerCode = item.code;
  339 + this.form.specification = item.specification;
  340 + } else {
  341 + this.form.trailerCode = '';
  342 + this.form.specification = '';
  343 + }
  344 + });
  345 + }
  346 + },
  347 + choseCar(type) {
  348 + this.typeCar = type;
  349 + this.carNumber = '';
  350 + this.showCar = true;
  351 + },
  352 + carConfirm(v) {
  353 + this.form[this.typeCar] = v;
  354 + this.showCar = false;
  355 + this.vehicleChange(v);
  356 + },
  357 + computedService() {
  358 + uni.$u.debounce(this.getServiceAmountInfo, 500);
  359 + },
  360 + getServiceAmountInfo() {
  361 + const { paidAmount = '', oilAmount = '', deliveryAmount = '', prepaidAmount = '', balancePaymentAmount = '', goodsName = '', goodsValue = '' } = this.form;
  362 + let params = {
  363 + paidAmount,
  364 + deliveryAmount,
  365 + prepaidAmount,
  366 + oilAmount,
  367 + balancePaymentAmount,
  368 + goodsName,
  369 + goodsValue,
  370 + };
  371 + uni.$u.api.freightOrder.getServiceAmount(params).then(res => {
  372 + if (res.success) {
  373 + this.form.paidAmount = res.result.paidAmount || paidAmount;
  374 + this.form.deliveryAmount = res.result.deliveryAmount || deliveryAmount;
  375 + this.form.prepaidAmount = res.result.prepaidAmount || prepaidAmount;
  376 + this.form.oilAmount = res.result.oilAmount || oilAmount;
  377 + this.form.balancePaymentAmount = res.result.balancePaymentAmount || balancePaymentAmount;
  378 + this.form.oilPayRebateRate = res.result.oilPayRebateRate || '';
  379 + this.form.driverSecurityServiceAmount = res.result.driverSecurityServiceAmount || '';
  380 + this.form.securityServiceAmount = res.result.securityServiceAmount || '';
  381 + this.form.serviceAmount = res.result.serviceAmount || '';
  382 + this.form.serviceRate = res.result.serviceRate || '';
  383 + }
  384 + });
  385 + },
  386 + submitAddFun() {
  387 + let totalAmount = Number(this.form.paidAmount || 0) + Number(this.form.serviceAmount || 0) + Number(this.form.securityServiceAmount || 0);
  388 + uni.$u.api.freightOrder
  389 + .add({ ...this.form, totalAmount, payeeId: this.payeeModel.driverId })
  390 + .then(res => {
  391 + if (res.success) {
  392 + uni.showToast({ title: '下单成功', icon: 'none' });
  393 + this.getOpenerEventChannel().emit('refreshData');
  394 + setTimeout(() => uni.navigateBack(), 500);
  395 + }
  396 + })
  397 + .catch(e => {
  398 + this.$refs.uToast.show({
  399 + type: 'default',
  400 + message: e,
  401 + });
  402 + });
  403 + },
  404 + },
  405 +};
  406 +</script>
  407 +<style lang="scss">
  408 +.page-order-add {
  409 + &__footer {
  410 + background: $color-white;
  411 + }
  412 + .payee {
  413 + margin-right: $padding-xs;
  414 + margin-left: $padding-xs;
  415 + }
  416 + .card {
  417 + color: #999999;
  418 + margin-bottom: $padding-md;
  419 + background-color: $color-white;
  420 + border-radius: $radius-md;
  421 + box-shadow: $shadow-normal;
  422 + .u-form-item {
  423 + padding-left: $padding-md !important;
  424 + padding-right: $padding-sm !important;
  425 + }
  426 + .u-form-item + .u-form-item {
  427 + border-top: 1px solid #f6f6f6;
  428 + }
  429 + .more-action {
  430 + display: flex;
  431 + padding: $padding-sm;
  432 + justify-content: center;
  433 + align-content: center;
  434 + align-items: center;
  435 + .sx-img {
  436 + height: 12upx;
  437 + width: 14upx;
  438 + position: relative;
  439 + margin-left: 12upx;
  440 +
  441 + .sx-image {
  442 + width: 100%;
  443 + height: 100%;
  444 + position: absolute;
  445 + top: 0;
  446 + left: 0;
  447 + }
  448 + .up {
  449 + transform: rotate(180deg);
  450 + }
  451 + }
  452 + }
  453 + }
  454 +}
  455 +</style>
pages/order/again-assign.vue 0 → 100644
@@ -0,0 +1,268 @@ @@ -0,0 +1,268 @@
  1 +<template>
  2 + <Page name="again-assign" flank>
  3 + <template #content>
  4 + <view class="card">
  5 + <view class="label">原指派信息</view>
  6 + <view class="line-solid"></view>
  7 + <view class="item">
  8 + <view class="item_field">承运司机</view>
  9 + <view class="item_content">
  10 + <text>{{ item.driverName }}</text>
  11 + <text>{{ item.driverMobile }}</text>
  12 + </view>
  13 + </view>
  14 + <view class="item">
  15 + <view class="item_field">收款人</view>
  16 + <view class="item_content">
  17 + <text>{{ item.payee }}</text>
  18 + <text>{{ item.payeeMobile }}</text>
  19 + </view>
  20 + </view>
  21 + <payee :value="oldPayeeModel"></payee>
  22 + <view class="item">
  23 + <view class="item_field">车牌号</view>
  24 + <view class="item_content">{{ item.vehicleLicenseNum ? item.vehicleLicenseNum : '' }}</view>
  25 + </view>
  26 + <view class="item">
  27 + <view class="item_field">车挂号</view>
  28 + <view class="item_content">{{ item.trailerLicenseNum ? item.trailerLicenseNum : '' }}</view>
  29 + </view>
  30 + </view>
  31 + <view class="card border-action">
  32 + <view class="label text-action">新指派信息</view>
  33 + <view class="line-solid"></view>
  34 + <u-form :model="form" ref="uForm" labelWidth="100">
  35 + <view class="line">
  36 + <u-form-item label="司机手机">
  37 + <u-input v-model="form.mobile" border="none" type="number" placeholder="请输入司机手机号" @blur="mobileChange" />
  38 + </u-form-item>
  39 + </view>
  40 + <view class="line">
  41 + <u-form-item label="司机姓名">
  42 + <u-input v-model="form.driverName" border="none" placeholder="请输入司机姓名" />
  43 + </u-form-item>
  44 + <view class="payee">
  45 + <payee :value="payeeModel" :have-action="isCollect"></payee>
  46 + </view>
  47 + </view>
  48 + <view class="line">
  49 + <u-form-item label="车牌号" @click="choseCar('licenseNumber')">
  50 + <u-input v-model="form.licenseNumber" border="none" placeholder="请输入车牌号" disabledColor="#ffffff" disabled />
  51 + </u-form-item>
  52 + </view>
  53 + <view class="line">
  54 + <u-form-item label="车挂号" @click="choseCar('trailerNumber')">
  55 + <u-input v-model="form.trailerNumber" border="none" placeholder="请输入车挂号" disabledColor="#ffffff" disabled />
  56 + </u-form-item>
  57 + </view>
  58 + </u-form>
  59 + </view>
  60 + </template>
  61 + <template #footer>
  62 + <u-button type="primary" @tap="submit">确认更改</u-button>
  63 + </template>
  64 + <popup-platenumber :visible="showCar" @update:visible="e => (showCar = e)" @confirm="carConfirm" v-model="carNumber"></popup-platenumber>
  65 + </Page>
  66 +</template>
  67 +
  68 +<script>
  69 +import Payee from '../../components/card/payee.vue';
  70 +import PopupPlatenumber from '../../components/popup/popup-platenumber.vue';
  71 +
  72 +export default {
  73 + name: 'again-assign',
  74 + components: { PopupPlatenumber, Payee },
  75 + data() {
  76 + return {
  77 + typeCar: '',
  78 + carNumber: '',
  79 + showCar: false,
  80 + payeeModel: {},
  81 + form: {
  82 + mobile: '',
  83 + driverName: '',
  84 + driverMobile: '',
  85 + driverId: '',
  86 + vehicleCode: '', // 车辆ID
  87 + licenseNumber: '', // 车牌号
  88 + trailerCode: '', // 车挂ID
  89 + trailerNumber: '', // 车挂号
  90 + updatePayeeFlag: true,
  91 + },
  92 + item: {},
  93 + currentFreight: {},
  94 + };
  95 + },
  96 + computed: {
  97 + isCollect() {
  98 + return this.currentFreight.collectByOtherFlag || false;
  99 + },
  100 + oldPayeeModel() {
  101 + return this.item.payee
  102 + ? {
  103 + dueBank: this.item.payee,
  104 + dueBankCardNo: this.item.dueBankCardNo,
  105 + openingBank: this.item.openingBank,
  106 + }
  107 + : {};
  108 + },
  109 + },
  110 + onLoad(options) {
  111 + if (options.code) {
  112 + this.initData(options.code);
  113 + }
  114 + },
  115 + methods: {
  116 + initData(code) {
  117 + uni.$u.api.freightOrder.currentFreight({}).then(en => {
  118 + this.currentFreight = en?.result || {};
  119 + });
  120 + uni.$u.api.freightOrder.getDetail({ code }).then(res => {
  121 + this.item = res.result || {};
  122 + });
  123 + },
  124 + mobileChange() {
  125 + if (this.form.mobile && this.form.mobile.length === 11) {
  126 + uni.$u.api.filter.driver({ query: this.form.mobile }).then(res => {
  127 + if (res.success && res.result && res.result.length === 1) {
  128 + this.form.driverId = res.result[0].id;
  129 + this.form.driverName = res.result[0].name;
  130 + this.form.driverMobile = res.result[0].mobile;
  131 + this.payeeModel = res.result[0];
  132 + } else {
  133 + this.form.driverId = '';
  134 + this.form.driverName = '';
  135 + this.payeeModel = {};
  136 + }
  137 + });
  138 + }
  139 + },
  140 + vehicleChange(v) {
  141 + if (this.typeCar === 'licenseNumber') {
  142 + // 车头
  143 + uni.$u.api.filter.vehicle({ query: v, operationModeList: 'OUT_INVITE' }).then(res => {
  144 + if (res.success && res.result && res.result.length === 1) {
  145 + let item = res.result[0];
  146 + this.form.vehicleCode = item.code;
  147 + this.form.specification = item.specification;
  148 + if (item && item.type === 'TRACTOR' && item.vehicleList && item.vehicleList.length > 0) {
  149 + this.form.trailerNumber = item.vehicleList[0].licenseNumber;
  150 + this.form.trailerCode = item.vehicleList[0].code;
  151 + this.form.specification = item.vehicleList[0].specification;
  152 + }
  153 + } else {
  154 + this.form.vehicleCode = '';
  155 + this.form.specification = '';
  156 + this.form.trailerCode = '';
  157 + this.form.trailerNumber = '';
  158 + }
  159 + });
  160 + } else {
  161 + uni.$u.api.filter.vehicle({ query: v, operationModeList: 'OUT_INVITE' }).then(res => {
  162 + if (res.success && res.result && res.result.length === 1) {
  163 + let item = res.result[0];
  164 + this.form.trailerCode = item.code;
  165 + this.form.specification = item.specification;
  166 + } else {
  167 + this.form.trailerCode = '';
  168 + this.form.specification = '';
  169 + }
  170 + });
  171 + }
  172 + },
  173 + choseCar(type) {
  174 + this.typeCar = type;
  175 + this.carNumber = '';
  176 + this.showCar = true;
  177 + },
  178 + carConfirm(v) {
  179 + this.form[this.typeCar] = v;
  180 + this.showCar = false;
  181 + this.vehicleChange(v);
  182 + },
  183 + submit() {
  184 + uni.$u.api.freightOrder.assignVehicle({ ...this.form, code: this.item.code, payeeId: this.payeeModel.driverId }).then(res => {
  185 + if (res.success) {
  186 + uni.showToast({ title: '操作成功', icon: 'none' });
  187 + this.getOpenerEventChannel().emit('refreshData');
  188 + setTimeout(() => uni.navigateBack(), 500);
  189 + }
  190 + });
  191 + },
  192 + },
  193 +};
  194 +</script>
  195 +
  196 +<style lang="scss">
  197 +.page-again-assign {
  198 + &__footer {
  199 + background: $color-white;
  200 + }
  201 +
  202 + .card {
  203 + color: #999999;
  204 + margin-bottom: $padding-md;
  205 + padding: $padding-md;
  206 + background-color: $color-white;
  207 + border-radius: $radius-md;
  208 + box-shadow: $shadow-normal;
  209 +
  210 + .label {
  211 + padding-bottom: $padding-sm;
  212 + font-weight: 500;
  213 + font-size: 30upx;
  214 + color: #2b2a27;
  215 + line-height: 34upx;
  216 + text-align: left;
  217 + font-style: normal;
  218 + }
  219 +
  220 + .line-solid {
  221 + border-bottom: 1px solid #dddddd;
  222 + }
  223 +
  224 + .text-action {
  225 + padding-left: $padding-md;
  226 + color: $color-primary;
  227 + }
  228 + .item {
  229 + margin-top: $padding-md;
  230 + display: flex;
  231 + &_field {
  232 + font-weight: 400;
  233 + font-size: 28upx;
  234 + line-height: 28upx;
  235 + color: #999999;
  236 + width: 170upx;
  237 + text-align: left;
  238 + }
  239 +
  240 + &_content {
  241 + flex: 1;
  242 + font-weight: 400;
  243 + font-size: 28upx;
  244 + line-height: 28upx;
  245 + color: #2b2a27;
  246 + text-align: left;
  247 + font-style: normal;
  248 + }
  249 + }
  250 + .line {
  251 + border-bottom: 1px solid #dddddd;
  252 + .u-form-item {
  253 + padding-left: $padding-md !important;
  254 + padding-right: $padding-sm !important;
  255 + }
  256 + .payee {
  257 + padding-left: $padding-md;
  258 + padding-right: $padding-md;
  259 + }
  260 + }
  261 + }
  262 + .border-action {
  263 + padding-left: 0 !important;
  264 + padding-right: 0 !important;
  265 + border: 1px solid $color-primary;
  266 + }
  267 +}
  268 +</style>
pages/order/arrival-car.vue 0 → 100644
@@ -0,0 +1,133 @@ @@ -0,0 +1,133 @@
  1 +<template>
  2 + <Page name="start-car">
  3 + <template #content>
  4 + <view class="address">
  5 + <view class="icon-waypoint icon-end">卸</view>
  6 + <text>{{ item.waypoints[1].address }}</text>
  7 + </view>
  8 + <u-form :model="form" ref="uForm" labelWidth="100">
  9 + <view class="card">
  10 + <u-form-item label="实际发车时间" required @click="(timeType = 'departTime'), (showLoadTime = true)">
  11 + <u-input v-model="form.departTime" border="none" suffix-icon="arrow-right" placeholder="请选择时间" disabledColor="#ffffff" disabled />
  12 + </u-form-item>
  13 + </view>
  14 + <view class="card">
  15 + <u-form-item label="实际到达时间" required @click="(timeType = 'arrivalTime'), (showLoadTime = true)">
  16 + <u-input v-model="form.arrivalTime" border="none" suffix-icon="arrow-right" placeholder="请选择时间" disabledColor="#ffffff" disabled />
  17 + </u-form-item>
  18 + </view>
  19 + <view class="card">
  20 + <u-form-item label="上传回单">
  21 + <z-upload v-model="form.receiptAttachment" :limit="20"></z-upload>
  22 + </u-form-item>
  23 + </view>
  24 + </u-form>
  25 + </template>
  26 + <template #footer>
  27 + <u-button type="primary" @tap="submit">确认到达</u-button>
  28 + </template>
  29 + <u-datetime-picker :show="showLoadTime" :value="loadTimeDef" @cancel="showLoadTime = false" @close="showLoadTime = false" @confirm="loadTimeFormat"></u-datetime-picker>
  30 + </Page>
  31 +</template>
  32 +
  33 +<script>
  34 +import ZUpload from '../../components/zee/z-upload.vue';
  35 +import dayjs from 'dayjs';
  36 +
  37 +export default {
  38 + name: 'arrivalCar',
  39 + components: { ZUpload },
  40 + data() {
  41 + return {
  42 + timeType: '',
  43 + showLoadTime: false,
  44 + loadTimeDef: new Date(),
  45 + form: {
  46 + departTime: '',
  47 + arrivalTime: '',
  48 + receiptAttachment: '',
  49 + },
  50 + item: {},
  51 + };
  52 + },
  53 + onLoad(options) {
  54 + if (options.code) {
  55 + this.initData(options.code);
  56 + }
  57 + },
  58 + methods: {
  59 + initData(code) {
  60 + uni.$u.api.freightOrder.getDetail({ code }).then(res => {
  61 + this.item = res.result || {};
  62 + this.form = {
  63 + departTime: this.item.confirmDepartureTime,
  64 + arrivalTime: this.item.confirmArrivalTime,
  65 + receiptAttachment: this.item.receiptAttachment,
  66 + };
  67 + });
  68 + },
  69 + loadTimeFormat({ value }) {
  70 + this.form[this.timeType] = dayjs(value).format('YYYY-MM-DD HH:mm:ss');
  71 + this.showLoadTime = false;
  72 + },
  73 + submit() {
  74 + if (!this.form.departTime || !this.form.departTime) {
  75 + uni.showToast({ title: '发车时间和到达时间不能为空', icon: 'none' });
  76 + return;
  77 + }
  78 + if (new Date(this.form.departTime).getTime() > new Date().getTime()) {
  79 + uni.showToast({ title: '发车时间不能大于当前时间', icon: 'none' });
  80 + return;
  81 + }
  82 + if (new Date(this.form.arrivalTime).getTime() > new Date().getTime()) {
  83 + uni.showToast({ title: '到达时间不能大于当前时间', icon: 'none' });
  84 + return;
  85 + }
  86 + if (new Date(this.form.departTime).getTime() > new Date(this.form.arrivalTime).getTime()) {
  87 + uni.showToast({ title: '到达时间不能小于发车时间', icon: 'none' });
  88 + return;
  89 + }
  90 + uni.$u.api.freightOrder.arrive({ codeList: [this.item.code], ...this.form }).then(res => {
  91 + if (res.success) {
  92 + uni.showToast({ title: '操作成功', icon: 'none' });
  93 + this.getOpenerEventChannel().emit('refreshData');
  94 + setTimeout(() => uni.navigateBack(), 500);
  95 + }
  96 + });
  97 + },
  98 + },
  99 +};
  100 +</script>
  101 +
  102 +<style lang="scss">
  103 +.page-start-car {
  104 + &__content {
  105 + padding-top: 0 !important;
  106 + }
  107 + &__footer {
  108 + background: $color-white;
  109 + }
  110 + .address {
  111 + background-color: $color-white;
  112 + padding: $padding-md;
  113 + .icon-waypoint {
  114 + font-size: $font-sm;
  115 + margin-right: $padding-sm;
  116 + height: $padding-md * 1.2;
  117 + width: $padding-md * 1.2;
  118 + min-width: $padding-md * 1.2;
  119 + }
  120 + }
  121 + .card {
  122 + color: #999999;
  123 + margin: $padding-md;
  124 + background-color: $color-white;
  125 + border-radius: $radius-md;
  126 + box-shadow: $shadow-normal;
  127 + .u-form-item {
  128 + padding-left: $padding-md !important;
  129 + padding-right: $padding-sm !important;
  130 + }
  131 + }
  132 +}
  133 +</style>
pages/order/card.vue 0 → 100644
@@ -0,0 +1,320 @@ @@ -0,0 +1,320 @@
  1 +<template>
  2 + <view class="card-order">
  3 + <view class="card-order__header">
  4 + <view class="title">
  5 + <view class="order-no">
  6 + <field-copy :value="item.code" v-if="item.code">{{ item.code }} </field-copy>
  7 + <view class="image" @click.stop="qrShow">
  8 + <image style="height: 30upx; width: 30upx" src="/static/qr.png"></image>
  9 + </view>
  10 + </view>
  11 + <render-dict v-if="item.status" class="status" :style="{ color: colorMap[item.status] }" dict="FREIGHT_ORDER_STATUS" :value="item.status"></render-dict>
  12 + </view>
  13 + </view>
  14 + <view class="card-order__item"> {{ item.projectName }} | {{ item.loadTime }}装货 </view>
  15 + <view class="card-order__steps">
  16 + <view class="step">
  17 + <view class="step-item">
  18 + <view class="icon-waypoint icon-start">装</view>
  19 + <view>
  20 + <view class="city">{{ item.startCityName }}-{{ item.startAreaName }}</view>
  21 + <view class="address">{{ item.startAddress }}</view>
  22 + </view>
  23 + </view>
  24 + <view class="step-item">
  25 + <view class="icon-waypoint icon-end">卸</view>
  26 + <view>
  27 + <view class="city">{{ item.endCityName }}-{{ item.endAreaName }}</view>
  28 + <view class="address">{{ item.endAddress }}</view>
  29 + </view>
  30 + </view>
  31 + </view>
  32 + </view>
  33 + <view class="card-order__tags">
  34 + <view class="tag--warning" v-if="item.driverCertifiedStatus === 'NOT_CERTIFIED'">司机未认证</view>
  35 + <view class="tag--paying" v-if="item.driverCertifiedStatus === 'CERTIFYING'">司机认证中</view>
  36 + <view class="tag--warning" v-if="item.payeeMobile && item.bindBankCardNoFlag === false">收款人未绑卡</view>
  37 + <view class="tag--warning" v-if="item.vehicleLicenseNum && item.vehicleCertifiedStatus === 'NOT_CERTIFIED' && !item.trailerLicenseNum">车辆未认证</view>
  38 + <view class="tag--paying" v-if="item.vehicleLicenseNum && item.vehicleCertifiedStatus === 'CERTIFYING' && !item.trailerLicenseNum">车辆认证中</view>
  39 + <view class="tag--warning" v-if="item.vehicleLicenseNum && item.vehicleCertifiedStatus === 'NOT_CERTIFIED' && item.trailerLicenseNum">车头未认证</view>
  40 + <view class="tag--paying" v-if="item.vehicleLicenseNum && item.vehicleCertifiedStatus === 'CERTIFYING' && item.trailerLicenseNum">车头认证中</view>
  41 + <view class="tag--warning" v-if="item.trailerLicenseNum && !item.extraTrailerFlag && item.trailerVehicleCertifiedStatus === 'NOT_CERTIFIED'">车挂未认证</view>
  42 + <view class="tag--paying" v-if="item.trailerLicenseNum && !item.extraTrailerFlag && item.trailerVehicleCertifiedStatus === 'CERTIFYING'">车挂认证中</view>
  43 + <text class="tag--warning" v-if="item.extraTrailerFlag">多车挂</text>
  44 + <text class="tag--warning" v-if="item.missTrailerFlag">缺车挂</text>
  45 + </view>
  46 + <view class="card-order__item">
  47 + {{ item.driverName ? item.driverName : '' }} {{ item.driverMobile ? item.driverMobile : '' }} | {{ item.vehicleLicenseNum ? item.vehicleLicenseNum : '' }}
  48 + {{ item.trailerLicenseNum ? item.trailerLicenseNum : '' }}
  49 + </view>
  50 + <view class="card-order__footer">
  51 + <view class="amount">
  52 + 运费<text class="red">¥{{ item.freightAmount }}</text>
  53 + </view>
  54 + <view class="action">
  55 + <zb-tooltip placement="bottom" :visible="visible" @update:visible="e => (visible = e)">
  56 + <template #content>
  57 + <view class="more-action">
  58 + <view v-if="$permission('/freightOrder/add')" @tap="againOne"> 再来一单 </view>
  59 + <view v-if="$permission('/freightOrder/delete') && ['CANCEL'].includes(item.status)" @tap="deleteOrder"> 删除订单 </view>
  60 + <view v-if="$permission('/freightOrder/cancel') && ['WAIT_CONFIRM', 'WAIT_ACCEPT', 'WAIT_DEPART'].includes(item.status)" @tap="cancelOrder"> 取消订单 </view>
  61 + </view>
  62 + </template>
  63 + <view class="button">
  64 + 更多操作
  65 + <view class="sx-img">
  66 + <image class="sx-image" :src="formatImagePath('down')"></image>
  67 + </view>
  68 + </view>
  69 + </zb-tooltip>
  70 + <view v-if="['WAIT_ACCEPT', 'WAIT_DEPART'].includes(item.status) && $permission('/freightOrder/depart')" class="button primary" @click.stop="start">确认发车</view>
  71 + <view v-if="['TRANSFER'].includes(item.status) && $permission('/freightOrder/arrive')" class="button primary" @click.stop="arrival">确认到达</view>
  72 + <view v-if="item.status === 'COMPLETED' && !item.receiptAttachment && $permission('/freightOrder/modifyReceiptAttachment')" class="button primary" @click.stop="uploadReceipt"
  73 + >上传回单</view
  74 + >
  75 + </view>
  76 + </view>
  77 + </view>
  78 +</template>
  79 +<script>
  80 +import ZbTooltip from '../../uni_modules/zb-tooltip/components/zb-tooltip/zb-tooltip.vue';
  81 +import FieldCopy from '../../components/field/field-copy.vue';
  82 +import page from '../../mixins/page';
  83 +
  84 +export default {
  85 + name: 'order-card',
  86 + mixins: [page],
  87 + components: { ZbTooltip, FieldCopy },
  88 + props: {
  89 + item: {
  90 + type: Object,
  91 + default() {
  92 + return {};
  93 + },
  94 + },
  95 + },
  96 + data() {
  97 + return {
  98 + visible: false,
  99 + colorMap: {
  100 + WAIT_CONFIRM: '#F52723',
  101 + WAIT_ACCEPT: '#FF9339',
  102 + WAIT_DEPART: '#666666',
  103 + TRANSFER: '#2673FB',
  104 + COMPLETED: '#00B87A',
  105 + CANCEL: '#999999',
  106 + },
  107 + };
  108 + },
  109 + methods: {
  110 + againOne() {
  111 + this.visible = false;
  112 + this.$emit('more', this.item.code);
  113 + },
  114 + cancelOrder() {
  115 + this.visible = false;
  116 + this.$emit('cancel', this.item.code);
  117 + },
  118 + deleteOrder() {
  119 + this.visible = false;
  120 + this.$emit('delete', this.item.code);
  121 + },
  122 + start() {
  123 + this.$emit('start', this.item.code);
  124 + },
  125 + arrival() {
  126 + this.$emit('arrival', this.item.code);
  127 + },
  128 + uploadReceipt() {
  129 + this.$emit('uploadReceipt', this.item.code);
  130 + },
  131 + qrShow() {
  132 + this.$emit('qrShow', this.item.code, this.item);
  133 + },
  134 + },
  135 +};
  136 +</script>
  137 +
  138 +<style scoped lang="scss">
  139 +.card-order {
  140 + background-color: $color-white;
  141 + color: $color-text;
  142 + padding: $padding-sm;
  143 + margin-bottom: $padding-sm;
  144 + border-radius: $radius-md;
  145 + box-shadow: $shadow-normal;
  146 + font-size: $font-md;
  147 + &__header {
  148 + display: flex;
  149 + align-items: center;
  150 + border-bottom: 1px solid $color-border;
  151 + padding-bottom: $padding-sm;
  152 + margin-bottom: $padding-sm;
  153 + .title {
  154 + width: 100%;
  155 + display: flex;
  156 + flex-direction: row;
  157 + align-items: center;
  158 + justify-content: space-between;
  159 + .order-no {
  160 + display: flex;
  161 + align-items: center;
  162 + .image {
  163 + width: 30upx;
  164 + height: 30upx;
  165 + margin-left: 20upx;
  166 + }
  167 + }
  168 + .status {
  169 + color: $color-primary;
  170 + font-weight: bold;
  171 + }
  172 + }
  173 + .title-notice {
  174 + display: flex;
  175 + align-items: center;
  176 + color: $color-red;
  177 + .u-icon {
  178 + margin-right: $padding-xs;
  179 + font-size: $font-lg;
  180 + }
  181 + }
  182 + .tip {
  183 + font-size: $font-md;
  184 + color: $color-red;
  185 + }
  186 + }
  187 + &__item {
  188 + display: flex;
  189 + font-size: 26upx;
  190 + color: #999999;
  191 + }
  192 + &__tags {
  193 + margin-bottom: $padding-sm;
  194 + display: flex;
  195 + align-items: center;
  196 + flex-wrap: wrap;
  197 + .tag {
  198 + margin-right: $padding-xs;
  199 + margin-bottom: $padding-xs;
  200 + border-radius: 4upx;
  201 + padding: 4upx 8upx;
  202 + display: inline-flex;
  203 + align-items: center;
  204 + justify-content: center;
  205 + color: $color-primary;
  206 + font-size: $font-sm;
  207 + background-color: rgba($color-primary, 0.1);
  208 + &--warning {
  209 + color: #f52723;
  210 + font-size: 20rpx;
  211 + padding-left: 10rpx;
  212 + padding-right: 10rpx;
  213 + border-radius: 8rpx;
  214 + border: 2rpx solid #f52723;
  215 + }
  216 + &--paying {
  217 + color: #ff9339;
  218 + font-size: 20rpx;
  219 + padding-left: 10upx;
  220 + padding-right: 10upx;
  221 + border-radius: 8upx;
  222 + border: 2rpx solid #ff9339;
  223 + }
  224 + }
  225 + }
  226 + &__steps {
  227 + margin-top: $padding-md;
  228 + .step {
  229 + &-item {
  230 + display: flex;
  231 + align-content: space-around;
  232 + font-size: $font-md;
  233 + .icon-waypoint {
  234 + font-size: $font-sm;
  235 + margin-right: $padding-sm;
  236 + height: $padding-md * 1.2;
  237 + width: $padding-md * 1.2;
  238 + min-width: $padding-md * 1.2;
  239 + }
  240 + .city {
  241 + font-weight: 500;
  242 + font-size: 32upx;
  243 + color: #2b2a27;
  244 + line-height: 32upx;
  245 + text-align: left;
  246 + font-style: normal;
  247 + }
  248 + .address {
  249 + font-weight: 400;
  250 + font-size: 24upx;
  251 + color: #999999;
  252 + line-height: 33upx;
  253 + text-align: left;
  254 + font-style: normal;
  255 + }
  256 + &:not(:first-child) {
  257 + margin-top: $padding-md;
  258 + }
  259 + }
  260 + }
  261 + }
  262 + &__footer {
  263 + display: flex;
  264 + justify-content: space-between;
  265 + align-items: center;
  266 + .amount {
  267 + font-size: 26upx;
  268 + .red {
  269 + color: #ff4f3b;
  270 + }
  271 + }
  272 + .action {
  273 + flex: 1;
  274 + display: flex;
  275 + justify-content: flex-end;
  276 + .more-action {
  277 + text-align: center;
  278 + color: #666666;
  279 + box-shadow: 0px 2px 8px 2px rgba(0, 0, 0, 0.22);
  280 + view {
  281 + padding: $padding-sm;
  282 + }
  283 + view + view {
  284 + border-top: 1px solid #eaeaea;
  285 + }
  286 + }
  287 + .button {
  288 + width: 164rpx;
  289 + height: 56rpx;
  290 + background: #ffffff;
  291 + border-radius: 12rpx;
  292 + border: 2rpx solid #e2e2e3;
  293 + display: flex;
  294 + align-items: center;
  295 + justify-content: center;
  296 + margin-left: $padding-sm;
  297 + .sx-img {
  298 + height: 12upx;
  299 + width: 14upx;
  300 + position: relative;
  301 + margin-left: 12upx;
  302 + .sx-image {
  303 + width: 100%;
  304 + height: 100%;
  305 + position: absolute;
  306 + top: 0;
  307 + left: 0;
  308 + }
  309 + }
  310 + }
  311 + .primary {
  312 + border: 2rpx solid $color-primary !important;
  313 + background: $color-primary;
  314 + color: #ffffff;
  315 + }
  316 + }
  317 + margin-top: $padding-sm;
  318 + }
  319 +}
  320 +</style>
pages/order/change-fee.vue 0 → 100644
@@ -0,0 +1,341 @@ @@ -0,0 +1,341 @@
  1 +<template>
  2 + <Page name="change-fee">
  3 + <template #content>
  4 + <u-alert type="warning" description="注意:只支持修改总运费,未支付或支付失败的款项"></u-alert>
  5 + <view class="card">
  6 + <view class="item">
  7 + <view class="th">费用项</view>
  8 + <view class="th">原运费</view>
  9 + <view class="th">修改后运费</view>
  10 + </view>
  11 + <view class="item line-solid"> </view>
  12 + <view class="item">
  13 + <view class="td">应付司机运费</view>
  14 + <view class="amount">¥{{ item.paidAmount }}</view>
  15 + <view class="amount">
  16 + <text>¥</text>
  17 + <u-input type="digit" @change="computedService" v-model="form.paidAmount" suffix-icon="arrow-right" border="none" placeholder="请输入"> </u-input>
  18 + </view>
  19 + </view>
  20 + <view class="item">
  21 + <view class="td">安全服务费</view>
  22 + <view class="amount">¥{{ item.securityServiceAmount ? item.securityServiceAmount : '0' }}</view>
  23 + <view class="amount">
  24 + <text>¥</text>
  25 + <u-input v-model="form.securityServiceAmount" border="none" disabled placeholder="自动计算"></u-input>
  26 + </view>
  27 + </view>
  28 + <view class="item line-dashed"> </view>
  29 + <view class="item" v-if="oilAmount.show">
  30 + <view class="td">
  31 + <text>油卡</text>
  32 + <text v-if="oilAmount.payStatus === 'PAY_SUCCESS'" class="td--success">已支付</text>
  33 + <text v-if="oilAmount.payStatus === 'PAY_FAILED'" class="td--warning">支付失败</text>
  34 + <text v-if="oilAmount.payStatus === 'NOT_PAY'" class="td--info">未支付</text>
  35 + <text v-if="oilAmount.payStatus === 'PAYING'" class="td--paying">支付中</text>
  36 + </view>
  37 + <view class="amount">¥{{ oilAmount.amount }}</view>
  38 + <view class="amount">
  39 + <text>¥</text>
  40 + <u-input type="digit" @change="computedService" v-model="form.oilAmount" border="none" suffix-icon="arrow-right" placeholder="请输入" :disabled="oilAmount.disabled"></u-input>
  41 + </view>
  42 + </view>
  43 + <view class="item" v-if="prePay.show">
  44 + <view class="td">
  45 + <text>预付款</text>
  46 + <text v-if="prePay.payStatus === 'PAY_SUCCESS'" class="td--success">已支付</text>
  47 + <text v-if="prePay.payStatus === 'PAY_FAILED'" class="td--warning">支付失败</text>
  48 + <text v-if="prePay.payStatus === 'NOT_PAY'" class="td--info">未支付</text>
  49 + <text v-if="prePay.payStatus === 'PAYING'" class="td--paying">支付中</text>
  50 + </view>
  51 + <view class="amount">¥{{ prePay.amount ? prePay.amount : '0' }}</view>
  52 + <view class="amount">
  53 + <text>¥</text>
  54 + <u-input type="digit" @change="computedService" v-model="form.prepaidAmount" border="none" suffix-icon="arrow-right" :disabled="prePay.disabled" placeholder="请输入"></u-input>
  55 + </view>
  56 + </view>
  57 + <view class="item" v-if="arrivalPay.show">
  58 + <view class="td">
  59 + <text>货到款</text>
  60 + <text v-if="arrivalPay.payStatus === 'PAY_SUCCESS'" class="td--success">已支付</text>
  61 + <text v-if="arrivalPay.payStatus === 'PAY_FAILED'" class="td--warning">支付失败</text>
  62 + <text v-if="arrivalPay.payStatus === 'NOT_PAY'" class="td--info">未支付</text>
  63 + <text v-if="arrivalPay.payStatus === 'PAYING'" class="td--paying">支付中</text>
  64 + </view>
  65 + <view class="amount">¥{{ arrivalPay.amount ? arrivalPay.amount : '0' }}</view>
  66 + <view class="amount">
  67 + <text>¥</text>
  68 + <u-input
  69 + border="none"
  70 + type="digit"
  71 + @change="computedService"
  72 + v-model="form.deliveryAmount"
  73 + :suffix-icon="autoComputedArrival ? '' : 'arrow-right'"
  74 + :placeholder="autoComputedArrival ? '自动计算' : '请输入'"
  75 + :disabled="autoComputedArrival || arrivalPay.disabled"
  76 + ></u-input>
  77 + </view>
  78 + </view>
  79 + <view class="item">
  80 + <view class="td">
  81 + <text>尾款</text>
  82 + <text v-if="final.payStatus === 'PAY_SUCCESS'" class="td--success">已支付</text>
  83 + <text v-if="final.payStatus === 'PAY_FAILED'" class="td--warning">支付失败</text>
  84 + <text v-if="final.payStatus === 'NOT_PAY'" class="td--info">未支付</text>
  85 + <text v-if="final.payStatus === 'PAYING'" class="td--paying">支付中</text>
  86 + </view>
  87 + <view class="amount">¥{{ final.amount ? final.amount : '0' }}</view>
  88 + <view class="amount">
  89 + <text>¥</text>
  90 + <u-input
  91 + border="none"
  92 + type="digit"
  93 + @change="computedService"
  94 + v-model="form.balancePaymentAmount"
  95 + :suffix-icon="!autoComputedArrival ? '' : 'arrow-right'"
  96 + :placeholder="!autoComputedArrival ? '自动计算' : '请输入'"
  97 + :disabled="!autoComputedArrival || final.disabled"
  98 + ></u-input>
  99 + </view>
  100 + </view>
  101 + </view>
  102 + </template>
  103 + <template #footer>
  104 + <u-button type="primary" @tap="submit">确定更改</u-button>
  105 + </template>
  106 + </Page>
  107 +</template>
  108 +<script>
  109 +export default {
  110 + name: 'change-fee',
  111 + data() {
  112 + return {
  113 + currentFreight: {},
  114 + item: {
  115 + orderFeePayPlanList: [],
  116 + },
  117 + form: {
  118 + paidAmount: '',
  119 + oilAmount: '',
  120 + deliveryAmount: '',
  121 + prepaidAmount: '',
  122 + balancePaymentAmount: '',
  123 + },
  124 + };
  125 + },
  126 + computed: {
  127 + oilAmount() {
  128 + let resList = this.item.orderFeePayPlanList ? this.item.orderFeePayPlanList.filter(i => i.type === 'OIL_COST') : [];
  129 + let res = resList.length === 1 ? resList[0] : {};
  130 + return {
  131 + ...res,
  132 + show: this.item.oilPayFlag,
  133 + disabled: !['NOT_PAY', 'PAY_FAILED', '', null, undefined].includes(res.payStatus),
  134 + };
  135 + },
  136 + prePay() {
  137 + let resList = this.item.orderFeePayPlanList.filter(i => i.type === 'OUT_INVITE_PRE');
  138 + let res = resList.length === 1 ? resList[0] : {};
  139 + return {
  140 + ...res,
  141 + show: this.item.prePayFlag,
  142 + disabled: !['NOT_PAY', 'PAY_FAILED', '', null, undefined].includes(res.payStatus),
  143 + };
  144 + },
  145 + arrivalPay() {
  146 + let resList = this.item.orderFeePayPlanList.filter(i => i.type === 'OUT_INVITE_ARRIVAL');
  147 + let res = resList.length === 1 ? resList[0] : {};
  148 + return {
  149 + ...res,
  150 + show: this.item.arrivalPayFlag,
  151 + disabled: !['NOT_PAY', 'PAY_FAILED', '', null, undefined].includes(res.payStatus),
  152 + };
  153 + },
  154 + final() {
  155 + let resList = this.item.orderFeePayPlanList.filter(i => i.type === 'OUT_INVITE_FINAL');
  156 + let res = resList.length === 1 ? resList[0] : {};
  157 + return {
  158 + ...res,
  159 + show: true,
  160 + disabled: !['NOT_PAY', 'PAY_FAILED', '', null, undefined].includes(res.payStatus),
  161 + };
  162 + },
  163 + autoComputedArrival() {
  164 + // 自动计算货到
  165 + return 'OUT_INVITE_ARRIVAL' === this.currentFreight?.autoComputeFeeType;
  166 + },
  167 + },
  168 + onLoad(options) {
  169 + if (options.code) {
  170 + this.initData(options.code);
  171 + }
  172 + },
  173 + methods: {
  174 + initData(code) {
  175 + uni.$u.api.freightOrder.currentFreight({}).then(en => {
  176 + this.currentFreight = en?.result || {};
  177 + });
  178 + uni.$u.api.freightOrder.getDetail({ code }).then(res => {
  179 + this.item = res.result || {};
  180 + this.form.paidAmount = this.item.paidAmount;
  181 + this.updateAfterAmount(this.item.orderFeePayPlanList);
  182 + });
  183 + },
  184 + updateAfterAmount(list) {
  185 + let oilPay = list.filter(i => i.type === 'OIL_COST')[0];
  186 + let prePay = list.filter(i => i.type === 'OUT_INVITE_PRE')[0];
  187 + let arrivalPay = list.filter(i => i.type === 'OUT_INVITE_ARRIVAL')[0];
  188 + let finalPay = list.filter(i => i.type === 'OUT_INVITE_FINAL')[0];
  189 + this.form = {
  190 + ...this.form,
  191 + oilAmount: oilPay.amount,
  192 + prepaidAmount: prePay.amount,
  193 + deliveryAmount: arrivalPay.amount,
  194 + balancePaymentAmount: finalPay.amount || 0,
  195 + };
  196 + },
  197 + computedService() {
  198 + uni.$u.debounce(this.getServiceAmountInfo, 500);
  199 + },
  200 + getServiceAmountInfo() {
  201 + const { paidAmount = '0', oilAmount = '0', deliveryAmount = '0', prepaidAmount = '0', balancePaymentAmount = '0' } = this.form;
  202 + const { goodsName = '', goodsValue = '' } = this.item;
  203 + let params = {
  204 + paidAmount,
  205 + deliveryAmount,
  206 + prepaidAmount,
  207 + oilAmount,
  208 + balancePaymentAmount,
  209 + goodsName,
  210 + goodsValue,
  211 + enterpriseId: this.item.enterpriseId,
  212 + code: this.item.code,
  213 + };
  214 + uni.$u.api.freightOrder.getServiceAmount(params).then(res => {
  215 + if (res.success) {
  216 + this.form.paidAmount = res.result.paidAmount || paidAmount;
  217 + this.form.prepaidAmount = res.result.prepaidAmount || prepaidAmount;
  218 + this.form.oilAmount = res.result.oilAmount || oilAmount;
  219 + this.form.deliveryAmount = res.result.deliveryAmount || '0';
  220 + this.form.balancePaymentAmount = res.result.balancePaymentAmount || '0';
  221 + this.form.driverSecurityServiceAmount = res.result.driverSecurityServiceAmount || '0';
  222 + this.form.securityServiceAmount = res.result.securityServiceAmount || '0';
  223 + this.form.serviceAmount = res.result.serviceAmount || '0';
  224 + }
  225 + });
  226 + },
  227 + submit() {
  228 + let params = [
  229 + { ...this.oilAmount, afterAmount: this.form.oilAmount },
  230 + { ...this.prePay, afterAmount: this.form.prepaidAmount },
  231 + { ...this.arrivalPay, afterAmount: this.form.deliveryAmount },
  232 + { ...this.final, afterAmount: this.form.balancePaymentAmount },
  233 + ];
  234 + uni.$u.api.freightOrder.adjustAmount({ feeList: params, code: this.item.code, paidAmount: this.form.paidAmount }).then(res => {
  235 + if (res.success) {
  236 + uni.showToast({ title: '操作成功', icon: 'none' });
  237 + this.getOpenerEventChannel().emit('refreshData');
  238 + setTimeout(() => uni.navigateBack(), 500);
  239 + }
  240 + });
  241 + },
  242 + },
  243 +};
  244 +</script>
  245 +
  246 +<style lang="scss">
  247 +.page-change-fee {
  248 + &__content {
  249 + padding-top: 0 !important;
  250 + }
  251 + &__footer {
  252 + background: $color-white;
  253 + }
  254 + .card {
  255 + background-color: $color-white;
  256 + color: $color-text;
  257 + padding: $padding-sm;
  258 + margin: $padding-sm;
  259 + border-radius: $radius-md;
  260 + box-shadow: $shadow-normal;
  261 + font-size: $font-md;
  262 + .line-solid {
  263 + border-bottom: 1px solid #dddddd;
  264 + }
  265 + .line-dashed {
  266 + border-bottom: 1px dashed #dddddd;
  267 + }
  268 + .item + .item {
  269 + margin-top: $padding-md;
  270 + }
  271 + .item {
  272 + display: flex;
  273 + view {
  274 + flex: 1;
  275 + }
  276 + .th {
  277 + font-weight: 500;
  278 + font-size: 30upx;
  279 + color: #2b2a27;
  280 + line-height: 30upx;
  281 + text-align: left;
  282 + font-style: normal;
  283 + }
  284 + .td {
  285 + font-weight: 400;
  286 + font-size: 28upx;
  287 + color: #999999;
  288 + line-height: 28upx;
  289 + text-align: left;
  290 + font-style: normal;
  291 + &--warning {
  292 + color: #f52723;
  293 + font-size: 20rpx;
  294 + margin-left: 20upx;
  295 + padding-left: 10upx;
  296 + padding-right: 10upx;
  297 + border-radius: 8upx;
  298 + border: 2rpx solid #f52723;
  299 + }
  300 + &--info {
  301 + color: #999999;
  302 + font-size: 20upx;
  303 + margin-left: 20upx;
  304 + padding-left: 10upx;
  305 + padding-right: 10upx;
  306 + border-radius: 8upx;
  307 + border: 2rpx solid #999999;
  308 + }
  309 + &--paying {
  310 + color: #ff9339;
  311 + font-size: 20upx;
  312 + margin-left: 20upx;
  313 + padding-left: 10upx;
  314 + padding-right: 10upx;
  315 + border-radius: 8upx;
  316 + border: 2rpx solid #ff9339;
  317 + }
  318 + &--success {
  319 + color: #00b87a;
  320 + font-size: 20upx;
  321 + margin-left: 20upx;
  322 + padding-left: 10upx;
  323 + padding-right: 10upx;
  324 + border-radius: 8upx;
  325 + border: 2rpx solid #00b87a;
  326 + }
  327 + }
  328 + .amount {
  329 + font-weight: 400;
  330 + font-size: 28upx;
  331 + color: #2b2a27;
  332 + line-height: 28upx;
  333 + text-align: left;
  334 + font-style: normal;
  335 + display: flex;
  336 + align-items: center;
  337 + }
  338 + }
  339 + }
  340 +}
  341 +</style>
pages/order/change-goods.vue 0 → 100644
@@ -0,0 +1,116 @@ @@ -0,0 +1,116 @@
  1 +<template>
  2 + <Page name="change-goods" flank>
  3 + <template #content>
  4 + <u-form :model="form" ref="uForm" labelWidth="100">
  5 + <view class="card">
  6 + <u-form-item label="货物名称" required @click="choseGoodsName">
  7 + <u-input v-model="form.goodsName" border="none" suffix-icon="arrow-right" placeholder="请选择" disabledColor="#ffffff" disabled />
  8 + </u-form-item>
  9 + <u-form-item v-if="showGoodsValue" label="货物价值" required>
  10 + <u-input v-model="form.goodsValue" border="none" type="number" placeholder="请输入" />
  11 + </u-form-item>
  12 + <u-form-item label="货物件数">
  13 + <u-input v-model="form.goodsPiece" border="none" type="number" placeholder="请输入,选填" />
  14 + </u-form-item>
  15 + <u-form-item label="货物吨数" required>
  16 + <u-input v-model="form.goodsWeight" border="none" type="number" placeholder="请输入" />
  17 + </u-form-item>
  18 + <u-form-item label="货物方数">
  19 + <u-input v-model="form.goodsVolume" border="none" type="number" placeholder="请输入,选填" />
  20 + </u-form-item>
  21 + </view>
  22 + </u-form>
  23 + </template>
  24 + <template #footer>
  25 + <u-button type="primary" @tap="submit">确认修改</u-button>
  26 + </template>
  27 + </Page>
  28 +</template>
  29 +
  30 +<script>
  31 +import { urlParam } from '@/utils/param';
  32 +export default {
  33 + name: 'change-goods',
  34 + data() {
  35 + return {
  36 + form: {
  37 + goodsName: '',
  38 + goodsValue: '',
  39 + goodsPiece: '',
  40 + goodsWeight: '',
  41 + goodsVolume: '',
  42 + },
  43 + item: {},
  44 + currentFreight: {},
  45 + };
  46 + },
  47 + onLoad(options) {
  48 + if (options.code) {
  49 + this.initData(options.code);
  50 + }
  51 + },
  52 + computed: {
  53 + showGoodsValue() {
  54 + return this.currentFreight ? this.currentFreight.driverSecurityServiceFlag || this.currentFreight.securityServiceFlag : false;
  55 + },
  56 + },
  57 + methods: {
  58 + initData(code) {
  59 + uni.$u.api.freightOrder.currentFreight({}).then(en => {
  60 + this.currentFreight = en?.result || {};
  61 + });
  62 + uni.$u.api.freightOrder.getDetail({ code }).then(res => {
  63 + this.item = res.result || {};
  64 + this.form = {
  65 + goodsName: this.item.goodsName,
  66 + goodsValue: this.item.goodsValue,
  67 + goodsPiece: this.item.goodsPiece,
  68 + goodsWeight: this.item.goodsWeight,
  69 + goodsVolume: this.item.goodsVolume,
  70 + };
  71 + });
  72 + },
  73 + choseGoodsName() {
  74 + uni.$once('select-common', option => {
  75 + this.form.goodsName = option.name;
  76 + });
  77 + uni.navigateTo({
  78 + url: `/pages/global/search-common${urlParam({
  79 + mode: 'select',
  80 + url: 'goodsName',
  81 + title: '货物名称',
  82 + label: 'name',
  83 + value: '',
  84 + })}`,
  85 + });
  86 + },
  87 + submit() {
  88 + uni.$u.api.freightOrder.modifyGoods({ code: this.item.code, ...this.form }).then(res => {
  89 + if (res.success) {
  90 + uni.showToast({ title: '操作成功', icon: 'none' });
  91 + this.getOpenerEventChannel().emit('refreshData');
  92 + setTimeout(() => uni.navigateBack(), 500);
  93 + }
  94 + });
  95 + },
  96 + },
  97 +};
  98 +</script>
  99 +
  100 +<style lang="scss">
  101 +.page-change-goods {
  102 + &__footer {
  103 + background: $color-white;
  104 + }
  105 + .card {
  106 + color: #999999;
  107 + background-color: $color-white;
  108 + border-radius: $radius-md;
  109 + box-shadow: $shadow-normal;
  110 + .u-form-item {
  111 + padding-left: $padding-md !important;
  112 + padding-right: $padding-sm !important;
  113 + }
  114 + }
  115 +}
  116 +</style>
pages/order/detail.vue 0 → 100644
@@ -0,0 +1,611 @@ @@ -0,0 +1,611 @@
  1 +<template>
  2 + <Page name="order-detail" flank>
  3 + <template #content>
  4 + <view class="card">
  5 + <view class="card__header">
  6 + <view class="title">
  7 + <view class="order-no">
  8 + <field-copy :value="item.code" v-if="item.code">{{ item.code }} </field-copy>
  9 + </view>
  10 + <render-dict class="status" :style="{ color: colorMap[item.status] }" dict="FREIGHT_ORDER_STATUS" :value="item.status"></render-dict>
  11 + </view>
  12 + </view>
  13 + <view class="card__item">
  14 + {{ item.loadTime }}装货
  15 + <text v-if="item.waitHandleExceptionNumber" class="card__item--warning">{{ item.waitHandleExceptionNumber || '0' }}个异常待处理</text>
  16 + </view>
  17 + <view class="card__steps">
  18 + <view class="step">
  19 + <view class="step-item">
  20 + <view class="icon-waypoint icon-start">装</view>
  21 + <view style="flex: 1">
  22 + <view class="city">{{ item.waypoints[0].cityName }}-{{ item.waypoints[0].areaName }}</view>
  23 + <view class="address">{{ item.waypoints[0].address }}</view>
  24 + <view class="address">
  25 + <text>{{ item.waypoints[0].contactName ? item.waypoints[0].contactName : '' }}</text>
  26 + <text>{{ item.waypoints[0].contactMobile ? item.waypoints[0].contactMobile : '' }}</text>
  27 + </view>
  28 + <view class="address_action">
  29 + <view> {{ item.confirmDepartureTime ? item.confirmDepartureTime + '发车' : '' }} </view>
  30 + <view v-if="['TRANSFER'].includes(item.status) && $permission('/freightOrder/depart')" @tap="toStartCar">
  31 + <u--text text="修改发车时间" suffixIcon="arrow-right"></u--text>
  32 + </view>
  33 + </view>
  34 + </view>
  35 + </view>
  36 + <view class="step-item">
  37 + <view class="icon-waypoint icon-end">卸</view>
  38 + <view style="flex: 1">
  39 + <view class="city">{{ item.waypoints[1].cityName }}-{{ item.waypoints[1].areaName }}</view>
  40 + <view class="address">{{ item.waypoints[1].address }}</view>
  41 + <view class="address">
  42 + <text>{{ item.waypoints[1].contactName ? item.waypoints[1].contactName : '' }}</text>
  43 + <text>{{ item.waypoints[1].contactMobile ? item.waypoints[1].contactMobile : '' }}</text>
  44 + </view>
  45 + <view class="address_action">
  46 + <view> {{ item.confirmArrivalTime ? item.confirmArrivalTime + '到车' : '' }} </view>
  47 + <view
  48 + v-if="['COMPLETED'].includes(item.status) && !['ALREADY_SETTLEMENT'].includes(item.paymentSettlementStatus) && $permission('/freightOrder/arrive')"
  49 + @tap="toArrivalCar"
  50 + >
  51 + <u--text text="修改到车时间" suffixIcon="arrow-right"></u--text>
  52 + </view>
  53 + </view>
  54 + </view>
  55 + </view>
  56 + </view>
  57 + </view>
  58 + </view>
  59 + <view class="card">
  60 + <view class="card__item">
  61 + <view class="card__item_field">所属项目</view>
  62 + <view class="card__item_content">{{ item.projectName }}</view>
  63 + </view>
  64 + <view class="card__item">
  65 + <view class="card__item_field">内部单号</view>
  66 + <view class="card__item_content">
  67 + <view class="text">
  68 + <field-copy :value="item.customerOrderCode" v-if="item.customerOrderCode">{{ item.customerOrderCode }}</field-copy>
  69 + </view>
  70 + <view class="action" @tap="(customerOrderCode = ''), (popShow = true)"> <u--text text="修改" suffixIcon="arrow-right"></u--text> </view>
  71 + </view>
  72 + </view>
  73 + <view class="card__item">
  74 + <view class="card__item_field">货物信息</view>
  75 + <view class="card__item_content">
  76 + <view class="text">
  77 + <text v-if="!!item.goodsName">{{ item.goodsName }}</text>
  78 + <text v-if="!!item.goodsPiece">{{ item.goodsPiece }}件</text>
  79 + <text v-if="!!item.goodsWeight">{{ item.goodsWeight }}吨</text>
  80 + <text v-if="!!item.goodsVolume">{{ item.goodsVolume }}方</text>
  81 + </view>
  82 + <view v-if="$permission('/freightOrder/modifyGoods')" class="action" @tap="toChangeGoods"> <u--text text="修改" suffixIcon="arrow-right"></u--text> </view>
  83 + </view>
  84 + </view>
  85 + <view class="card__item">
  86 + <view class="card__item_field">订单备注</view>
  87 + <view class="card__item_content">{{ item.remark ? item.remark : '' }}</view>
  88 + </view>
  89 + <view class="card__item">
  90 + <view class="card__item_field">回单照片</view>
  91 + <view class="card__item_content">
  92 + <z-upload v-if="item.receiptAttachment" v-model="item.receiptAttachment" :limit="20" readonly disabled></z-upload>
  93 + </view>
  94 + <view v-if="['COMPLETED'].includes(item.status) && $permission('/freightOrder/modifyReceiptAttachment')" class="action" @tap="toUploadReceipt">
  95 + <u--text text="修改" suffixIcon="arrow-right"></u--text>
  96 + </view>
  97 + </view>
  98 + </view>
  99 + <view class="card">
  100 + <view class="card__header">
  101 + <view class="label"> 司机车辆 </view>
  102 + <view
  103 + v-if="
  104 + $permission('/freightOrder/assignVehicle') &&
  105 + !['ALREADY_SETTLEMENT'].includes(item.paymentSettlementStatus) &&
  106 + ['WAIT_CONFIRM', 'WAIT_ACCEPT', 'WAIT_DEPART', 'TRANSFER', 'COMPLETED'].includes(item.status)
  107 + "
  108 + class="action"
  109 + @tap="toAgainAssign"
  110 + >
  111 + <u--text text="重新指派" suffixIcon="arrow-right"></u--text>
  112 + </view>
  113 + </view>
  114 + <view class="card__item">
  115 + <view class="card__item_field">司机</view>
  116 + <view class="card__item_content">
  117 + <view>
  118 + <text v-if="!!item.driverName">{{ item.driverName }}</text>
  119 + <text v-if="!!item.driverMobile">{{ item.driverMobile }}</text>
  120 + <text v-if="item.driverMobile && item.driverCertifiedStatus === 'NOT_CERTIFIED'" class="card__item--warning">未认证</text>
  121 + <text v-if="item.driverMobile && item.driverCertifiedStatus === 'CERTIFYING'" class="card__item--paying">认证中</text>
  122 + </view>
  123 + </view>
  124 + </view>
  125 + <view class="card__item">
  126 + <view class="card__item_field">收款人</view>
  127 + <view class="card__item_content">
  128 + <view class="text">
  129 + <text>{{ item.payee ? item.payee : '' }}</text>
  130 + <text>
  131 + {{ item.payeeMobile ? item.payeeMobile : '' }}
  132 + <text v-if="item.payeeMobile && item.bindBankCardNoFlag === false" class="card__item--warning">未绑卡</text>
  133 + </text>
  134 + </view>
  135 + <view
  136 + v-if="
  137 + $permission('/freightOrder/modifyPayee') &&
  138 + !['ALREADY_SETTLEMENT'].includes(item.paymentSettlementStatus) &&
  139 + ['WAIT_CONFIRM', 'WAIT_ACCEPT', 'WAIT_DEPART', 'TRANSFER', 'COMPLETED'].includes(item.status)
  140 + "
  141 + class="action"
  142 + @tap="changePayee"
  143 + >
  144 + <u--text text="更换收款人" suffixIcon="arrow-right"></u--text>
  145 + </view>
  146 + </view>
  147 + </view>
  148 + <payee :value="payeeModel"></payee>
  149 + <view class="card__item">
  150 + <view class="card__item_field">车型</view>
  151 + <view class="card__item_content">
  152 + <view>
  153 + <text>{{ item.specification ? item.specification : '' }}</text>
  154 + <render-dict dict="VEHICLE_COMPARTMENT_TYPE" :value="item.vanType"></render-dict>
  155 + </view>
  156 + </view>
  157 + </view>
  158 + <view class="card__item">
  159 + <view class="card__item_field">车牌号</view>
  160 + <view class="card__item_content">
  161 + <text>
  162 + {{ item.vehicleLicenseNum ? item.vehicleLicenseNum : '' }}
  163 + <text v-if="item.vehicleLicenseNum && item.vehicleCertifiedStatus === 'NOT_CERTIFIED'" class="card__item--warning">未认证</text>
  164 + <text v-if="item.vehicleLicenseNum && item.vehicleCertifiedStatus === 'CERTIFYING'" class="card__item--paying">认证中</text>
  165 + </text>
  166 + </view>
  167 + </view>
  168 + <view class="card__item">
  169 + <view class="card__item_field">车挂号</view>
  170 + <view class="card__item_content">
  171 + <text>
  172 + {{ item.trailerLicenseNum ? item.trailerLicenseNum : '' }}
  173 + <text v-if="item.extraTrailerFlag" class="card__item--warning">多车挂</text>
  174 + <text v-if="item.missTrailerFlag" class="card__item--warning">缺车挂</text>
  175 + <text v-if="item.trailerLicenseNum && !item.extraTrailerFlag && item.trailerVehicleCertifiedStatus === 'NOT_CERTIFIED'" class="card__item--warning">未认证</text>
  176 + <text v-if="item.trailerLicenseNum && !item.extraTrailerFlag && item.trailerVehicleCertifiedStatus === 'CERTIFYING'" class="card__item--paying">认证中</text>
  177 + </text>
  178 + </view>
  179 + </view>
  180 + </view>
  181 + <view class="card">
  182 + <view class="card__header">
  183 + <view class="label"> 订单费用 </view>
  184 + <view
  185 + v-if="
  186 + $permission('/freightOrder/adjustAmount') &&
  187 + !['ALREADY_SETTLEMENT'].includes(item.paymentSettlementStatus) &&
  188 + ['WAIT_CONFIRM', 'WAIT_ACCEPT', 'WAIT_DEPART', 'TRANSFER', 'COMPLETED'].includes(item.status)
  189 + "
  190 + class="action"
  191 + @tap="toChangeFee"
  192 + >
  193 + <u--text text="更改运费" suffixIcon="arrow-right"></u--text>
  194 + </view>
  195 + </view>
  196 + <view class="card__item" v-if="!!item.paidAmount">
  197 + <view class="card__item_field">应付司机运费</view>
  198 + <view class="card__item_content">¥{{ item.paidAmount }}</view>
  199 + </view>
  200 + <view class="card__item" v-if="!!item.securityServiceAmount">
  201 + <view class="card__item_field">安全服务费</view>
  202 + <view class="card__item_content">¥{{ item.securityServiceAmount }}</view>
  203 + </view>
  204 + <view class="card__item">
  205 + <view class="card__item_field">综合服务费</view>
  206 + <view class="card__item_content">¥{{ item.serviceAmount ? item.serviceAmount : '' }}</view>
  207 + </view>
  208 + <view class="count-line">
  209 + <view class="field">订单总额</view>
  210 + <view class="number">¥{{ item.totalAmount ? item.totalAmount : '' }}</view>
  211 + </view>
  212 + </view>
  213 + <view class="card">
  214 + <view class="card__header">
  215 + <view class="label"> 司机运费 </view>
  216 + </view>
  217 + <view class="card__item" v-for="(it, i) in amountList" :key="i">
  218 + <view class="card__item_field">
  219 + <render-dict dict="ONLINE_FREIGHT_ORDER_FEE_TYPE" :value="it.type"></render-dict>
  220 + </view>
  221 + <view class="card__item_content">¥{{ it.amount }}</view>
  222 + <view v-if="it.payStatus === 'PAY_FAILED'" class="card__item--warning">支付失败:{{ it.remark }}</view>
  223 + <view v-if="it.payStatus === 'PAYING'" class="card__item--paying">支付中</view>
  224 + <view v-if="it.payStatus === 'PAY_SUCCESS'" class="card__item--success">已支付</view>
  225 + </view>
  226 + <view class="count-line">
  227 + <view class="field">实付司机运费</view>
  228 + <view class="number">¥{{ item.freightAmount }}</view>
  229 + </view>
  230 + </view>
  231 + <view class="card">
  232 + <u-steps current="0" direction="column" dot>
  233 + <u-steps-item v-for="(it, i) in item.operateRecords" :key="i" :title="it.type" :desc="it.operateTime"> </u-steps-item>
  234 + </u-steps>
  235 + </view>
  236 + </template>
  237 + <u-popup :show="popShow" type="center" @close="popShow = false" closeable>
  238 + <view class="modify-customer">
  239 + <view class="title">修改内部单号</view>
  240 + <u-input v-model="customerOrderCode"></u-input>
  241 + <view class="but">
  242 + <u-button type="primary" @click="modifyCustomerFun">确定</u-button>
  243 + </view>
  244 + </view>
  245 + </u-popup>
  246 + </Page>
  247 +</template>
  248 +<script>
  249 +import FieldCopy from '../../components/field/field-copy.vue';
  250 +import Payee from '../../components/card/payee.vue';
  251 +import USteps from '../../uni_modules/uview-ui/components/u-steps/u-steps.vue';
  252 +import UStepsItem from '../../uni_modules/uview-ui/components/u-steps-item/u-steps-item.vue';
  253 +import ZUpload from '../../components/zee/z-upload.vue';
  254 +import UPopup from '../../uni_modules/uview-ui/components/u-popup/u-popup.vue';
  255 +import UInput from '../../uni_modules/uview-ui/components/u--input/u--input.vue';
  256 +import UButton from '../../uni_modules/uview-ui/components/u-button/u-button.vue';
  257 +import page from '../../mixins/page';
  258 +
  259 +export default {
  260 + name: 'order-detail',
  261 + mixins: [page],
  262 + components: { UButton, UInput, UPopup, ZUpload, UStepsItem, USteps, Payee, FieldCopy },
  263 + data() {
  264 + return {
  265 + popShow: false,
  266 + customerOrderCode: '',
  267 + colorMap: {
  268 + WAIT_CONFIRM: '#F52723',
  269 + WAIT_ACCEPT: '#FF9339',
  270 + WAIT_DEPART: '#666666',
  271 + TRANSFER: '#2673FB',
  272 + COMPLETED: '#00B87A',
  273 + CANCEL: '#999999',
  274 + },
  275 + item: {
  276 + code: '',
  277 + status: 'TRANSFER',
  278 + projectName: '',
  279 + loadTime: '',
  280 + customerOrderCode: '',
  281 + remark: '',
  282 + receiptAttachment: '',
  283 + waypoints: [
  284 + { cityName: '', areaName: '', address: '' },
  285 + { cityName: '', areaName: '', address: '' },
  286 + ],
  287 + },
  288 + };
  289 + },
  290 + computed: {
  291 + amountList() {
  292 + return this.item.orderFeePayPlanList ? this.item.orderFeePayPlanList.filter(i => i.amount && i.amount > 0) : [];
  293 + },
  294 + payeeModel() {
  295 + return this.item.payee
  296 + ? {
  297 + dueBank: this.item.payee,
  298 + dueBankCardNo: this.item.dueBankCardNo,
  299 + openingBank: this.item.openingBank,
  300 + }
  301 + : {};
  302 + },
  303 + },
  304 + onLoad(options) {
  305 + if (options.code) {
  306 + this.initData(options.code);
  307 + }
  308 + },
  309 + methods: {
  310 + initData(code) {
  311 + uni.$u.api.freightOrder.getDetail({ code }).then(res => {
  312 + this.item = res.result || {};
  313 + });
  314 + },
  315 + toStartCar() {
  316 + uni.navigateTo({
  317 + url: '/pages/order/start-car?code=' + this.item.code,
  318 + events: {
  319 + refreshData: () => {
  320 + this.initData(this.item.code);
  321 + },
  322 + },
  323 + });
  324 + },
  325 + toArrivalCar() {
  326 + uni.navigateTo({
  327 + url: '/pages/order/arrival-car?code=' + this.item.code,
  328 + events: {
  329 + refreshData: () => {
  330 + this.initData(this.item.code);
  331 + },
  332 + },
  333 + });
  334 + },
  335 + toChangeFee() {
  336 + uni.navigateTo({
  337 + url: '/pages/order/change-fee?code=' + this.item.code,
  338 + events: {
  339 + refreshData: () => {
  340 + this.initData(this.item.code);
  341 + },
  342 + },
  343 + });
  344 + },
  345 + toAgainAssign() {
  346 + uni.navigateTo({
  347 + url: '/pages/order/again-assign?code=' + this.item.code,
  348 + events: {
  349 + refreshData: () => {
  350 + this.initData(this.item.code);
  351 + },
  352 + },
  353 + });
  354 + },
  355 + toUploadReceipt() {
  356 + uni.navigateTo({
  357 + url: '/pages/order/upload-receipt?code=' + this.item.code,
  358 + events: {
  359 + refreshData: () => {
  360 + this.initData(this.item.code);
  361 + },
  362 + },
  363 + });
  364 + },
  365 + toChangeGoods() {
  366 + uni.navigateTo({
  367 + url: '/pages/order/change-goods?code=' + this.item.code,
  368 + events: {
  369 + refreshData: () => {
  370 + this.initData(this.item.code);
  371 + },
  372 + },
  373 + });
  374 + },
  375 + changePayee() {
  376 + uni.$once('select-payee', obj => {
  377 + uni.$u.api.freightOrder.modifyPayee({ payeeId: obj.driverId, code: this.item.code }).then(res => {
  378 + if (res.success) {
  379 + this.initData(this.item.code);
  380 + }
  381 + });
  382 + });
  383 + uni.navigateTo({
  384 + url: '/pages/global/search-payee',
  385 + });
  386 + },
  387 + modifyCustomerFun() {
  388 + uni.$u.api.freightOrder.modifyCustomerOrderCode({ customerOrderCode: this.customerOrderCode, code: this.item.code }).then(res => {
  389 + if (res.success) {
  390 + this.popShow = false;
  391 + this.initData(this.item.code);
  392 + }
  393 + });
  394 + },
  395 + },
  396 +};
  397 +</script>
  398 +<style scoped lang="scss">
  399 +.page-order-detail {
  400 + .modify-customer {
  401 + padding: $padding-md;
  402 + .title {
  403 + font-weight: 400;
  404 + font-size: 32rpx;
  405 + color: #2b2a27;
  406 + line-height: 45px;
  407 + text-align: left;
  408 + font-style: normal;
  409 + }
  410 + .but {
  411 + margin-top: $padding-md;
  412 + }
  413 + }
  414 + .card {
  415 + background-color: $color-white;
  416 + color: $color-text;
  417 + padding: $padding-sm;
  418 + margin-bottom: $padding-sm;
  419 + border-radius: $radius-md;
  420 + box-shadow: $shadow-normal;
  421 + font-size: $font-md;
  422 + &__header {
  423 + display: flex;
  424 + align-items: center;
  425 + border-bottom: 1px solid $color-border;
  426 + padding-bottom: $padding-sm;
  427 + margin-bottom: $padding-sm;
  428 + justify-content: space-between;
  429 + .title {
  430 + width: 100%;
  431 + display: flex;
  432 + flex-direction: row;
  433 + align-items: center;
  434 + justify-content: space-between;
  435 + .order-no {
  436 + display: flex;
  437 + align-items: center;
  438 + }
  439 + .status {
  440 + font-weight: bold;
  441 + }
  442 + }
  443 + }
  444 + .count-line {
  445 + padding-top: $padding-sm;
  446 + margin-top: $padding-sm;
  447 + border-top: 1px solid $color-border;
  448 + display: flex;
  449 + justify-content: space-between;
  450 + .field {
  451 + font-weight: 400;
  452 + font-size: 28upx;
  453 + color: #999999;
  454 + line-height: 28upx;
  455 + text-align: left;
  456 + }
  457 + .number {
  458 + font-weight: 600;
  459 + font-size: 28upx;
  460 + color: #2b2a27;
  461 + line-height: 28upx;
  462 + text-align: center;
  463 + font-style: normal;
  464 + }
  465 + }
  466 + &__item {
  467 + display: flex;
  468 + font-size: 26upx;
  469 + color: #999999;
  470 + align-content: baseline;
  471 + &--warning {
  472 + color: #f52723;
  473 + font-size: 20rpx;
  474 + margin-left: 20upx;
  475 + padding-left: 10upx;
  476 + padding-right: 10upx;
  477 + border-radius: 8upx;
  478 + border: 2rpx solid #f52723;
  479 + }
  480 + &--paying {
  481 + color: #ff9339;
  482 + font-size: 20rpx;
  483 + margin-left: 20upx;
  484 + padding-left: 10upx;
  485 + padding-right: 10upx;
  486 + border-radius: 8upx;
  487 + border: 2rpx solid #ff9339;
  488 + }
  489 + &--success {
  490 + color: #00b87a;
  491 + font-size: 20rpx;
  492 + margin-left: 20upx;
  493 + padding-left: 10upx;
  494 + padding-right: 10upx;
  495 + border-radius: 8upx;
  496 + border: 2rpx solid #00b87a;
  497 + }
  498 + &_field {
  499 + font-weight: 400;
  500 + font-size: 28upx;
  501 + line-height: 28upx;
  502 + color: #999999;
  503 + width: 170upx;
  504 + text-align: left;
  505 + }
  506 + &_content {
  507 + flex: 1;
  508 + font-weight: 400;
  509 + font-size: 28upx;
  510 + line-height: 28upx;
  511 + color: #2b2a27;
  512 + text-align: left;
  513 + font-style: normal;
  514 + display: flex;
  515 + justify-content: space-between;
  516 + &_text {
  517 + font-weight: 400;
  518 + font-size: 28upx;
  519 + line-height: 28upx;
  520 + text-align: left;
  521 + font-style: normal;
  522 + }
  523 + &_action {
  524 + font-weight: 400;
  525 + font-size: 28upx;
  526 + line-height: 28upx;
  527 + color: #2673fb;
  528 + text-align: right;
  529 + font-style: normal;
  530 + }
  531 + text + text {
  532 + margin-left: 10rpx;
  533 + }
  534 + }
  535 + }
  536 + .card__item + .card__item {
  537 + margin-top: $padding-sm;
  538 + }
  539 + &__steps {
  540 + margin-top: $padding-md;
  541 + .step {
  542 + &-item {
  543 + display: flex;
  544 + align-content: space-around;
  545 + font-size: $font-md;
  546 + .icon-waypoint {
  547 + font-size: $font-sm;
  548 + margin-right: $padding-sm;
  549 + height: $padding-md * 1.2;
  550 + width: $padding-md * 1.2;
  551 + min-width: $padding-md * 1.2;
  552 + }
  553 + .city {
  554 + font-weight: 500;
  555 + font-size: 32upx;
  556 + color: #2b2a27;
  557 + line-height: 32upx;
  558 + text-align: left;
  559 + font-style: normal;
  560 + }
  561 + .address {
  562 + font-weight: 400;
  563 + font-size: 24upx;
  564 + color: #999999;
  565 + line-height: 33upx;
  566 + text-align: left;
  567 + font-style: normal;
  568 + text + text {
  569 + margin-left: 10rpx;
  570 + }
  571 + }
  572 + .address_action {
  573 + font-weight: 400;
  574 + font-size: 24upx;
  575 + color: #2673fb;
  576 + line-height: 33upx;
  577 + text-align: left;
  578 + font-style: normal;
  579 + display: flex;
  580 + justify-content: space-between;
  581 + .u-icon {
  582 + display: inline-block !important;
  583 + }
  584 + }
  585 + &:not(:first-child) {
  586 + margin-top: $padding-md;
  587 + }
  588 + }
  589 + }
  590 + }
  591 + &_label {
  592 + }
  593 + .label {
  594 + font-weight: 500;
  595 + font-size: 32rpx;
  596 + color: #2b2a27;
  597 + }
  598 + .action {
  599 + font-weight: 400;
  600 + font-size: 28rpx;
  601 + color: #007aff;
  602 + }
  603 + }
  604 + .aux-color {
  605 + color: #999999;
  606 + }
  607 + .main-color {
  608 + color: #2b2a27;
  609 + }
  610 +}
  611 +</style>
pages/order/filter.vue 0 → 100644
@@ -0,0 +1,117 @@ @@ -0,0 +1,117 @@
  1 +<template>
  2 + <Page name="order-filter" flank>
  3 + <template #content>
  4 + <u-form :model="searchForm" ref="uForm" labelWidth="100">
  5 + <u-form-item label="订单号"><u-input v-model="searchForm.code" /></u-form-item>
  6 + <u-form-item label="司机姓名"><u-input v-model="searchForm.driverName" /></u-form-item>
  7 + <u-form-item label="司机手机号"><u-input v-model="searchForm.driverMobile" /></u-form-item>
  8 + <u-form-item label="车牌号"><u-input v-model="searchForm.vehicleLicenseNum" /></u-form-item>
  9 + <u-form-item label="存在未处理异常" labelWidth="130">
  10 + <u-radio-group v-model="searchForm.unHandledExceptionFlag">
  11 + <u-radio v-for="(item, index) in radioList" :key="index" :name="item.value">
  12 + {{ item.text }}
  13 + </u-radio>
  14 + </u-radio-group>
  15 + </u-form-item>
  16 + </u-form>
  17 + </template>
  18 + <template #footer>
  19 + <view class="footer">
  20 + <view class="reset" @click="resetChange">重置</view>
  21 + <view class="inquiry" @click="inquiryChange">查询</view>
  22 + </view>
  23 + </template>
  24 + </Page>
  25 +</template>
  26 +
  27 +<script>
  28 +export default {
  29 + name: 'order-filter',
  30 + props: {
  31 + searchModel: {
  32 + type: Object,
  33 + default: () => {
  34 + return {};
  35 + },
  36 + },
  37 + },
  38 + data() {
  39 + return {
  40 + searchForm: {
  41 + code: '', //
  42 + driverName: '',
  43 + driverMobile: '', // 客户
  44 + vehicleLicenseNum: '',
  45 + unHandledExceptionFlag: '', // 存在异常
  46 + },
  47 + radioList: [
  48 + { text: '是', value: 'true' },
  49 + { text: '否', value: 'false' },
  50 + ],
  51 + };
  52 + },
  53 + onLoad(option) {
  54 + Object.keys(option).forEach(i => {
  55 + this.searchForm[i] = option[i];
  56 + });
  57 + },
  58 + methods: {
  59 + // 重置
  60 + resetChange() {
  61 + this.searchForm = {
  62 + code: '', //
  63 + driverName: '',
  64 + driverMobile: '', // 客户
  65 + vehicleLicenseNum: '',
  66 + unHandledExceptionFlag: '', // 存在异常
  67 + startCityCode: '',
  68 + startCityName: '',
  69 + endCityCode: '',
  70 + endCityName: '',
  71 + projectCode: '',
  72 + projectName: '',
  73 + };
  74 + },
  75 + // 查询
  76 + inquiryChange() {
  77 + this.getOpenerEventChannel().emit('refreshData', this.searchForm);
  78 + setTimeout(() => uni.navigateBack(), 500);
  79 + },
  80 + },
  81 +};
  82 +</script>
  83 +
  84 +<style lang="scss">
  85 +.page-order-filter {
  86 + &__footer {
  87 + background: $color-white;
  88 + .footer {
  89 + display: flex;
  90 + justify-content: space-between;
  91 + .reset {
  92 + text-align: center;
  93 + width: 236upx;
  94 + height: 82upx;
  95 + line-height: 82upx;
  96 + margin-right: 20upx;
  97 + background: #dfebff;
  98 + border-radius: 14upx;
  99 + font-size: 30upx;
  100 + font-weight: 500;
  101 + color: $color-primary;
  102 + }
  103 + .inquiry {
  104 + text-align: center;
  105 + width: 450upx;
  106 + height: 82upx;
  107 + line-height: 82upx;
  108 + background: $color-primary;
  109 + border-radius: 14upx;
  110 + font-size: 30upx;
  111 + font-weight: 500;
  112 + color: #ffffff;
  113 + }
  114 + }
  115 + }
  116 +}
  117 +</style>
pages/order/index.vue 0 → 100644
@@ -0,0 +1,462 @@ @@ -0,0 +1,462 @@
  1 +<template>
  2 + <Page name="freight-order" flank>
  3 + <template #header>
  4 + <u-tabs :current="activeTab" :list="tabList" @click="onTabChange" :scrollable="true" :disabled="loading" :activeStyle="{ color: '#1E7B6B' }"> </u-tabs>
  5 + <view class="line"></view>
  6 + <view class="quick-tag">
  7 + <view class="quick-tag-group">
  8 + <view class="quick-tag-item" :class="searchForm.projectCode ? 'active' : ''" @click="selectQuickTag({ key: 'projectCode', value: searchForm.projectCode })">
  9 + <text>{{ searchForm.projectName || '所属项目' }}</text>
  10 + <view class="sx-img">
  11 + <image v-if="searchForm.projectCode" class="sx-image" :src="formatImagePath('active-down')"></image>
  12 + <image v-else class="sx-image" :src="formatImagePath('down')"></image>
  13 + </view>
  14 + </view>
  15 + <view class="quick-tag-item" :class="searchForm.startCityCode ? 'active' : ''" @click="selectQuickTag({ key: 'startCityCode', value: searchForm.startCityCode })">
  16 + <text>{{ searchForm.startCityName || '始发地' }}</text>
  17 + <view class="sx-img">
  18 + <image v-if="searchForm.startCityCode" class="sx-image" :src="formatImagePath('active-down')"></image>
  19 + <image v-else class="sx-image" :src="formatImagePath('down')"></image>
  20 + </view>
  21 + </view>
  22 + <view class="quick-tag-item" :class="searchForm.endCityCode ? 'active' : ''" @click="selectQuickTag({ key: 'endCityCode', value: searchForm.endCityCode })">
  23 + <text>{{ searchForm.endCityName || '目的地' }}</text>
  24 + <view class="sx-img">
  25 + <image v-if="searchForm.endCityCode" class="sx-image" :src="formatImagePath('active-down')"></image>
  26 + <image v-else class="sx-image" :src="formatImagePath('down')"></image>
  27 + </view>
  28 + </view>
  29 + </view>
  30 + <view class="quick-screen" @click="openFilter">
  31 + <image class="search-image" :src="formatImagePath('search')"></image>
  32 + </view>
  33 + </view>
  34 + </template>
  35 + <template #content>
  36 + <List ref="list" v-model="list" :api="orderAPI" @update:loading="e => (loading = e)">
  37 + <template v-for="(item, index) in list">
  38 + <card
  39 + @more="more"
  40 + @cancel="cancelOrder"
  41 + @delete="deleteOrder"
  42 + @uploadReceipt="toUploadReceipt"
  43 + @start="toStartCar"
  44 + @arrival="toArrivalCar"
  45 + @qrShow="qrCodeShow"
  46 + :key="index"
  47 + :item="item"
  48 + @tap="toDetail(item.code)"
  49 + ></card>
  50 + </template>
  51 + <template #empty>
  52 + <Empty tips="暂无数据" />
  53 + </template>
  54 + </List>
  55 + <view v-if="$permission('/freightOrder/add')" class="add-order" @tap="toAddPage('')">
  56 + <image class="sx-image" src="/static/addOrder.png"></image>
  57 + </view>
  58 + </template>
  59 + <u-popup :show="popShow" @close="closePop" closeable>
  60 + <view class="popup">
  61 + <view class="title">{{ popConfig[popType].title }}</view>
  62 + <u--textarea v-model="popValue" :placeholder="popConfig[popType].placeholder" placeholderStyle="background:#f6f6f6" :cursorSpacing="60"></u--textarea>
  63 + <view class="but">
  64 + <u-button type="primary" @tap="popSubmit">确定</u-button>
  65 + </view>
  66 + </view>
  67 + </u-popup>
  68 + <u-popup :show="qrShow" @close="qrShow = false" mode="center" closeable>
  69 + <l-painter ref="painter" :board="poster"></l-painter>
  70 + <view style="margin-top: 30upx">
  71 + <u-button type="primary" @click="saveQrImage">保存</u-button>
  72 + </view>
  73 + </u-popup>
  74 + </Page>
  75 +</template>
  76 +<script>
  77 +import { urlParam } from '@/utils/param';
  78 +import card from './card.vue';
  79 +import page from '../../mixins/page';
  80 +import qrPainter from './qr-painter';
  81 +import UButton from '../../uni_modules/uview-ui/components/u-button/u-button.vue';
  82 +export default {
  83 + name: 'order',
  84 + mixins: [page, qrPainter],
  85 + components: { UButton, card },
  86 + data() {
  87 + return {
  88 + poster: {},
  89 + qrShow: false,
  90 + popType: 'cancel',
  91 + popValue: '',
  92 + popConfig: {
  93 + cancel: { fun: '', title: '取消原因', placeholder: '请输入取消原因,必填' },
  94 + delete: { fun: '', title: '删除原因', placeholder: '请输入删除原因,必填' },
  95 + },
  96 + loading: false,
  97 + popShow: false,
  98 + currentCode: '',
  99 + searchForm: {
  100 + projectCode: '',
  101 + projectName: '',
  102 + code: '', //
  103 + driverName: '',
  104 + driverMobile: '', // 客户
  105 + vehicleLicenseNum: '',
  106 + unHandledExceptionFlag: '', // 存在异常
  107 + startCityCode: '',
  108 + endCityCode: '',
  109 + status: '',
  110 + },
  111 + activeTab: 0,
  112 + count: {},
  113 + list: [],
  114 + };
  115 + },
  116 + onPullDownRefresh() {
  117 + this.onSearch();
  118 + },
  119 + computed: {
  120 + tabList() {
  121 + let list = [
  122 + { name: '全部', value: '', key: 'allCount' },
  123 + { name: '待确认', value: 'WAIT_CONFIRM', key: 'waitConfirm' },
  124 + { name: '待接单', value: 'WAIT_ACCEPT', key: 'waitAccept' },
  125 + { name: '待发车', value: 'WAIT_DEPART', key: 'waitDepart' },
  126 + { name: '运输中', value: 'TRANSFER', key: 'transfer' },
  127 + { name: '已完成', value: 'COMPLETED', key: 'completed' },
  128 + { name: '已取消', value: 'CANCEL', key: 'cancel' },
  129 + ];
  130 + return Object.keys(this.count).length > 0
  131 + ? list.map(item => {
  132 + return { ...item, name: `${item.name}(${this.count[item.key] || 0})`, disabled: this.loading };
  133 + })
  134 + : list;
  135 + },
  136 + },
  137 + methods: {
  138 + onTabChange({ index }) {
  139 + if (this.loading) {
  140 + return;
  141 + }
  142 + this.activeTab = index;
  143 + this.list = [];
  144 + this.onSearch();
  145 + },
  146 + selectQuickTag({ key, value }) {
  147 + this.searchForm = Object.assign(this.searchForm, { [key]: value });
  148 + if (key == 'startCityCode') {
  149 + uni.$once('select-city', option => {
  150 + this.searchForm.startCityCode = option.code;
  151 + this.searchForm.startCityName = option.shortName;
  152 + this.onSearch();
  153 + });
  154 + uni.navigateTo({ url: '/pages/global/search-city' });
  155 + } else if (key == 'endCityCode') {
  156 + uni.$once('select-city', option => {
  157 + this.searchForm.endCityCode = option.code;
  158 + this.searchForm.endCityName = option.shortName;
  159 + this.onSearch();
  160 + });
  161 + uni.navigateTo({ url: '/pages/global/search-city' });
  162 + } else if (key == 'projectCode') {
  163 + uni.$once('select-common', option => {
  164 + this.searchForm.projectCode = option.code;
  165 + this.searchForm.projectName = option.name;
  166 + this.onSearch();
  167 + });
  168 + uni.navigateTo({
  169 + url: `/pages/global/search-common${urlParam({
  170 + mode: 'select',
  171 + url: 'projectCode',
  172 + title: '项目',
  173 + label: 'name',
  174 + value: '',
  175 + })}`,
  176 + });
  177 + }
  178 + },
  179 + // 再来一单
  180 + more(code) {
  181 + this.currentCode = code;
  182 + this.toAddPage('?code=' + code);
  183 + },
  184 + // 取消订单
  185 + cancelOrder(code) {
  186 + this.currentCode = code;
  187 + this.popType = 'cancel';
  188 + this.popValue = '';
  189 + this.popShow = true;
  190 + uni.hideTabBar();
  191 + },
  192 + closePop() {
  193 + setTimeout(() => uni.showTabBar(), 300);
  194 + this.popShow = false;
  195 + },
  196 + popSubmit() {
  197 + if (!this.popValue) {
  198 + uni.showToast({ title: '请输入原因', icon: 'none' });
  199 + return;
  200 + }
  201 + uni.$u.api.freightOrder[this.popType]({
  202 + codeList: [this.currentCode],
  203 + reason: this.popValue,
  204 + }).then(res => {
  205 + if (res.success) {
  206 + this.closePop();
  207 + this.onSearch();
  208 + }
  209 + });
  210 + },
  211 + // 删除订单
  212 + deleteOrder(code) {
  213 + this.currentCode = code;
  214 + this.popType = 'delete';
  215 + this.popValue = '';
  216 + this.popShow = true;
  217 + uni.hideTabBar();
  218 + },
  219 + toUploadReceipt(code) {
  220 + uni.navigateTo({
  221 + url: '/pages/order/upload-receipt?code=' + code,
  222 + events: {
  223 + refreshData: () => {
  224 + this.onSearch();
  225 + },
  226 + },
  227 + });
  228 + },
  229 + toAddPage(param) {
  230 + uni.navigateTo({
  231 + url: '/pages/order/add' + param,
  232 + events: {
  233 + refreshData: option => {
  234 + this.onSearch();
  235 + },
  236 + },
  237 + });
  238 + },
  239 + // 筛选
  240 + openFilter() {
  241 + uni.navigateTo({
  242 + url: `/pages/order/filter${urlParam(this.searchForm)}`,
  243 + events: {
  244 + refreshData: option => {
  245 + this.searchForm = { ...this.searchForm, ...option };
  246 + this.onSearch();
  247 + },
  248 + },
  249 + });
  250 + },
  251 + orderAPI(params) {
  252 + let format = {
  253 + ...this.searchForm,
  254 + status: this.tabList[this.activeTab].value,
  255 + };
  256 + this.getAggregateType(format);
  257 + return uni.$u.api.freightOrder.page({
  258 + ...format,
  259 + ...params,
  260 + });
  261 + },
  262 + // 获取聚合数量
  263 + getAggregateType(params) {
  264 + uni.$u.api.freightOrder.count({ ...params, status: '' }).then(res => {
  265 + this.count = res?.result || {};
  266 + });
  267 + },
  268 + toDetail(code) {
  269 + uni.navigateTo({ url: '/pages/order/detail?code=' + code });
  270 + },
  271 + toStartCar(code) {
  272 + uni.navigateTo({
  273 + url: '/pages/order/start-car?code=' + code,
  274 + events: {
  275 + refreshData: () => {
  276 + this.onSearch();
  277 + },
  278 + },
  279 + });
  280 + },
  281 + toArrivalCar(code) {
  282 + uni.navigateTo({
  283 + url: '/pages/order/arrival-car?code=' + code,
  284 + events: {
  285 + refreshData: () => {
  286 + this.onSearch();
  287 + },
  288 + },
  289 + });
  290 + },
  291 + qrCodeShow(code, data) {
  292 + if (this.loading) return;
  293 + this.loading = true;
  294 + this.qrShow = true;
  295 + uni.$u.api.freightOrder
  296 + .getSensitiveByOrderCode({ orderCode: code })
  297 + .then(res => {
  298 + if (res.success) {
  299 + uni.$u.api.freightOrder
  300 + .buildMaQrcode({ orderCode: code })
  301 + .then(res2 => {
  302 + this.loading = false;
  303 + if (res2.success) {
  304 + this.poster = this.getPoster(res.result, data, res2.result);
  305 + console.info(this.poster);
  306 + }
  307 + })
  308 + .catch(e => {
  309 + this.loading = false;
  310 + });
  311 + }
  312 + })
  313 + .catch(e => {
  314 + this.loading = false;
  315 + });
  316 + },
  317 + },
  318 +};
  319 +</script>
  320 +<style lang="scss">
  321 +.page-freight-order {
  322 + &__header {
  323 + padding: 0 !important;
  324 +
  325 + .line {
  326 + height: 1rpx;
  327 + background: #f6f6f6;
  328 + position: relative;
  329 + top: -5rpx;
  330 + }
  331 +
  332 + .quick-tag {
  333 + display: flex;
  334 + padding: 15upx 22upx;
  335 + box-sizing: border-box;
  336 + position: relative;
  337 +
  338 + .quick-cover {
  339 + width: 25upx;
  340 + height: 90upx;
  341 + position: absolute;
  342 + right: 122upx;
  343 + top: 0;
  344 +
  345 + .cover-image {
  346 + width: 100%;
  347 + height: 100%;
  348 + }
  349 + }
  350 +
  351 + .quick-screen {
  352 + width: 100upx;
  353 + display: flex;
  354 + align-items: center;
  355 + justify-content: center;
  356 +
  357 + .search-image {
  358 + width: 42upx;
  359 + height: 42upx;
  360 + }
  361 + }
  362 +
  363 + .quick-tag-group {
  364 + flex: 1;
  365 + display: flex;
  366 + align-items: center;
  367 + background-color: #fff;
  368 + padding-left: $padding-xs !important;
  369 + padding-right: $padding-xs !important;
  370 + overflow-y: auto;
  371 +
  372 + .quick-tag-item {
  373 + flex-shrink: 0;
  374 + min-width: 158upx;
  375 + height: 58upx;
  376 + background: #f6f6f6;
  377 + border-radius: 8upx;
  378 + font-size: 28upx;
  379 + font-weight: 400;
  380 + color: #2b2a27;
  381 + display: flex;
  382 + align-items: center;
  383 + justify-content: center;
  384 + padding: 0 10upx;
  385 + box-sizing: border-box;
  386 +
  387 + &:not(:last-child) {
  388 + margin-right: 18upx;
  389 + }
  390 +
  391 + &.active {
  392 + background: #ffffff;
  393 + border-radius: 8upx;
  394 + border: 2upx solid #2673fb;
  395 + font-size: 28upx;
  396 + font-family:
  397 + PingFangSC,
  398 + PingFang SC;
  399 + font-weight: 400;
  400 + color: #2673fb;
  401 + }
  402 +
  403 + .sx-img {
  404 + height: 12upx;
  405 + width: 14upx;
  406 + position: relative;
  407 + margin-left: 12upx;
  408 +
  409 + .sx-image {
  410 + width: 100%;
  411 + height: 100%;
  412 + position: absolute;
  413 + top: 0;
  414 + left: 0;
  415 + }
  416 + }
  417 + }
  418 +
  419 + .z-dropdown__text .text {
  420 + word-break: keep-all;
  421 + }
  422 + }
  423 + }
  424 + }
  425 + .add-order {
  426 + right: 34upx;
  427 + bottom: 34upx;
  428 + height: 106upx;
  429 + width: 106upx;
  430 + position: fixed;
  431 + .sx-image {
  432 + width: 100%;
  433 + height: 100%;
  434 + position: absolute;
  435 + top: 0;
  436 + left: 0;
  437 + }
  438 + }
  439 + .popup {
  440 + padding-left: $padding-md;
  441 + padding-right: $padding-md;
  442 + border-top-left-radius: $radius-md;
  443 + border-top-right-radius: $radius-md;
  444 + .title {
  445 + padding-top: $padding-xs;
  446 + padding-bottom: $padding-xs;
  447 + display: flex;
  448 + align-content: center;
  449 + justify-content: center;
  450 + font-weight: 400;
  451 + font-size: 32rpx;
  452 + color: #2b2a27;
  453 + line-height: 45px;
  454 + text-align: left;
  455 + font-style: normal;
  456 + }
  457 + .but {
  458 + margin-top: $padding-md;
  459 + }
  460 + }
  461 +}
  462 +</style>
pages/order/qr-painter.js 0 → 100644
@@ -0,0 +1,288 @@ @@ -0,0 +1,288 @@
  1 +import dayjs from 'dayjs';
  2 +export default {
  3 + data() {
  4 + return {
  5 + posterCss: { width: '150rpx', height: '150rpx', padding: '11rpx', backgroundColor: '#FFFFFF', borderRadius: '50%', objectFit: 'cover' }, // 二维码大小样式
  6 + QRcss: { position: 'fixed', left: '52rpx', bottom: '24rpx', display: 'flex' }, // 二维码定位样式
  7 + };
  8 + },
  9 + methods: {
  10 + saveQrImage() {
  11 + this.$refs.painter.canvasToTempFilePathSync({
  12 + fileType: 'jpg',
  13 + // 如果返回的是base64是无法使用 saveImageToPhotosAlbum,需要设置 pathType为url
  14 + pathType: 'url',
  15 + quality: 1,
  16 + success: res => {
  17 + uni.saveImageToPhotosAlbum({
  18 + filePath: res.tempFilePath,
  19 + success: () => {
  20 + this.qrShow = false;
  21 + uni.showToast({ title: '保存成功', icon: 'none' });
  22 + },
  23 + });
  24 + },
  25 + });
  26 + },
  27 + getPoster(item, params, wxcode) {
  28 + let driverInfo = item.driverName ? item.driverName : '';
  29 + driverInfo += item.driverMobile ? item.driverMobile : '';
  30 + let vehicle = item.vehicleLicenseNum;
  31 + if (item.trailerLicenseNum) {
  32 + vehicle += '·' + item.trailerLicenseNum;
  33 + }
  34 + return {
  35 + css: {
  36 + width: '640rpx',
  37 + height: '880rpx',
  38 + backgroundImage: 'url(https://zeyi-tms-product.oss-cn-hangzhou.aliyuncs.com/image/freight/b6988d70-26db-490c-9ddf-e59c554fa2ff.png)',
  39 + objectFit: 'cover',
  40 + },
  41 + views: [
  42 + {
  43 + type: 'view',
  44 + views: [
  45 + {
  46 + type: 'text',
  47 + text: '订 单 号:',
  48 + css: {
  49 + width: '300rpx',
  50 + height: '33rpx',
  51 + fontSize: '24rpx',
  52 + fontSamily: 'PingFangSC-Regular',
  53 + color: '#999999',
  54 + lineHeight: '33rpx',
  55 + display: 'block',
  56 + boxOrient: 'vertical',
  57 + lineClamp: 1 /* 这里是超出几行省略 */,
  58 + position: 'fixed',
  59 + top: '169rpx',
  60 + left: '75rpx',
  61 + },
  62 + },
  63 + {
  64 + type: 'text',
  65 + text: params.code,
  66 + css: {
  67 + width: '400rpx',
  68 + height: '33rpx',
  69 + fontSize: '24rpx',
  70 + fontSamily: 'PingFangSC-Regular',
  71 + color: '#121212',
  72 + lineHeight: '33rpx',
  73 + overflow: 'hidden',
  74 + textOverflow: 'ellipsis',
  75 + display: 'block',
  76 + boxOrient: 'vertical',
  77 + lineClamp: 1 /* 这里是超出几行省略 */,
  78 + position: 'fixed',
  79 + top: '169rpx',
  80 + left: '195rpx',
  81 + },
  82 + },
  83 + {
  84 + type: 'text',
  85 + text: '任务日期:',
  86 + css: {
  87 + width: '400rpx',
  88 + height: '33rpx',
  89 + fontSize: '24rpx',
  90 + fontSamily: 'PingFangSC-Regular',
  91 + color: '#999999',
  92 + lineHeight: '33rpx',
  93 + display: 'block',
  94 + boxOrient: 'vertical',
  95 + lineClamp: 1 /* 这里是超出几行省略 */,
  96 + position: 'fixed',
  97 + top: '204rpx',
  98 + left: '75rpx',
  99 + },
  100 + },
  101 + {
  102 + type: 'text',
  103 + text: dayjs(params.loadTime).format('YYYY-MM-DD'),
  104 + css: {
  105 + width: '400rpx',
  106 + height: '33rpx',
  107 + fontSize: '24rpx',
  108 + fontSamily: 'PingFangSC-Regular',
  109 + color: '#121212',
  110 + lineHeight: '33rpx',
  111 + overflow: 'hidden',
  112 + textOverflow: 'ellipsis',
  113 + display: 'block',
  114 + boxOrient: 'vertical',
  115 + lineClamp: 1 /* 这里是超出几行省略 */,
  116 + position: 'fixed',
  117 + top: '204rpx',
  118 + left: '195rpx',
  119 + },
  120 + },
  121 + {
  122 + type: 'text',
  123 + text: params.startCityName + '-' + params.startAreaName,
  124 + css: {
  125 + width: '400rpx',
  126 + height: '40rpx',
  127 + fontSize: '36rpx',
  128 + fontSamily: 'PingFangSC-Semibold, PingFang SC',
  129 + fontWeight: '600',
  130 + color: '#051B33',
  131 + lineHeight: '40rpx',
  132 + overflow: 'hidden',
  133 + textOverflow: 'ellipsis',
  134 + display: 'block',
  135 + boxOrient: 'vertical',
  136 + lineClamp: 1 /* 这里是超出几行省略 */,
  137 + position: 'fixed',
  138 + top: '270rpx',
  139 + left: '129rpx',
  140 + },
  141 + },
  142 + {
  143 + type: 'text',
  144 + text: params.endCityName + '-' + params.endAreaName,
  145 + css: {
  146 + width: '400rpx',
  147 + height: '40rpx',
  148 + fontSize: '36rpx',
  149 + fontSamily: 'PingFangSC-Semibold, PingFang SC',
  150 + fontWeight: '600',
  151 + color: '#051B33',
  152 + lineHeight: '40rpx',
  153 + overflow: 'hidden',
  154 + textOverflow: 'ellipsis',
  155 + display: 'block',
  156 + boxOrient: 'vertical',
  157 + lineClamp: 1 /* 这里是超出几行省略 */,
  158 + position: 'fixed',
  159 + top: '405rpx',
  160 + left: '129rpx',
  161 + },
  162 + },
  163 + {
  164 + type: 'text',
  165 + text: '总里程:' + item.distance + 'KM',
  166 + css: {
  167 + width: '400rpx',
  168 + height: '33rpx',
  169 + fontSize: '24rpx',
  170 + fontWeight: '400',
  171 + fontSamily: 'PingFangSC-Medium, PingFang SC',
  172 + color: '#999999',
  173 + lineHeight: '33rpx',
  174 + position: 'fixed',
  175 + top: '345rpx',
  176 + left: '129rpx',
  177 + },
  178 + },
  179 + {
  180 + type: 'text',
  181 + text: '订单备注:',
  182 + css: {
  183 + width: '400rpx',
  184 + height: '33rpx',
  185 + fontSize: '24rpx',
  186 + fontSamily: 'PingFangSC-Regular',
  187 + color: '#999999',
  188 + lineHeight: '33rpx',
  189 + display: 'block',
  190 + boxOrient: 'vertical',
  191 + lineClamp: 1 /* 这里是超出几行省略 */,
  192 + position: 'fixed',
  193 + top: '477rpx',
  194 + left: '75rpx',
  195 + },
  196 + },
  197 + {
  198 + type: 'text',
  199 + text: params.remark,
  200 + css: {
  201 + width: '350rpx',
  202 + height: '33rpx',
  203 + fontSize: '24rpx',
  204 + fontSamily: 'PingFangSC-Regular',
  205 + color: '#121212',
  206 + lineHeight: '33rpx',
  207 + overflow: 'hidden',
  208 + textOverflow: 'ellipsis',
  209 + display: 'block',
  210 + boxOrient: 'vertical',
  211 + lineClamp: 1 /* 这里是超出几行省略 */,
  212 + position: 'fixed',
  213 + top: '477rpx',
  214 + left: '195rpx',
  215 + },
  216 + },
  217 + {
  218 + type: 'text',
  219 + text: '司 机:',
  220 + css: {
  221 + width: '400rpx',
  222 + height: '33rpx',
  223 + fontSize: '26rpx',
  224 + fontSamily: 'PingFangSC-Regular',
  225 + color: '#FFFFFF',
  226 + lineHeight: '33rpx',
  227 + display: 'block',
  228 + boxOrient: 'vertical',
  229 + lineClamp: 1 /* 这里是超出几行省略 */,
  230 + position: 'fixed',
  231 + top: '564rpx',
  232 + left: '75rpx',
  233 + },
  234 + },
  235 + {
  236 + type: 'text',
  237 + text: driverInfo,
  238 + css: {
  239 + width: '400rpx',
  240 + height: '33rpx',
  241 + fontSize: '26rpx',
  242 + fontSamily: 'PingFangSC-Regular',
  243 + color: '#FFFFFF',
  244 + lineHeight: '33rpx',
  245 + display: 'block',
  246 + boxOrient: 'vertical',
  247 + lineClamp: 1 /* 这里是超出几行省略 */,
  248 + position: 'fixed',
  249 + top: '564rpx',
  250 + left: '180rpx',
  251 + },
  252 + },
  253 + {
  254 + type: 'text',
  255 + text: '车牌号:' + vehicle,
  256 + css: {
  257 + width: '400rpx',
  258 + height: '33rpx',
  259 + fontSize: '26rpx',
  260 + fontSamily: 'PingFangSC-Regular',
  261 + color: '#FFFFFF',
  262 + lineHeight: '33rpx',
  263 + display: 'block',
  264 + boxOrient: 'vertical',
  265 + lineClamp: 1 /* 这里是超出几行省略 */,
  266 + position: 'fixed',
  267 + top: '613rpx',
  268 + left: '75rpx',
  269 + },
  270 + },
  271 + ],
  272 + },
  273 + {
  274 + type: 'view',
  275 + css: this.QRcss,
  276 + views: [
  277 + {
  278 + src: wxcode,
  279 + type: 'image',
  280 + css: this.posterCss,
  281 + },
  282 + ],
  283 + },
  284 + ],
  285 + };
  286 + },
  287 + },
  288 +};
pages/order/start-car.vue 0 → 100644
@@ -0,0 +1,117 @@ @@ -0,0 +1,117 @@
  1 +<template>
  2 + <Page name="start-car">
  3 + <template #content>
  4 + <view class="address">
  5 + <view class="icon-waypoint icon-start">装</view>
  6 + <text>{{ item.waypoints[0].address }}</text>
  7 + </view>
  8 + <u-form :model="form" ref="uForm" labelWidth="100">
  9 + <view class="card">
  10 + <u-form-item label="实际发车时间" @click="showLoadTime = true" required>
  11 + <u-input v-model="form.departTime" border="none" suffix-icon="arrow-right" placeholder="请选择时间" disabledColor="#ffffff" disabled />
  12 + </u-form-item>
  13 + </view>
  14 + <view class="card">
  15 + <u-form-item label="上传照片">
  16 + <z-upload v-model="item.receiptAttachment" :limit="20"></z-upload>
  17 + </u-form-item>
  18 + </view>
  19 + </u-form>
  20 + </template>
  21 + <u-datetime-picker :show="showLoadTime" :value="loadTimeDef" @cancel="showLoadTime = false" @close="showLoadTime = false" @confirm="loadTimeFormat"></u-datetime-picker>
  22 + <template #footer>
  23 + <u-button type="primary" @tap="submit">确认发车</u-button>
  24 + </template>
  25 + </Page>
  26 +</template>
  27 +
  28 +<script>
  29 +import ZUpload from '../../components/zee/z-upload.vue';
  30 +import dayjs from 'dayjs';
  31 +
  32 +export default {
  33 + name: 'startCar',
  34 + components: { ZUpload },
  35 + data() {
  36 + return {
  37 + showLoadTime: false,
  38 + loadTimeDef: new Date(),
  39 + form: {
  40 + departTime: '',
  41 + receiptAttachment: '',
  42 + },
  43 + item: {},
  44 + };
  45 + },
  46 + onLoad(options) {
  47 + if (options.code) {
  48 + this.initData(options.code);
  49 + }
  50 + },
  51 + methods: {
  52 + initData(code) {
  53 + uni.$u.api.freightOrder.getDetail({ code }).then(res => {
  54 + this.item = res.result || {};
  55 + this.form = {
  56 + departTime: this.item.confirmDepartureTime,
  57 + receiptAttachment: this.item.receiptAttachment,
  58 + };
  59 + });
  60 + },
  61 + loadTimeFormat({ value }) {
  62 + this.form.departTime = dayjs(value).format('YYYY-MM-DD HH:mm:ss');
  63 + this.showLoadTime = false;
  64 + },
  65 + submit() {
  66 + if (!this.form.departTime) {
  67 + uni.showToast({ title: '发车时间不能为空', icon: 'none' });
  68 + return;
  69 + }
  70 + if (new Date(this.form.departTime).getTime() > new Date().getTime()) {
  71 + uni.showToast({ title: '发车时间不能大于当前时间', icon: 'none' });
  72 + return;
  73 + }
  74 + uni.$u.api.freightOrder.depart({ codeList: [this.item.code], ...this.form }).then(res => {
  75 + if (res.success) {
  76 + uni.showToast({ title: '操作成功', icon: 'none' });
  77 + this.getOpenerEventChannel().emit('refreshData');
  78 + setTimeout(() => uni.navigateBack(), 500);
  79 + }
  80 + });
  81 + },
  82 + },
  83 +};
  84 +</script>
  85 +
  86 +<style lang="scss">
  87 +.page-start-car {
  88 + &__content {
  89 + padding-top: 0 !important;
  90 + }
  91 + &__footer {
  92 + background: $color-white;
  93 + }
  94 + .address {
  95 + background-color: $color-white;
  96 + padding: $padding-md;
  97 + .icon-waypoint {
  98 + font-size: $font-sm;
  99 + margin-right: $padding-sm;
  100 + height: $padding-md * 1.2;
  101 + width: $padding-md * 1.2;
  102 + min-width: $padding-md * 1.2;
  103 + }
  104 + }
  105 + .card {
  106 + color: #999999;
  107 + margin: $padding-md;
  108 + background-color: $color-white;
  109 + border-radius: $radius-md;
  110 + box-shadow: $shadow-normal;
  111 + .u-form-item {
  112 + padding-left: $padding-md !important;
  113 + padding-right: $padding-sm !important;
  114 + }
  115 + }
  116 +}
  117 +</style>
pages/order/upload-receipt.vue 0 → 100644
@@ -0,0 +1,74 @@ @@ -0,0 +1,74 @@
  1 +<template>
  2 + <Page name="upload-receipt" flank>
  3 + <template #content>
  4 + <u-form :model="form" ref="uForm" labelWidth="100">
  5 + <view class="card">
  6 + <u-form-item label="上传回单">
  7 + <z-upload v-model="form.receiptAttachment" :limit="20"></z-upload>
  8 + </u-form-item>
  9 + </view>
  10 + </u-form>
  11 + </template>
  12 + <template #footer>
  13 + <u-button type="primary" @tap="submit">确认上传</u-button>
  14 + </template>
  15 + </Page>
  16 +</template>
  17 +
  18 +<script>
  19 +import ZUpload from '../../components/zee/z-upload.vue';
  20 +import dayjs from 'dayjs';
  21 +
  22 +export default {
  23 + name: 'upload-receipt',
  24 + components: { ZUpload },
  25 + data() {
  26 + return {
  27 + form: {
  28 + receiptAttachment: '',
  29 + },
  30 + item: {},
  31 + };
  32 + },
  33 + onLoad(options) {
  34 + if (options.code) {
  35 + this.initData(options.code);
  36 + }
  37 + },
  38 + methods: {
  39 + initData(code) {
  40 + uni.$u.api.freightOrder.getDetail({ code }).then(res => {
  41 + this.item = res.result || {};
  42 + this.form.receiptAttachment = this.item.receiptAttachment;
  43 + });
  44 + },
  45 + submit() {
  46 + uni.$u.api.freightOrder.modifyReceiptAttachment({ code: this.item.code, ...this.form }).then(res => {
  47 + if (res.success) {
  48 + uni.showToast({ title: '操作成功', icon: 'none' });
  49 + this.getOpenerEventChannel().emit('refreshData');
  50 + setTimeout(() => uni.navigateBack(), 500);
  51 + }
  52 + });
  53 + },
  54 + },
  55 +};
  56 +</script>
  57 +
  58 +<style lang="scss">
  59 +.page-upload-receipt {
  60 + &__footer {
  61 + background: $color-white;
  62 + }
  63 + .card {
  64 + color: #999999;
  65 + background-color: $color-white;
  66 + border-radius: $radius-md;
  67 + box-shadow: $shadow-normal;
  68 + .u-form-item {
  69 + padding-left: $padding-md !important;
  70 + padding-right: $padding-sm !important;
  71 + }
  72 + }
  73 +}
  74 +</style>
pages/settlement/card.vue 0 → 100644
@@ -0,0 +1,166 @@ @@ -0,0 +1,166 @@
  1 +<template>
  2 + <view class="settlement-card">
  3 + <view class="title">
  4 + <view class="code">
  5 + <field-copy :value="item.payCode" v-if="item.payCode">{{ item.payCode }} </field-copy>
  6 + </view>
  7 + <render-dict v-if="item.applyStatus" class="status" :style="{ color: colorMap[item.applyStatus] }" dict="PAY_APPLY_STATUS" :value="item.applyStatus"></render-dict>
  8 + </view>
  9 + <view class="title-sub">{{ item.projectName ? item.projectName : '' }}{{ item.loadTime ? '|' + item.loadTime + '装货' : '' }}</view>
  10 + <view class="item">
  11 + <view class="label">
  12 + <render-dict v-if="item.feeType" dict="ONLINE_FREIGHT_ORDER_FEE_TYPE" :value="item.feeType"></render-dict>
  13 + </view>
  14 + <view class="content">
  15 + <text class="amount">¥{{ item.feeAmount ? item.feeAmount : '' }}</text>
  16 + </view>
  17 + </view>
  18 + <view class="item">
  19 + <view class="label">承运司机</view>
  20 + <view class="content">
  21 + <text>{{ item.driverName ? item.driverName : '' }}</text>
  22 + <text>{{ item.driverMobile ? item.driverMobile : '' }}</text>
  23 + </view>
  24 + </view>
  25 + <view class="item">
  26 + <view class="label">收款人</view>
  27 + <view class="content">
  28 + <text>{{ item.recAccountName ? item.recAccountName : '' }}</text>
  29 + <text>{{ item.recMobile ? item.recMobile : '' }}</text>
  30 + </view>
  31 + </view>
  32 + <view class="item">
  33 + <view class="label">承运车辆</view>
  34 + <view class="content">{{ item.vehicleLicenseNum ? item.vehicleLicenseNum : '' }}{{ item.trailerLicenseNum ? '·' + item.trailerLicenseNum : '' }}</view>
  35 + </view>
  36 + <view class="item">
  37 + <view class="label">订单号</view>
  38 + <view class="content">
  39 + <text>{{ item.orderCode }}</text>
  40 + <text v-if="!!item.waitHandleExceptionNumber" class="content--warning">{{ item.waitHandleExceptionNumber || '0' }}个异常待处理</text>
  41 + </view>
  42 + </view>
  43 + <view class="item">
  44 + <view class="label">线路名称</view>
  45 + <view class="content">{{ item.lineName ? item.lineName : '' }}</view>
  46 + </view>
  47 + <view class="item" v-if="'WAIT_APPLY' === item.applyStatus">
  48 + <u-button v-if="$permission('/paymentApply/apply')" type="primary" @tap.stop="applyFun">申请支付</u-button>
  49 + </view>
  50 + <view class="item" v-else>
  51 + <u-button v-if="'WAIT_AUDIT' === item.applyStatus && $permission('/paymentApply/apply')" @tap.stop="cancelApplyFun">撤回申请</u-button>
  52 + <u-button v-if="$permission('/paymentApply/audit')" type="primary" @tap.stop="auditFun">审核申请</u-button>
  53 + </view>
  54 + </view>
  55 +</template>
  56 +<script>
  57 +import FieldCopy from '../../components/field/field-copy.vue';
  58 +import UButton from '../../uni_modules/uview-ui/components/u-button/u-button.vue';
  59 +import page from '../../mixins/page';
  60 +
  61 +export default {
  62 + name: 'settlement-card',
  63 + mixins: [page],
  64 + components: { UButton, FieldCopy },
  65 + props: {
  66 + item: {
  67 + type: Object,
  68 + default() {
  69 + return {};
  70 + },
  71 + },
  72 + },
  73 + data() {
  74 + return {
  75 + visible: false,
  76 + colorMap: {
  77 + WAIT_APPLY: '#F52723',
  78 + WAIT_AUDIT: '#FF9339',
  79 + AUDITED: '#00B87A',
  80 + },
  81 + };
  82 + },
  83 + methods: {
  84 + applyFun() {
  85 + this.$emit('apply', this.item);
  86 + },
  87 + cancelApplyFun() {
  88 + this.$emit('cancelApply', this.item);
  89 + },
  90 + auditFun() {
  91 + this.$emit('audit', this.item);
  92 + },
  93 + },
  94 +};
  95 +</script>
  96 +
  97 +<style scoped lang="scss">
  98 +.settlement-card {
  99 + background-color: $color-white;
  100 + color: $color-text;
  101 + padding: $padding-sm;
  102 + margin-bottom: $padding-sm;
  103 + border-radius: $radius-md;
  104 + box-shadow: $shadow-normal;
  105 + font-size: $font-md;
  106 + .title {
  107 + padding-bottom: $padding-sm;
  108 + display: flex;
  109 + justify-content: space-between;
  110 + .code {
  111 + font-weight: 500;
  112 + font-size: 30upx;
  113 + color: #2b2a27;
  114 + line-height: 34upx;
  115 + text-align: left;
  116 + font-style: normal;
  117 + }
  118 + border-bottom: 1px solid $color-border;
  119 + }
  120 + .title-sub {
  121 + margin-top: $padding-sm;
  122 + font-weight: 400;
  123 + font-size: 26upx;
  124 + color: #5d5d5d;
  125 + line-height: 37upx;
  126 + text-align: left;
  127 + font-style: normal;
  128 + }
  129 + .item {
  130 + margin-top: $padding-sm;
  131 + display: flex;
  132 + .label {
  133 + width: 170upx;
  134 + font-weight: 400;
  135 + font-size: 28upx;
  136 + color: #999999;
  137 + line-height: 28upx;
  138 + text-align: left;
  139 + font-style: normal;
  140 + }
  141 + .content {
  142 + font-weight: 400;
  143 + font-size: 28upx;
  144 + color: #2b2a27;
  145 + line-height: 28upx;
  146 + text-align: left;
  147 + font-style: normal;
  148 + text + text {
  149 + margin-left: $padding-sm;
  150 + }
  151 + .amount {
  152 + color: #ff4f3b;
  153 + }
  154 + &--warning {
  155 + color: #f52723;
  156 + font-size: 20rpx;
  157 + margin-left: 20upx;
  158 + padding-left: 10upx;
  159 + padding-right: 10upx;
  160 + border-radius: 8upx;
  161 + border: 2rpx solid #f52723;
  162 + }
  163 + }
  164 + }
  165 +}
  166 +</style>
pages/settlement/filter.vue 0 → 100644
@@ -0,0 +1,100 @@ @@ -0,0 +1,100 @@
  1 +<template>
  2 + <Page name="order-filter" flank>
  3 + <template #content>
  4 + <u-form :model="searchForm" ref="uForm" labelWidth="100">
  5 + <u-form-item label="订单号"><u-input v-model="searchForm.orderCode" /></u-form-item>
  6 + <u-form-item label="内部单号"><u-input v-model="searchForm.customerOrderCodes" /></u-form-item>
  7 + </u-form>
  8 + </template>
  9 + <template #footer>
  10 + <view class="footer">
  11 + <view class="reset" @click="resetChange">重置</view>
  12 + <view class="inquiry" @click="inquiryChange">查询</view>
  13 + </view>
  14 + </template>
  15 + </Page>
  16 +</template>
  17 +
  18 +<script>
  19 +export default {
  20 + name: 'settlement-filter',
  21 + props: {
  22 + searchModel: {
  23 + type: Object,
  24 + default: () => {
  25 + return {};
  26 + },
  27 + },
  28 + },
  29 + data() {
  30 + return {
  31 + searchForm: {
  32 + orderCode: '', // 订单号
  33 + customerOrderCodes: '', // 内部订单编号
  34 + },
  35 + };
  36 + },
  37 + onLoad(option) {
  38 + Object.keys(option).forEach(i => {
  39 + this.searchForm[i] = option[i];
  40 + });
  41 + },
  42 + methods: {
  43 + // 重置
  44 + resetChange() {
  45 + this.searchForm = {
  46 + orderCode: '', // 订单号
  47 + customerOrderCodes: '', // 内部订单编号
  48 + startCityCode: '',
  49 + startCityName: '',
  50 + endCityCode: '',
  51 + endCityName: '',
  52 + projectCode: '',
  53 + projectName: '',
  54 + feeType: '',
  55 + feeTypeName: '',
  56 + };
  57 + },
  58 + // 查询
  59 + inquiryChange() {
  60 + this.getOpenerEventChannel().emit('refreshData', this.searchForm);
  61 + setTimeout(() => uni.navigateBack(), 500);
  62 + },
  63 + },
  64 +};
  65 +</script>
  66 +
  67 +<style lang="scss">
  68 +.page-order-filter {
  69 + &__footer {
  70 + background: $color-white;
  71 + .footer {
  72 + display: flex;
  73 + justify-content: space-between;
  74 + .reset {
  75 + text-align: center;
  76 + width: 236upx;
  77 + height: 82upx;
  78 + line-height: 82upx;
  79 + margin-right: 20upx;
  80 + background: #dfebff;
  81 + border-radius: 14upx;
  82 + font-size: 30upx;
  83 + font-weight: 500;
  84 + color: $color-primary;
  85 + }
  86 + .inquiry {
  87 + text-align: center;
  88 + width: 450upx;
  89 + height: 82upx;
  90 + line-height: 82upx;
  91 + background: $color-primary;
  92 + border-radius: 14upx;
  93 + font-size: 30upx;
  94 + font-weight: 500;
  95 + color: #ffffff;
  96 + }
  97 + }
  98 + }
  99 +}
  100 +</style>
pages/settlement/index.vue 0 → 100644
@@ -0,0 +1,424 @@ @@ -0,0 +1,424 @@
  1 +<template>
  2 + <Page name="freight-order" flank>
  3 + <template #header>
  4 + <u-tabs :current="activeTab" :list="tabList" @click="onTabChange" :scrollable="false" :activeStyle="{ color: '#1E7B6B' }"> </u-tabs>
  5 + <view class="line"></view>
  6 + <view class="quick-tag">
  7 + <view class="quick-tag-group">
  8 + <view class="quick-tag-item" :class="searchForm.feeType ? 'active' : ''" @click="selectQuickTag({ key: 'feeType', value: searchForm.feeType })">
  9 + <text>{{ searchForm.feeTypeName || '款项类型' }}</text>
  10 + <view class="sx-img">
  11 + <image v-if="searchForm.feeType" class="sx-image" :src="formatImagePath('active-down')"></image>
  12 + <image v-else class="sx-image" :src="formatImagePath('down')"></image>
  13 + </view>
  14 + </view>
  15 + <view class="quick-tag-item" :class="searchForm.projectCode ? 'active' : ''" @click="selectQuickTag({ key: 'projectCode', value: searchForm.projectCode })">
  16 + <text>{{ searchForm.projectName || '所属项目' }}</text>
  17 + <view class="sx-img">
  18 + <image v-if="searchForm.projectCode" class="sx-image" :src="formatImagePath('active-down')"></image>
  19 + <image v-else class="sx-image" :src="formatImagePath('down')"></image>
  20 + </view>
  21 + </view>
  22 + <view class="quick-tag-item" :class="searchForm.startCityCode ? 'active' : ''" @click="selectQuickTag({ key: 'startCityCode', value: searchForm.startCityCode })">
  23 + <text>{{ searchForm.startCityName || '始发地' }}</text>
  24 + <view class="sx-img">
  25 + <image v-if="searchForm.startCityCode" class="sx-image" :src="formatImagePath('active-down')"></image>
  26 + <image v-else class="sx-image" :src="formatImagePath('down')"></image>
  27 + </view>
  28 + </view>
  29 + <view class="quick-tag-item" :class="searchForm.endCityCode ? 'active' : ''" @click="selectQuickTag({ key: 'endCityCode', value: searchForm.endCityCode })">
  30 + <text>{{ searchForm.endCityName || '目的地' }}</text>
  31 + <view class="sx-img">
  32 + <image v-if="searchForm.startCityCode" class="sx-image" :src="formatImagePath('active-down')"></image>
  33 + <image v-else class="sx-image" :src="formatImagePath('down')"></image>
  34 + </view>
  35 + </view>
  36 + </view>
  37 + <view class="quick-screen" @click="openFilter">
  38 + <image class="search-image" :src="formatImagePath('search')"></image>
  39 + </view>
  40 + </view>
  41 + </template>
  42 + <template #content>
  43 + <List ref="list" v-model="list" :api="orderAPI" @update:loading="e => (loading = e)">
  44 + <template v-for="(item, index) in list">
  45 + <card @apply="applySub" @audit="auditFun" @cancelApply="cancelApplySub" @tap="toDetail(item.orderCode)" :key="index" :item="item"></card>
  46 + </template>
  47 + <template #empty>
  48 + <Empty tips="暂无数据" />
  49 + </template>
  50 + </List>
  51 + </template>
  52 + <u-popup :show="popShow" @close="closePop" closeable>
  53 + <view class="popup">
  54 + <view class="title">确定审核</view>
  55 + <u-form label-width="90">
  56 + <u-form-item label="审核结果" required>
  57 + <u-radio-group v-model="auditForm.auditResultFlag">
  58 + <u-radio name="true"> 审核通过 </u-radio>
  59 + <u-radio name="false"> 审核不通过 </u-radio>
  60 + </u-radio-group>
  61 + </u-form-item>
  62 + <u-form-item label="驳回原因" :required="auditForm.auditResultFlag === 'false'">
  63 + <u--textarea v-model="auditForm.auditRejectMsg" placeholder="200字以内描述" :count="true" :maxlength="200" :cursorSpacing="60"></u--textarea>
  64 + </u-form-item>
  65 + </u-form>
  66 + <view class="but">
  67 + <u-button type="primary" @tap="auditSub">确定</u-button>
  68 + </view>
  69 + </view>
  70 + </u-popup>
  71 + <u-toast ref="uToast"></u-toast>
  72 + </Page>
  73 +</template>
  74 +<script>
  75 +import { urlParam } from '@/utils/param';
  76 +import card from './card.vue';
  77 +import UFormItem from '../../uni_modules/uview-ui/components/u-form-item/u-form-item.vue';
  78 +export default {
  79 + name: 'settlement',
  80 + components: { UFormItem, card },
  81 + data() {
  82 + return {
  83 + loading: false,
  84 + popShow: false,
  85 + auditForm: {
  86 + ids: [],
  87 + auditResultFlag: '',
  88 + auditRejectMsg: '',
  89 + },
  90 + searchForm: {
  91 + feeType: '', // 费用类型
  92 + feeTypeName: '', // 费用类型
  93 + projectCode: '',
  94 + projectName: '',
  95 + startCityCode: '',
  96 + startCityName: '',
  97 + applyStatus: '',
  98 + orderCode: '', // 订单号
  99 + customerOrderCodes: '', // 内部订单编号
  100 + },
  101 + activeTab: 0,
  102 + count: {},
  103 + list: [],
  104 + };
  105 + },
  106 + onPullDownRefresh() {
  107 + this.onSearch();
  108 + },
  109 + computed: {
  110 + tabList() {
  111 + let res = [
  112 + { name: '待申请', value: 'WAIT_APPLY', key: 'waitApplyCount' },
  113 + { name: '待审核', value: 'WAIT_AUDIT', key: 'waitAuditCount' },
  114 + { name: '已审核', value: 'AUDITED', key: 'auditedCount' },
  115 + ];
  116 + return Object.keys(this.count).length > 0
  117 + ? res.map(item => {
  118 + return { ...item, name: `${item.name}(${this.count[item.key] || 0})`, disabled: this.loading };
  119 + })
  120 + : res;
  121 + },
  122 + },
  123 + methods: {
  124 + toDetail(code) {
  125 + uni.navigateTo({ url: '/pages/order/detail?code=' + code });
  126 + },
  127 + onTabChange({ index }) {
  128 + if (this.loading) {
  129 + return;
  130 + }
  131 + this.activeTab = index;
  132 + this.list = [];
  133 + this.onSearch();
  134 + },
  135 + orderAPI(params) {
  136 + let format = {
  137 + ...this.searchForm,
  138 + applyStatus: this.tabList[this.activeTab].value,
  139 + };
  140 + this.getAggregateType(format);
  141 + return uni.$u.api.freightPayApply.page({
  142 + ...format,
  143 + ...params,
  144 + });
  145 + },
  146 + // 获取聚合数量
  147 + getAggregateType(params) {
  148 + uni.$u.api.freightPayApply.getCount({ ...params, applyStatus: '' }).then(res => {
  149 + this.count = res?.result || {};
  150 + });
  151 + },
  152 + selectQuickTag({ key, value }) {
  153 + this.searchForm = Object.assign(this.searchForm, { [key]: value });
  154 + if (key == 'feeType') {
  155 + uni.$once('select-dict', option => {
  156 + this.searchForm.feeType = option.valueCode;
  157 + this.searchForm.feeTypeName = option.valueName;
  158 + this.onSearch();
  159 + });
  160 + uni.navigateTo({
  161 + url: `/pages/global/search-dict${urlParam({
  162 + title: '款项类型',
  163 + dict: 'ONLINE_FREIGHT_ORDER_FEE_TYPE',
  164 + })}`,
  165 + });
  166 + } else if (key == 'startCityCode') {
  167 + uni.$once('select-city', option => {
  168 + this.searchForm.startCityCode = option.code;
  169 + this.searchForm.startCityName = option.shortName;
  170 + this.onSearch();
  171 + });
  172 + uni.navigateTo({ url: '/pages/global/search-city' });
  173 + } else if (key == 'endCityCode') {
  174 + uni.$once('select-city', option => {
  175 + this.searchForm.endCityCode = option.code;
  176 + this.searchForm.endCityName = option.shortName;
  177 + this.onSearch();
  178 + });
  179 + uni.navigateTo({ url: '/pages/global/search-city' });
  180 + } else if (key == 'projectCode') {
  181 + uni.$once('select-common', option => {
  182 + this.searchForm.projectCode = option.code;
  183 + this.searchForm.projectName = option.name;
  184 + this.onSearch();
  185 + });
  186 + uni.navigateTo({
  187 + url: `/pages/global/search-common${urlParam({
  188 + mode: 'select',
  189 + url: 'projectCode',
  190 + title: '项目',
  191 + label: 'name',
  192 + value: '',
  193 + })}`,
  194 + });
  195 + }
  196 + },
  197 + // 筛选
  198 + openFilter() {
  199 + uni.navigateTo({
  200 + url: `/pages/settlement/filter${urlParam(this.searchForm)}`,
  201 + events: {
  202 + refreshData: option => {
  203 + this.searchForm = { ...this.searchForm, ...option };
  204 + this.onSearch();
  205 + },
  206 + },
  207 + });
  208 + },
  209 + applySub(item) {
  210 + uni.$u.api.freightPayApply
  211 + .apply([item.id])
  212 + .then(res => {
  213 + if (res.success) {
  214 + uni.showToast({ title: '申请成功', icon: 'none' });
  215 + this.onSearch();
  216 + }
  217 + })
  218 + .catch(e => {
  219 + this.$refs.uToast.show({
  220 + type: 'default',
  221 + message: e,
  222 + });
  223 + });
  224 + },
  225 + cancelApplySub(item) {
  226 + uni.$u.api.freightPayApply
  227 + .cancelApply([item.id])
  228 + .then(res => {
  229 + if (res.success) {
  230 + uni.showToast({ title: '取消成功', icon: 'none' });
  231 + this.onSearch();
  232 + }
  233 + })
  234 + .catch(e => {
  235 + this.$refs.uToast.show({
  236 + type: 'default',
  237 + message: e,
  238 + });
  239 + });
  240 + },
  241 + auditFun(item) {
  242 + this.popShow = true;
  243 + this.auditForm = {
  244 + ids: [item.id],
  245 + auditResultFlag: '',
  246 + auditRejectMsg: '',
  247 + };
  248 + uni.hideTabBar();
  249 + },
  250 + closePop() {
  251 + setTimeout(() => uni.showTabBar(), 300);
  252 + this.popShow = false;
  253 + },
  254 + auditSub() {
  255 + if (!this.auditForm.auditResultFlag) {
  256 + uni.showToast({ title: '审核结果不能为空', icon: 'none' });
  257 + return;
  258 + }
  259 + if (this.auditForm.auditResultFlag === 'false' && !this.auditForm.auditRejectMsg) {
  260 + uni.showToast({ title: '驳回原因不能为空', icon: 'none' });
  261 + return;
  262 + }
  263 + uni.$u.api.freightPayApply
  264 + .audit(this.auditForm)
  265 + .then(res => {
  266 + if (res.success) {
  267 + uni.showToast({ title: '审核成功', icon: 'none' });
  268 + this.closePop();
  269 + this.onSearch();
  270 + }
  271 + })
  272 + .catch(e => {
  273 + this.$refs.uToast.show({
  274 + type: 'default',
  275 + message: e,
  276 + });
  277 + });
  278 + },
  279 + },
  280 +};
  281 +</script>
  282 +<style lang="scss">
  283 +.page-freight-order {
  284 + &__header {
  285 + padding: 0 !important;
  286 +
  287 + .line {
  288 + height: 1rpx;
  289 + background: #f6f6f6;
  290 + position: relative;
  291 + top: -5rpx;
  292 + }
  293 +
  294 + .quick-tag {
  295 + display: flex;
  296 + padding: 15upx 22upx;
  297 + box-sizing: border-box;
  298 + position: relative;
  299 +
  300 + .quick-cover {
  301 + width: 25upx;
  302 + height: 90upx;
  303 + position: absolute;
  304 + right: 122upx;
  305 + top: 0;
  306 +
  307 + .cover-image {
  308 + width: 100%;
  309 + height: 100%;
  310 + }
  311 + }
  312 +
  313 + .quick-screen {
  314 + width: 100upx;
  315 + display: flex;
  316 + align-items: center;
  317 + justify-content: center;
  318 +
  319 + .search-image {
  320 + width: 42upx;
  321 + height: 42upx;
  322 + }
  323 + }
  324 +
  325 + .quick-tag-group {
  326 + flex: 1;
  327 + display: flex;
  328 + align-items: center;
  329 + background-color: #fff;
  330 + padding-left: $padding-xs !important;
  331 + padding-right: $padding-xs !important;
  332 + overflow-y: auto;
  333 +
  334 + .quick-tag-item {
  335 + flex-shrink: 0;
  336 + min-width: 158upx;
  337 + height: 58upx;
  338 + background: #f6f6f6;
  339 + border-radius: 8upx;
  340 + font-size: 28upx;
  341 + font-weight: 400;
  342 + color: #2b2a27;
  343 + display: flex;
  344 + align-items: center;
  345 + justify-content: center;
  346 + padding: 0 10upx;
  347 + box-sizing: border-box;
  348 +
  349 + &:not(:last-child) {
  350 + margin-right: 18upx;
  351 + }
  352 +
  353 + &.active {
  354 + background: #ffffff;
  355 + border-radius: 8upx;
  356 + border: 2upx solid #2673fb;
  357 + font-size: 28upx;
  358 + font-family:
  359 + PingFangSC,
  360 + PingFang SC;
  361 + font-weight: 400;
  362 + color: #2673fb;
  363 + }
  364 +
  365 + .sx-img {
  366 + height: 12upx;
  367 + width: 14upx;
  368 + position: relative;
  369 + margin-left: 12upx;
  370 +
  371 + .sx-image {
  372 + width: 100%;
  373 + height: 100%;
  374 + position: absolute;
  375 + top: 0;
  376 + left: 0;
  377 + }
  378 + }
  379 + }
  380 +
  381 + .z-dropdown__text .text {
  382 + word-break: keep-all;
  383 + }
  384 + }
  385 + }
  386 + }
  387 + .add-order {
  388 + right: 34upx;
  389 + bottom: 34upx;
  390 + height: 106upx;
  391 + width: 106upx;
  392 + position: fixed;
  393 + .sx-image {
  394 + width: 100%;
  395 + height: 100%;
  396 + position: absolute;
  397 + top: 0;
  398 + left: 0;
  399 + }
  400 + }
  401 + .popup {
  402 + padding-left: $padding-md;
  403 + padding-right: $padding-md;
  404 + border-top-left-radius: $radius-md;
  405 + border-top-right-radius: $radius-md;
  406 + .title {
  407 + padding-top: $padding-xs;
  408 + padding-bottom: $padding-xs;
  409 + display: flex;
  410 + align-content: center;
  411 + justify-content: center;
  412 + font-weight: 400;
  413 + font-size: 32rpx;
  414 + color: #2b2a27;
  415 + line-height: 45px;
  416 + text-align: left;
  417 + font-style: normal;
  418 + }
  419 + .but {
  420 + margin-top: $padding-md;
  421 + }
  422 + }
  423 +}
  424 +</style>
static/addOrder.png 0 → 100644

8.14 KB

static/copy-icon.png 0 → 100644

201 Bytes

static/logo.png 0 → 100644

20.3 KB

static/qr.png 0 → 100644

188 Bytes

static/tabbar/inquiry-active-dingtalk.png

1.65 KB

static/tabbar/inquiry-active.png

1.58 KB

static/tabbar/inquiry.png

1.78 KB

static/tabbar/me-active.png 0 → 100644

2.19 KB

static/tabbar/me.png 0 → 100644

2.12 KB

static/tabbar/my-active-dingtalk.png

1.49 KB

static/tabbar/my-active.png

1.63 KB

static/tabbar/my.png

2.04 KB

static/tabbar/order-active.png 0 → 100644

3.81 KB

static/tabbar/order.png 0 → 100644

3.68 KB

static/tabbar/settlement-active.png 0 → 100644

2.66 KB

static/tabbar/settlement.png 0 → 100644

2.61 KB

store/index.js
@@ -33,7 +33,7 @@ const store = new Vuex.Store({ @@ -33,7 +33,7 @@ const store = new Vuex.Store({
33 districtValue: state => code => { 33 districtValue: state => code => {
34 const list = state.district || cache.get('DISTRICT') || []; 34 const list = state.district || cache.get('DISTRICT') || [];
35 let flattenList = []; 35 let flattenList = [];
36 - function flatten(array) { 36 + function flatten(array) {
37 array.forEach(item => { 37 array.forEach(item => {
38 flattenList.push({ code: item.code, name: item.name }); 38 flattenList.push({ code: item.code, name: item.name });
39 if (item.children) { 39 if (item.children) {
@@ -149,9 +149,9 @@ const store = new Vuex.Store({ @@ -149,9 +149,9 @@ const store = new Vuex.Store({
149 state.orderTab = orderTab; 149 state.orderTab = orderTab;
150 }, 150 },
151 }, 151 },
152 - modules:{  
153 - invoice  
154 - }  
155 -}) 152 + modules: {
  153 + invoice,
  154 + },
  155 +});
156 156
157 export default store; 157 export default store;
1 /* uni.scss */ 1 /* uni.scss */
2 @import '@/uni_modules/uview-ui/theme.scss'; 2 @import '@/uni_modules/uview-ui/theme.scss';
3 3
4 -$color-primary: #2673FB; 4 +$color-primary: #1E7B6B;
5 $color-secondary: #F39800; 5 $color-secondary: #F39800;
6 6
7 /* #ifdef MP-DINGTALK */ 7 /* #ifdef MP-DINGTALK */
8 -$color-primary: #3296FA; 8 +$color-primary: #1E7B6B;
9 /* #endif */ 9 /* #endif */
10 10
11 $color-zy-green: #074137; 11 $color-zy-green: #074137;
@@ -65,4 +65,4 @@ $font-md: 28upx; @@ -65,4 +65,4 @@ $font-md: 28upx;
65 $font-sm: 24upx; 65 $font-sm: 24upx;
66 $font-xs: 20upx; 66 $font-xs: 20upx;
67 67
68 -$shadow-normal: 0 18upx 24upx -18upx rgba($color-text, 0.02);  
69 \ No newline at end of file 68 \ No newline at end of file
  69 +$shadow-normal: 0 18upx 24upx -18upx rgba($color-text, 0.02);
uni_modules/uview-ui/libs/config/props/input.js
@@ -8,41 +8,41 @@ @@ -8,41 +8,41 @@
8 * @FilePath : /u-view2.0/uview-ui/libs/config/props/input.js 8 * @FilePath : /u-view2.0/uview-ui/libs/config/props/input.js
9 */ 9 */
10 export default { 10 export default {
11 - // index 组件  
12 - input: {  
13 - value: '',  
14 - type: 'text',  
15 - fixed: false,  
16 - disabled: false,  
17 - disabledColor: '#f5f7fa',  
18 - clearable: false,  
19 - password: false,  
20 - maxlength: -1,  
21 - placeholder: null,  
22 - placeholderClass: 'input-placeholder',  
23 - placeholderStyle: 'color: #c0c4cc',  
24 - showWordLimit: false,  
25 - confirmType: 'done',  
26 - confirmHold: false,  
27 - holdKeyboard: false,  
28 - focus: false,  
29 - autoBlur: false,  
30 - disableDefaultPadding: false,  
31 - cursor: -1,  
32 - cursorSpacing: 30,  
33 - selectionStart: -1,  
34 - selectionEnd: -1,  
35 - adjustPosition: true,  
36 - inputAlign: 'left',  
37 - fontSize: '15px',  
38 - color: '#303133',  
39 - prefixIcon: '',  
40 - prefixIconStyle: '',  
41 - suffixIcon: '',  
42 - suffixIconStyle: '',  
43 - border: 'surround',  
44 - readonly: false,  
45 - shape: 'square',  
46 - formatter: null  
47 - }  
48 -} 11 + // index 组件
  12 + input: {
  13 + value: '',
  14 + type: 'text',
  15 + fixed: false,
  16 + disabled: false,
  17 + disabledColor: '#f5f7fa',
  18 + clearable: false,
  19 + password: false,
  20 + maxlength: -1,
  21 + placeholder: null,
  22 + placeholderClass: 'input-placeholder',
  23 + placeholderStyle: 'color: #c0c4cc',
  24 + showWordLimit: false,
  25 + confirmType: 'done',
  26 + confirmHold: false,
  27 + holdKeyboard: false,
  28 + focus: false,
  29 + autoBlur: false,
  30 + disableDefaultPadding: false,
  31 + cursor: -1,
  32 + cursorSpacing: 30,
  33 + selectionStart: -1,
  34 + selectionEnd: -1,
  35 + adjustPosition: true,
  36 + inputAlign: 'left',
  37 + fontSize: '15px',
  38 + color: '#2B2A27',
  39 + prefixIcon: '',
  40 + prefixIconStyle: '',
  41 + suffixIcon: '',
  42 + suffixIconStyle: '',
  43 + border: 'surround',
  44 + readonly: false,
  45 + shape: 'square',
  46 + formatter: null,
  47 + },
  48 +};
uni_modules/uview-ui/theme.scss
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 // uni.scss中引入的样式会同时混入到全局样式文件和单独每一个页面的样式中,造成微信程序包太大, 2 // uni.scss中引入的样式会同时混入到全局样式文件和单独每一个页面的样式中,造成微信程序包太大,
3 // 故uni.scss只建议放scss变量名相关样式,其他的样式可以通过main.js或者App.vue引入 3 // 故uni.scss只建议放scss变量名相关样式,其他的样式可以通过main.js或者App.vue引入
4 4
5 -$u-main-color: #303133; 5 +$u-main-color: #999999;
6 $u-content-color: #606266; 6 $u-content-color: #606266;
7 $u-tips-color: #909193; 7 $u-tips-color: #909193;
8 $u-light-color: #c0c4cc; 8 $u-light-color: #c0c4cc;
uni_modules/zb-tooltip/changelog.md 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +## 1.0.11(2023-01-29)
  2 +优化点击,加入点击自己再次点击也会关闭
  3 +## 1.0.10(2023-01-17)
  4 +优化
  5 +## 1.0.9(2023-01-17)
  6 +增加注释
  7 +## 1.0.8(2022-08-18)
  8 +优化细节
  9 +## 1.0.67(2022-05-09)
  10 +修复安卓报错
  11 +## 1.0.6(2022-05-07)
  12 +修改默认展示
  13 +## 1.0.5(2022-04-28)
  14 +进行优化
  15 +## 1.0.4(2022-04-27)
  16 +进行优化
  17 +## 1.0.3(2022-04-25)
  18 +去掉多余得注释
  19 +## 1.0.2(2022-04-25)
  20 +增加自定义主题颜色
  21 +## 1.0.1(2022-04-25)
  22 +进行优化显示
  23 +## 1.0.0(2022-04-24)
  24 +初始化
uni_modules/zb-tooltip/components/zb-tooltip/zb-tooltip.vue 0 → 100644
@@ -0,0 +1,301 @@ @@ -0,0 +1,301 @@
  1 +<template>
  2 + <view
  3 + class="zb-tooltip"
  4 + :style="{
  5 + '--theme-bg-color': color,
  6 + }"
  7 + >
  8 + <view class="zb_tooltip_content" @click.stop="handleClick">
  9 + <slot></slot>
  10 + <view
  11 + class="zb_tooltip__popper"
  12 + @click.stop="() => {}"
  13 + :style="[
  14 + style,
  15 + {
  16 + visibility: isShow ? 'visible' : 'hidden',
  17 + color: color === 'white' ? '' : '#fff',
  18 + boxShadow: color === 'white' ? '0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d' : '',
  19 + },
  20 + ]"
  21 + >
  22 + <slot name="content">{{ content }}</slot>
  23 + <view
  24 + class="zb_popper__icon"
  25 + :style="[arrowStyle]"
  26 + :class="[
  27 + {
  28 + zb_popper__up: placement.indexOf('bottom') === 0,
  29 + zb_popper__arrow: placement.indexOf('top') === 0,
  30 + zb_popper__right: placement.indexOf('right') === 0,
  31 + zb_popper__left: placement.indexOf('left') === 0,
  32 + },
  33 + ]"
  34 + >
  35 + </view>
  36 + </view>
  37 + </view>
  38 + </view>
  39 +</template>
  40 +
  41 +<script>
  42 +export default {
  43 + props: {
  44 + visible: Boolean,
  45 + color: {
  46 + type: String,
  47 + default: '#FFFFFF',
  48 + },
  49 + placement: {
  50 + type: String,
  51 + default: 'top',
  52 + },
  53 + content: {
  54 + type: String,
  55 + default: '',
  56 + },
  57 + show: {
  58 + type: Boolean,
  59 + default: false,
  60 + },
  61 + },
  62 +
  63 + data() {
  64 + return {
  65 + isShow: this.visible,
  66 + title: 'Hello',
  67 + arrowLeft: 0,
  68 + query: null,
  69 + style: {},
  70 + arrowStyle: {},
  71 + };
  72 + },
  73 + onLoad() {},
  74 + watch: {
  75 + isShow: {
  76 + handler(val) {
  77 + this.$emit('update:visible', val);
  78 + },
  79 + immediate: true,
  80 + },
  81 + visible: {
  82 + handler(val) {
  83 + if (val) {
  84 + this.$nextTick(() => {
  85 + this.getPosition();
  86 + });
  87 + }
  88 + this.isShow = val;
  89 + },
  90 + immediate: true,
  91 + },
  92 + },
  93 + mounted() {
  94 + // #ifdef H5
  95 + window.addEventListener('click', () => {
  96 + this.isShow = false;
  97 + });
  98 + // #endif
  99 + this.getPosition();
  100 + },
  101 + methods: {
  102 + close() {
  103 + this.isShow = false;
  104 + },
  105 + fixedWrap() {
  106 + this.isShow = false;
  107 + },
  108 + async handleClick() {
  109 + if (this.isShow) {
  110 + return (this.isShow = false);
  111 + }
  112 + await this.getPosition();
  113 + this.isShow = true;
  114 + },
  115 + getPosition() {
  116 + return new Promise(resolve => {
  117 + uni
  118 + .createSelectorQuery()
  119 + .in(this)
  120 + .selectAll('.zb_tooltip_content,.zb_tooltip__popper')
  121 + .boundingClientRect(async data => {
  122 + let { left, bottom, right, top, width, height } = data[0];
  123 + let obj1 = data[1];
  124 + let objStyle = {};
  125 + let objStyle1 = {};
  126 + switch (this.placement) {
  127 + case 'top':
  128 + if (obj1.width > width) {
  129 + objStyle.left = `-${(obj1.width - width) / 2}px`;
  130 + } else {
  131 + objStyle.left = `${Math.abs(obj1.width - width) / 2}px`;
  132 + }
  133 +
  134 + objStyle.bottom = `${height + 8}px`;
  135 + objStyle1.left = obj1.width / 2 - 6 + 'px';
  136 + break;
  137 + case 'top-start':
  138 + objStyle.left = `0px`;
  139 + objStyle.bottom = `${height + 8}px`;
  140 + break;
  141 + case 'top-end':
  142 + objStyle.right = `0px`;
  143 + objStyle.bottom = `${height + 8}px`;
  144 + objStyle1.right = `8px`;
  145 + break;
  146 + case 'bottom':
  147 + if (obj1.width > width) {
  148 + objStyle.left = `-${(obj1.width - width) / 2}px`;
  149 + } else {
  150 + objStyle.left = `${Math.abs(obj1.width - width) / 2}px`;
  151 + }
  152 + objStyle.top = `${height + 8}px`;
  153 + objStyle1.left = obj1.width / 2 - 6 + 'px';
  154 + break;
  155 + case 'bottom-start':
  156 + objStyle.left = `0px`;
  157 + objStyle.top = `${height + 8}px`;
  158 + objStyle1.left = `8px`;
  159 + break;
  160 +
  161 + case 'bottom-end':
  162 + objStyle.right = `0px`;
  163 + objStyle.top = `${height + 8}px`;
  164 + objStyle1.right = `8px`;
  165 + break;
  166 +
  167 + case 'right':
  168 + objStyle.left = `${width + 8}px`;
  169 + if (obj1.height > height) {
  170 + objStyle.top = `-${(obj1.height - height) / 2}px`;
  171 + } else {
  172 + objStyle.top = `${Math.abs((obj1.height - height) / 2)}px`;
  173 + }
  174 +
  175 + objStyle1.top = `${obj1.height / 2 - 6}px`;
  176 + break;
  177 + case 'right-start':
  178 + objStyle.left = `${width + 8}px`;
  179 + objStyle.top = `0px`;
  180 + objStyle1.top = `8px`;
  181 + break;
  182 +
  183 + case 'right-end':
  184 + objStyle.left = `${width + 8}px`;
  185 + objStyle.bottom = `0px`;
  186 + objStyle1.bottom = `8px`;
  187 + break;
  188 +
  189 + case 'left':
  190 + objStyle.right = `${width + 8}px`;
  191 +
  192 + if (obj1.height > height) {
  193 + objStyle.top = `-${(obj1.height - height) / 2}px`;
  194 + } else {
  195 + objStyle.top = `${Math.abs((obj1.height - height) / 2)}px`;
  196 + }
  197 +
  198 + objStyle1.top = `${obj1.height / 2 - 6}px`;
  199 + break;
  200 +
  201 + case 'left-start':
  202 + objStyle.right = `${width + 8}px`;
  203 + objStyle.top = `0px`;
  204 + objStyle1.top = `8px`;
  205 + break;
  206 +
  207 + case 'left-end':
  208 + objStyle.right = `${width + 8}px`;
  209 + objStyle.bottom = `0px`;
  210 + objStyle1.bottom = `8px`;
  211 + break;
  212 + }
  213 + this.style = objStyle;
  214 + // 三角形箭头
  215 + this.arrowStyle = objStyle1;
  216 + resolve();
  217 + })
  218 + .exec();
  219 + });
  220 + },
  221 + },
  222 +};
  223 +</script>
  224 +
  225 +<style lang="scss" scoped>
  226 +$theme-bg-color: var(--theme-bg-color);
  227 +
  228 +.zb-tooltip {
  229 + position: relative;
  230 +}
  231 +.zb_tooltip_content {
  232 + height: 100%;
  233 + /* float: left; */
  234 + position: relative;
  235 + display: inline-block;
  236 +
  237 + // display: flex;
  238 + // flex-direction: row;
  239 + // align-items: center;
  240 + /* overflow: hidden; */
  241 +}
  242 +.zb_tooltip__popper {
  243 + /* transform-origin: center top; */
  244 + background: $theme-bg-color;
  245 +
  246 + visibility: hidden;
  247 + // color:'#fff';
  248 + position: absolute;
  249 + border-radius: 4px;
  250 + font-size: 12px;
  251 + min-width: 10px;
  252 + word-wrap: break-word;
  253 + display: inline-block;
  254 + white-space: nowrap;
  255 + z-index: 9;
  256 +}
  257 +.zb_popper__icon {
  258 + width: 0;
  259 + height: 0;
  260 + z-index: 9;
  261 + position: absolute;
  262 +}
  263 +.zb_popper__arrow {
  264 + bottom: -5px;
  265 + /* transform-origin: center top; */
  266 + border-left: 6px solid transparent;
  267 + border-right: 6px solid transparent;
  268 + border-top: 6px solid $theme-bg-color;
  269 +}
  270 +.zb_popper__right {
  271 + border-top: 6px solid transparent;
  272 + border-bottom: 6px solid transparent;
  273 + border-right: 6px solid $theme-bg-color;
  274 + left: -5px;
  275 +}
  276 +
  277 +.zb_popper__left {
  278 + border-top: 6px solid transparent;
  279 + border-bottom: 6px solid transparent;
  280 + border-left: 6px solid $theme-bg-color;
  281 + right: -5px;
  282 +}
  283 +
  284 +.zb_popper__up {
  285 + border-left: 6px solid transparent;
  286 + border-right: 6px solid transparent;
  287 + border-bottom: 6px solid $theme-bg-color;
  288 + top: -5px;
  289 +}
  290 +.fixed {
  291 + position: absolute;
  292 + width: 100vw;
  293 + height: 100vh;
  294 + position: fixed;
  295 + left: 0;
  296 + top: 0;
  297 + pointer-events: auto;
  298 + background: red;
  299 + z-index: -1;
  300 +}
  301 +</style>
uni_modules/zb-tooltip/package.json 0 → 100644
@@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
  1 +{
  2 + "id": "zb-tooltip",
  3 + "displayName": "zb-tooltip (文字提示气泡框)",
  4 + "version": "1.0.11",
  5 + "description": "简单的文字提示气泡框,可以自定义皮肤颜色",
  6 + "keywords": [
  7 + "tooltip",
  8 + "tip",
  9 + "文字提示",
  10 + "气泡框",
  11 + "自定义皮肤颜色、Popover"
  12 +],
  13 + "repository": "",
  14 +"engines": {
  15 + },
  16 + "dcloudext": {
  17 + "category": [
  18 + "前端组件",
  19 + "通用组件"
  20 + ],
  21 + "sale": {
  22 + "regular": {
  23 + "price": "0.00"
  24 + },
  25 + "sourcecode": {
  26 + "price": "0.00"
  27 + }
  28 + },
  29 + "contact": {
  30 + "qq": ""
  31 + },
  32 + "declaration": {
  33 + "ads": "无",
  34 + "data": "无",
  35 + "permissions": "无"
  36 + },
  37 + "npmurl": ""
  38 + },
  39 + "uni_modules": {
  40 + "dependencies": [],
  41 + "encrypt": [],
  42 + "platforms": {
  43 + "cloud": {
  44 + "tcb": "y",
  45 + "aliyun": "y"
  46 + },
  47 + "client": {
  48 + "Vue": {
  49 + "vue2": "y",
  50 + "vue3": "y"
  51 + },
  52 + "App": {
  53 + "app-vue": "y",
  54 + "app-nvue": "u"
  55 + },
  56 + "H5-mobile": {
  57 + "Safari": "y",
  58 + "Android Browser": "y",
  59 + "微信浏览器(Android)": "y",
  60 + "QQ浏览器(Android)": "y"
  61 + },
  62 + "H5-pc": {
  63 + "Chrome": "y",
  64 + "IE": "y",
  65 + "Edge": "y",
  66 + "Firefox": "y",
  67 + "Safari": "y"
  68 + },
  69 + "小程序": {
  70 + "微信": "y",
  71 + "阿里": "y",
  72 + "百度": "y",
  73 + "字节跳动": "y",
  74 + "QQ": "y"
  75 + },
  76 + "快应用": {
  77 + "华为": "y",
  78 + "联盟": "y"
  79 + }
  80 + }
  81 + }
  82 + }
  83 +}
0 \ No newline at end of file 84 \ No newline at end of file
uni_modules/zb-tooltip/readme.md 0 → 100644
@@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
  1 +## 介绍
  2 +基于uni-app开发的一个普通的提示组件,功能点击提示
  3 +
  4 +
  5 +## 友情链接
  6 +#### vue-admin-perfect —— [企业级、通用型中后台前端解决方案 预览地址](http://182.61.5.190:8889/)
  7 +#### vue-admin-perfect —— [企业级、通用型中后台前端解决方案(基于vue3.0+TS+Element-Plus 最新版,同时支持电脑,手机,平板)](https://github.com/zouzhibin/vue-admin-perfect)
  8 +
  9 +
  10 +## Tooltip 属性
  11 +| 参数 | 说明 | 类型 | 可选值 | 默认值 |
  12 +| ------ | ------ | ------ | ------ | ------ |
  13 +| visible | 是否显示 tooltip,支持 .sync 修饰符 | Boolean |visible.sync | false |
  14 +| content | 显示的内容,也可以通过 slot#content | String |-- | ' ' |
  15 +| color | 自定义主题颜色| String |'#303133' | '#303133' |
  16 +| placement | Tooltip 的出现位置 | String |top/top-start/top-end/bottom/bottom-start/bottom-end/left/left-start/left-end/right/right-start/right-end | top |
  17 +
  18 +
  19 +## Slot 插槽
  20 +| 参数 | 说明 |
  21 +| ------ | ------ |
  22 +| content | 显示提示框得内容 |
  23 +
  24 +
  25 +```
  26 +因为uniapp 中小程序中没有window对象,需手动调用 关闭
  27 + 第一种办法关闭:this.$refs.tooltip.close()
  28 + 第二种办法关闭:visible.sync = false
  29 +
  30 +```
@@ -144,6 +144,11 @@ object-assign@^4.1.0: @@ -144,6 +144,11 @@ object-assign@^4.1.0:
144 resolved "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 144 resolved "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
145 integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== 145 integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
146 146
  147 +prettier@3.3.2:
  148 + version "3.3.2"
  149 + resolved "https://registry.npmmirror.com/prettier/-/prettier-3.3.2.tgz#03ff86dc7c835f2d2559ee76876a3914cec4a90a"
  150 + integrity sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==
  151 +
147 promise-polyfill@^7.1.0: 152 promise-polyfill@^7.1.0:
148 version "7.1.2" 153 version "7.1.2"
149 resolved "https://registry.npmmirror.com/promise-polyfill/-/promise-polyfill-7.1.2.tgz#ab05301d8c28536301622d69227632269a70ca3b" 154 resolved "https://registry.npmmirror.com/promise-polyfill/-/promise-polyfill-7.1.2.tgz#ab05301d8c28536301622d69227632269a70ca3b"