Commit d9a12bd944517479c4af19bba75658589cd9b342

Authored by 史婷婷
2 parents ee9ca938 0e6958b7

Merge remote-tracking branch 'origin/cjerp-1.0' into publish_cjerp

Showing 80 changed files with 4857 additions and 2203 deletions
... ... @@ -5,13 +5,17 @@ export const statusStyle = [
5 5 { color: '#2BA471', bgColor:'#E3F9E9',text: '审核通过' },
6 6 { color: '#D54941', bgColor:'#FFF0ED',text: '已驳回' },
7 7 { color: '#3D48A3', bgColor:'#F2F3FF',text: '审核中' },
  8 + { color: '#000', bgColor:'#F2F3FF',text: '已取消' },
8 9 ];
9 10
10 11 export const statusMap = {
11 12 '生产中': '#2BA471',
  13 + '审核通过': '#2BA471',
12 14 '审核中': '#3D48A3',
13 15 '已签收': '#E7E7E7',
  16 + '已取消': '#000',
14 17 '已发货': '#D54941',
  18 + '已驳回': '#D54941',
15 19 }
16 20
17 21 const baseUrl = '/contract';
... ... @@ -23,6 +27,15 @@ export function queryApi(params) {
23 27 params
24 28 })
25 29 }
  30 +//取消锁价无规格申请单申请
  31 +export function cancelApi(id) {
  32 + return request({
  33 + url: `${baseUrl}/specLockDelayApplication/cancel`,
  34 + method: 'get',
  35 + params: { id }
  36 + })
  37 +}
  38 +
26 39 // 查询锁价无规格申请单列表
27 40 export function querySpecLockApi(params) {
28 41 return request({
... ...
... ... @@ -126,4 +126,16 @@ export function getDeptUser() {
126 126 url: '/customerCredit/getDeptUser',
127 127 method: 'get',
128 128 })
  129 +}
  130 +
  131 +// 获取区域
  132 +// type: ALL 代表获取全部区域的值
  133 +export function getArea(type) {
  134 + return request({
  135 + url: '/system/dept/queryArea',
  136 + method: 'get',
  137 + params: {
  138 + type,
  139 + },
  140 + })
129 141 }
\ No newline at end of file
... ...
... ... @@ -47,6 +47,16 @@ export function createApi(params) {
47 47 })
48 48 }
49 49
  50 +// 新增拜访记录
  51 +export function createVisitRecordApi(params) {
  52 + return request({
  53 + url: `/customer/visitRecord`,
  54 + method: 'post',
  55 + data: params,
  56 + contentType: ContentTypeEnum.FORM_URLENCODED
  57 + })
  58 +}
  59 +
50 60
51 61 // 修改保存
52 62 export function updateApi(params) {
... ...
  1 +import request from '@/utils/request'
  2 +
  3 +const baseUrl = '/system/message/site';
  4 +
  5 +// 查询列表
  6 +export function queryApi(params) {
  7 + return request({
  8 + url: `${baseUrl}/query/my`,
  9 + method: 'get',
  10 + params
  11 + })
  12 +}
  13 +
  14 +// 查询内容
  15 +export function getContentApi(id) {
  16 + return request({
  17 + url: `${baseUrl}/content`,
  18 + method: 'get',
  19 + params: { id }
  20 + })
  21 +}
... ...
... ... @@ -65,3 +65,13 @@ export function listCanRevokeOrChangeOrderInfo(params) {
65 65 })
66 66 }
67 67
  68 +// 申请发货-检查数据是否规范
  69 +export function checkApi(params) {
  70 + return request({
  71 + url: `${baseUrl}/check`,
  72 + method: 'get',
  73 + params: {
  74 + ...params,
  75 + },
  76 + })
  77 +}
... ...
... ... @@ -53,50 +53,50 @@
53 53 <uni-easyinput v-model="item.quality" :inputBorder="false" placeholder="请输入品质" />
54 54 </template>
55 55 </uni-list-item>
56   - <uni-list-item title="厚度">
  56 + <uni-list-item title="厚度mm">
57 57 <template v-slot:footer>
58 58 <uni-easyinput v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" />
59 59 </template>
60 60 </uni-list-item>
61   - <uni-list-item title="厚度公差(单项+)">
  61 + <uni-list-item title="厚度公差(单项+)mm">
62 62 <template v-slot:footer>
63 63 <uni-easyinput v-model="item.thicknessTolPos" :inputBorder="false"
64 64 placeholder="请输入厚度公差(单项+)" />
65 65 </template>
66 66 </uni-list-item>
67   - <uni-list-item title="厚度公差(单项-)">
  67 + <uni-list-item title="厚度公差(单项-)mm">
68 68 <template v-slot:footer>
69 69 <uni-easyinput v-model="item.thicknessTolNeg" :inputBorder="false"
70 70 placeholder="请输入厚度公差(单项-)" />
71 71 </template>
72 72 </uni-list-item>
73   - <uni-list-item title="宽度">
  73 + <uni-list-item title="宽度mm">
74 74 <template v-slot:footer>
75 75 <uni-easyinput v-model="item.width" :inputBorder="false" placeholder="请输入宽度" />
76 76 </template>
77 77 </uni-list-item>
78   - <uni-list-item title="宽度公差(单项+)">
  78 + <uni-list-item title="宽度公差(单项+)mm">
79 79 <template v-slot:footer>
80 80 <uni-easyinput v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差(单项+)" />
81 81 </template>
82 82 </uni-list-item>
83   - <uni-list-item title="宽度公差(单项-)">
  83 + <uni-list-item title="宽度公差(单项-)mm">
84 84 <template v-slot:footer>
85 85 <uni-easyinput v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差(单项-)" />
86 86 </template>
87 87 </uni-list-item>
88   - <uni-list-item title="长度">
  88 + <uni-list-item title="长度mm">
89 89 <template v-slot:footer>
90 90 <uni-easyinput v-model="item.length" :inputBorder="false" placeholder="请输入长度" />
91 91 </template>
92 92 </uni-list-item>
93   - <uni-list-item title="长度公差(单项+)">
  93 + <uni-list-item title="长度公差(单项+)mm">
94 94 <template v-slot:footer>
95 95 <uni-easyinput v-model="item.lengthTolPos" :inputBorder="false"
96 96 placeholder="请输入长度公差(单项+)" />
97 97 </template>
98 98 </uni-list-item>
99   - <uni-list-item title="长度公差(单项-)">
  99 + <uni-list-item title="长度公差(单项-)mm">
100 100 <template v-slot:footer>
101 101 <uni-easyinput v-model="item.lengthTolNeg" :inputBorder="false"
102 102 placeholder="请输入长度公差(单项-)" />
... ... @@ -129,7 +129,7 @@
129 129 </uni-list-item>
130 130 <uni-list-item title="发货日期">
131 131 <template v-slot:footer>
132   - <uni-datetime-picker type="date" v-model="item.orderDate" @change="onDateChange(idx, $event)" />
  132 + <uni-datetime-picker type="date" v-model="item.deliveryDate" @change="onDateChange(idx, $event)" />
133 133 </template>
134 134 </uni-list-item>
135 135 </uni-list>
... ... @@ -151,7 +151,30 @@
151 151 <view class="row"><text class="label">行业</text><text class="value">{{ item.industry }}</text></view>
152 152 <view class="row"><text class="label">牌号</text><text class="value">{{ item.brand }}</text></view>
153 153 <view class="row"><text class="label">品质</text><text class="value">{{ item.quality }}</text></view>
154   - <view class="row"><text class="label">规格</text><text class="value">{{ item.specDisplay }}</text></view>
  154 + <!-- 厚(公差) * 宽(公差) * 长(公差) -->
  155 + <view class="row row-spec"><text class="label">规格(mm)</text>
  156 + <view class="value value-spec">
  157 + <view v-if="item.thickness" class="value-spec_val">{{ item.thickness }}</view>
  158 + <view v-if="item.thickness" class="value-spec_box">
  159 + <view v-if="item.thicknessTolPos" class="value-spec_box_1">+{{ item.thicknessTolPos }}
  160 + </view>
  161 + <view v-if="item.thicknessTolNeg" class="value-spec_box_2">-{{ item.thicknessTolNeg }}
  162 + </view>
  163 + </view>
  164 + <view v-if="item.width" class="value-spec_val p12">*</view>
  165 + <view v-if="item.width" class="value-spec_val">{{ item.width }}</view>
  166 + <view v-if="item.width" class="value-spec_box">
  167 + <view v-if="item.widthTolPos" class="value-spec_box_1">+{{ item.widthTolPos }}</view>
  168 + <view v-if="item.widthTolNeg" class="value-spec_box_2">-{{ item.widthTolNeg }}</view>
  169 + </view>
  170 + <view v-if="item.length" class="value-spec_val p12">*</view>
  171 + <view v-if="item.length" class="value-spec_val">{{ item.length }}</view>
  172 + <view v-if="item.length" class="value-spec_box">
  173 + <view v-if="item.lengthTolPos" class="value-spec_box_1">+{{ item.lengthTolPos }}</view>
  174 + <view v-if="item.lengthTolNeg" class="value-spec_box_2">-{{ item.lengthTolNeg }}</view>
  175 + </view>
  176 + </view>
  177 + </view>
155 178 <view class="row"><text class="label">状态</text><text class="value">{{ item.status }}</text></view>
156 179 <view class="row"><text class="label">数量</text><text class="value">{{ item.quantity }}</text></view>
157 180 <view class="row"><text class="label">单价</text><text class="value">{{ formatCurrency(item.unitPrice)
... ... @@ -162,7 +185,7 @@
162 185 }}</text></view>
163 186 <view class="row"><text class="label">总金额</text><text class="value">{{ formatCurrency(item.totalAmount)
164 187 }}</text></view>
165   - <view class="row"><text class="label">发货日期</text><text class="value">{{ item.orderDate }}</text></view>
  188 + <view class="row"><text class="label">发货日期</text><text class="value">{{ item.deliveryDate }}</text></view>
166 189 </view>
167 190 </view>
168 191 <SingleSelectSheet :visible.sync="sheet.visible" :title="sheet.title" :options="sheet.options" v-model="sheet.value" @confirm="onProductConfirm" />
... ... @@ -176,7 +199,7 @@ export default {
176 199 mode: { type: String, default: 'add' },
177 200 list: { type: Array, default: () => [] },
178 201 max: { type: Number, default: 8 },
179   - orderDateBase: { type: String, default: '' },
  202 + deliveryDateBase: { type: String, default: '' },
180 203 options: { type: Array, default: () => [] }
181 204 },
182 205 components: { SingleSelectSheet },
... ... @@ -218,7 +241,7 @@ export default {
218 241 },
219 242 methods: {
220 243 defaultItem() {
221   - return { productId: '', productName: '', industry: '', brand: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', status: '', quantity: '', unitPrice: '', amountExcludingTax: 0, totalAmount: 0, orderDate: '' }
  244 + return { productId: '', productName: '', industry: '', brand: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', status: '', quantity: '', unitPrice: '', amountExcludingTax: 0, totalAmount: 0, deliveryDate: '' }
222 245 },
223 246 onImmediateChange(idx) {
224 247 this.$nextTick(() => this.recalculate(idx))
... ... @@ -319,15 +342,15 @@ export default {
319 342 onDateChange(idx, e) {
320 343 const it = this.items[idx]
321 344 if (!it) return
322   - const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.orderDate
  345 + const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.deliveryDate
323 346 const dateStr = String(val).slice(0, 10)
324   - const base = this.orderDateBase ? new Date(this.orderDateBase) : null
  347 + const base = this.deliveryDateBase ? new Date(this.deliveryDateBase) : null
325 348 const d = new Date(dateStr)
326 349 if (base && !isNaN(d.getTime()) && d.getTime() < base.getTime()) {
327 350 uni.showToast({ title: '发货日期不得早于订货日期', icon: 'none' })
328   - it.orderDate = this.orderDateBase
  351 + it.deliveryDate = this.deliveryDateBase
329 352 } else {
330   - it.orderDate = dateStr
  353 + it.deliveryDate = dateStr
331 354 }
332 355 this.$set(this.items, idx, it)
333 356 },
... ... @@ -500,8 +523,46 @@ export default {
500 523
501 524 .value {
502 525 flex: 1;
503   - text-align: right;
  526 + // text-align: right;
504 527 color: rgba(0, 0, 0, 0.9);
505 528 font-size: 28rpx;
506 529 }
  530 + .value-spec {
  531 + height: 48rpx;
  532 + display: flex;
  533 + align-items: center;
  534 + color: #000000;
  535 + // justify-content: end;
  536 + &_box {
  537 + position: relative;
  538 + width: 60rpx;
  539 + height: 48rpx;
  540 +
  541 + &_1 {
  542 + font-size: 16rpx;
  543 + position: absolute;
  544 + top: -10rpx;
  545 + left: 0;
  546 + }
  547 +
  548 + &_2 {
  549 + font-size: 16rpx;
  550 + position: absolute;
  551 + bottom: -10rpx;
  552 + left: 0;
  553 + }
  554 + }
  555 +
  556 + &_val {
  557 + font-size: 28rpx;
  558 +
  559 + &.p12 {
  560 + padding-right: 12rpx;
  561 + }
  562 + }
  563 + }
  564 + .row-spec {
  565 + height: 60rpx;
  566 + align-items: center;
  567 + }
507 568 </style>
... ...
1 1 {
2   - "pages": [{
  2 + "pages": [
  3 + {
3 4 "path": "pages/login",
4 5 "style": {
5 6 "navigationBarTitleText": "登录",
6 7 "navigationStyle": "custom"
7 8 }
8   - }, {
  9 + },
  10 + {
9 11 "path": "pages/register",
10 12 "style": {
11 13 "navigationBarTitleText": "注册"
12 14 }
13   - }, {
  15 + },
  16 + {
14 17 "path": "pages/index",
15 18 "style": {
16 19 "navigationBarTitleText": "首页",
17 20 "navigationStyle": "custom"
18 21 }
19   - }, {
  22 + },
  23 + {
20 24 "path": "pages/mine/index",
21 25 "style": {
22 26 "navigationBarTitleText": "我的",
23 27 "navigationBarTextStyle": "white"
24 28 }
25   - }, {
  29 + },
  30 + {
26 31 "path": "pages/mine/index2",
27 32 "style": {
28 33 "navigationBarTitleText": "我的2"
29 34 }
30   - }, {
  35 + },
  36 + {
31 37 "path": "pages/mine/info/index",
32 38 "style": {
33 39 "navigationBarTitleText": "个人信息"
34 40 }
35   - }, {
  41 + },
  42 + {
36 43 "path": "pages/mine/pwd/index",
37 44 "style": {
38 45 "navigationBarTitleText": "修改密码"
39 46 }
40   - }, {
  47 + },
  48 + {
41 49 "path": "pages/mine/setting/index",
42 50 "style": {
43 51 "navigationBarTitleText": "应用设置"
44 52 }
45   - }, {
  53 + },
  54 + {
46 55 "path": "pages/mine/about/index",
47 56 "style": {
48 57 "navigationBarTitleText": "关于我们"
49 58 }
50   - }, {
  59 + },
  60 + {
51 61 "path": "pages/dev_manage/index",
52 62 "style": {
53 63 "navigationBarTitleText": "客户开发管理",
54 64 "navigationBarBackgroundColor": "#ffffff",
55 65 "navigationBarTextStyle": "black"
56 66 }
57   - }, {
58   - "path": "pages/dev_manage/add",
59   - "style": {
60   - "navigationBarTitleText": "新增客户开发",
61   - "navigationBarBackgroundColor": "#ffffff",
62   - "navigationBarTextStyle": "black"
63   - }
64   - }, {
65   - "path": "pages/dev_manage/modify",
66   - "style": {
67   - "navigationBarTitleText": "编辑客户开发",
68   - "navigationBarBackgroundColor": "#ffffff",
69   - "navigationBarTextStyle": "black"
70   - }
71   - }, {
  67 + },
  68 + {
72 69 "path": "pages/dev_manage/add",
73 70 "style": {
74 71 "navigationBarTitleText": "新增客户开发",
75 72 "navigationBarBackgroundColor": "#ffffff",
76 73 "navigationBarTextStyle": "black"
77 74 }
78   - }, {
79   - "path": "pages/dev_manage/detail",
80   - "style": {
81   - "navigationBarTitleText": "查看客户开发",
82   - "navigationBarBackgroundColor": "#ffffff",
83   - "navigationBarTextStyle": "black"
84   - }
85   - }, {
86   - "path": "pages/credit_manage/index",
87   - "style": {
88   - "navigationBarTitleText": "客户资信管理",
89   - "navigationBarBackgroundColor": "#ffffff",
90   - "navigationBarTextStyle": "black"
91   - }
92   - }, {
93   - "path": "pages/credit_manage/add",
94   - "style": {
95   - "navigationBarTitleText": "新增客户资信",
96   - "navigationBarBackgroundColor": "#ffffff",
97   - "navigationBarTextStyle": "black"
98   - }
99   - }, {
100   - "path": "pages/credit_manage/detail",
101   - "style": {
102   - "navigationBarTitleText": "查看客户资信",
103   - "navigationBarBackgroundColor": "#ffffff",
104   - "navigationBarTextStyle": "black"
105   - }
106   - }, {
107   - "path": "pages/credit_manage/modify",
108   - "style": {
109   - "navigationBarTitleText": "编辑客户资信",
110   - "navigationBarBackgroundColor": "#ffffff",
111   - "navigationBarTextStyle": "black"
112   - }
113   - }, {
114   - "path": "pages/credit_manage/change",
  75 + },
  76 + {
  77 + "path": "pages/dev_manage/modify",
115 78 "style": {
116   - "navigationBarTitleText": "申请客户资信变更",
  79 + "navigationBarTitleText": "编辑客户开发",
117 80 "navigationBarBackgroundColor": "#ffffff",
118 81 "navigationBarTextStyle": "black"
119 82 }
120   - }, {
121   - "path": "pages/credit_manage/history_detail",
  83 + },
  84 + {
  85 + "path": "pages/dev_manage/visit_add",
122 86 "style": {
123   - "navigationBarTitleText": "变更记录详情",
  87 + "navigationBarTitleText": "新增拜访记录",
124 88 "navigationBarBackgroundColor": "#ffffff",
125 89 "navigationBarTextStyle": "black"
126 90 }
127 91 },
128   - {
129   - "path": "pages/flow/myflow",
130   - "style": {
131   - "navigationBarTitleText": "我发起的",
132   - "navigationBarBackgroundColor": "#ffffff",
  92 + {
  93 + "path": "pages/dev_manage/add",
  94 + "style": {
  95 + "navigationBarTitleText": "新增客户开发",
  96 + "navigationBarBackgroundColor": "#ffffff",
  97 + "navigationBarTextStyle": "black"
  98 + }
  99 + },
  100 + {
  101 + "path": "pages/dev_manage/detail",
  102 + "style": {
  103 + "navigationBarTitleText": "查看客户开发",
  104 + "navigationBarBackgroundColor": "#ffffff",
  105 + "navigationBarTextStyle": "black"
  106 + }
  107 + },
  108 + {
  109 + "path": "pages/credit_manage/index",
  110 + "style": {
  111 + "navigationBarTitleText": "客户资信管理",
  112 + "navigationBarBackgroundColor": "#ffffff",
  113 + "navigationBarTextStyle": "black"
  114 + }
  115 + },
  116 + {
  117 + "path": "pages/credit_manage/add",
  118 + "style": {
  119 + "navigationBarTitleText": "新增客户资信",
  120 + "navigationBarBackgroundColor": "#ffffff",
  121 + "navigationBarTextStyle": "black"
  122 + }
  123 + },
  124 + {
  125 + "path": "pages/credit_manage/detail",
  126 + "style": {
  127 + "navigationBarTitleText": "查看客户资信",
  128 + "navigationBarBackgroundColor": "#ffffff",
  129 + "navigationBarTextStyle": "black"
  130 + }
  131 + },
  132 + {
  133 + "path": "pages/credit_manage/modify",
  134 + "style": {
  135 + "navigationBarTitleText": "编辑客户资信",
  136 + "navigationBarBackgroundColor": "#ffffff",
  137 + "navigationBarTextStyle": "black"
  138 + }
  139 + },
  140 + {
  141 + "path": "pages/credit_manage/change",
  142 + "style": {
  143 + "navigationBarTitleText": "申请客户资信变更",
  144 + "navigationBarBackgroundColor": "#ffffff",
  145 + "navigationBarTextStyle": "black"
  146 + }
  147 + },
  148 + {
  149 + "path": "pages/credit_manage/history_detail",
  150 + "style": {
  151 + "navigationBarTitleText": "变更记录详情",
  152 + "navigationBarBackgroundColor": "#ffffff",
  153 + "navigationBarTextStyle": "black"
  154 + }
  155 + },
  156 + {
  157 + "path": "pages/flow/myflow",
  158 + "style": {
  159 + "navigationBarTitleText": "我发起的",
  160 + "navigationBarBackgroundColor": "#ffffff",
133 161 "navigationBarTextStyle": "black"
134 162 }
135 163 },
... ... @@ -149,395 +177,452 @@
149 177 "navigationBarTextStyle": "black"
150 178 }
151 179 },
152   - {
153   - "path": "pages/flow/audit",
154   - "style": {
155   - "navigationBarTitleText": "审核",
156   - "navigationBarBackgroundColor": "#ffffff",
157   - "navigationBarTextStyle": "black"
158   - }
159   - },
160   - {
161   - "path": "pages/order_list/index",
162   - "style": {
163   - "navigationBarTitleText": "订货单列表",
164   - "navigationBarBackgroundColor": "#ffffff",
165   - "navigationBarTextStyle": "black"
166   - }
167   - },{
168   - "path": "pages/order_list/detail",
169   - "style": {
170   - "navigationBarTitleText": "查看订货单",
171   - "navigationBarBackgroundColor": "#ffffff",
172   - "navigationBarTextStyle": "black"
173   - }
174   - },
175   - {
176   - "path": "pages/order_list/modify",
177   - "style": {
178   - "navigationBarTitleText": "编辑订货单",
179   - "navigationBarBackgroundColor": "#ffffff",
180   - "navigationBarTextStyle": "black"
181   - }
182   - },
183   - {
184   - "path": "pages/order_list/shipment_apply",
185   - "style": {
186   - "navigationBarTitleText": "申请发货",
187   - "navigationBarBackgroundColor": "#ffffff",
188   - "navigationBarTextStyle": "black"
189   - }
190   - },
191   - {
192   - "path": "pages/revoke_list/index",
193   - "style": {
194   - "navigationBarTitleText": "撤销单列表",
195   - "navigationBarBackgroundColor": "#ffffff",
196   - "navigationBarTextStyle": "black"
197   - }
198   - },{
199   - "path": "pages/revoke_list/add",
200   - "style": {
201   - "navigationBarTitleText": "新增撤销单",
202   - "navigationBarBackgroundColor": "#ffffff",
203   - "navigationBarTextStyle": "black"
204   - }
205   - },{
206   - "path": "pages/revoke_list/detail",
207   - "style": {
208   - "navigationBarTitleText": "查看撤销单",
209   - "navigationBarBackgroundColor": "#ffffff",
210   - "navigationBarTextStyle": "black"
211   - }
212   - },{
213   - "path": "pages/revoke_list/modify",
214   - "style": {
215   - "navigationBarTitleText": "编辑撤销单",
216   - "navigationBarBackgroundColor": "#ffffff",
217   - "navigationBarTextStyle": "black"
218   - }
219   - },
220   - {
221   - "path": "pages/change_list/index",
222   - "style": {
223   - "navigationBarTitleText": "规格变更单",
224   - "navigationBarBackgroundColor": "#ffffff",
225   - "navigationBarTextStyle": "black"
226   - }
227   - },{
228   - "path": "pages/change_list/add",
229   - "style": {
230   - "navigationBarTitleText": "新增规格变更单",
231   - "navigationBarBackgroundColor": "#ffffff",
232   - "navigationBarTextStyle": "black"
233   - }
234   - },{
235   - "path": "pages/change_list/detail",
236   - "style": {
237   - "navigationBarTitleText": "查看规格变更单",
238   - "navigationBarBackgroundColor": "#ffffff",
239   - "navigationBarTextStyle": "black"
240   - }
241   - },{
242   - "path": "pages/change_list/modify",
243   - "style": {
244   - "navigationBarTitleText": "编辑规格变更单",
245   - "navigationBarBackgroundColor": "#ffffff",
246   - "navigationBarTextStyle": "black"
247   - }
248   - },
249   - {
250   - "path": "pages/contract_framework/index",
251   - "style": {
252   - "navigationBarTitleText": "框架合同",
253   - "navigationBarBackgroundColor": "#ffffff",
  180 + {
  181 + "path": "pages/flow/audit",
  182 + "style": {
  183 + "navigationBarTitleText": "审核",
  184 + "navigationBarBackgroundColor": "#ffffff",
  185 + "navigationBarTextStyle": "black"
  186 + }
  187 + },
  188 + {
  189 + "path": "pages/order_list/index",
  190 + "style": {
  191 + "navigationBarTitleText": "订货单列表",
  192 + "navigationBarBackgroundColor": "#ffffff",
  193 + "navigationBarTextStyle": "black"
  194 + }
  195 + },
  196 + {
  197 + "path": "pages/order_list/detail",
  198 + "style": {
  199 + "navigationBarTitleText": "查看订货单",
  200 + "navigationBarBackgroundColor": "#ffffff",
  201 + "navigationBarTextStyle": "black"
  202 + }
  203 + },
  204 + {
  205 + "path": "pages/order_list/modify",
  206 + "style": {
  207 + "navigationBarTitleText": "编辑订货单",
  208 + "navigationBarBackgroundColor": "#ffffff",
  209 + "navigationBarTextStyle": "black"
  210 + }
  211 + },
  212 + {
  213 + "path": "pages/order_list/shipment_apply",
  214 + "style": {
  215 + "navigationBarTitleText": "申请发货",
  216 + "navigationBarBackgroundColor": "#ffffff",
254 217 "navigationBarTextStyle": "black"
255 218 }
256   - }, {
  219 + },
  220 + {
  221 + "path": "pages/revoke_list/index",
  222 + "style": {
  223 + "navigationBarTitleText": "撤销单列表",
  224 + "navigationBarBackgroundColor": "#ffffff",
  225 + "navigationBarTextStyle": "black"
  226 + }
  227 + },
  228 + {
  229 + "path": "pages/revoke_list/add",
  230 + "style": {
  231 + "navigationBarTitleText": "新增撤销单",
  232 + "navigationBarBackgroundColor": "#ffffff",
  233 + "navigationBarTextStyle": "black"
  234 + }
  235 + },
  236 + {
  237 + "path": "pages/revoke_list/detail",
  238 + "style": {
  239 + "navigationBarTitleText": "查看撤销单",
  240 + "navigationBarBackgroundColor": "#ffffff",
  241 + "navigationBarTextStyle": "black"
  242 + }
  243 + },
  244 + {
  245 + "path": "pages/revoke_list/modify",
  246 + "style": {
  247 + "navigationBarTitleText": "编辑撤销单",
  248 + "navigationBarBackgroundColor": "#ffffff",
  249 + "navigationBarTextStyle": "black"
  250 + }
  251 + },
  252 + {
  253 + "path": "pages/change_list/index",
  254 + "style": {
  255 + "navigationBarTitleText": "规格变更单",
  256 + "navigationBarBackgroundColor": "#ffffff",
  257 + "navigationBarTextStyle": "black"
  258 + }
  259 + },
  260 + {
  261 + "path": "pages/change_list/add",
  262 + "style": {
  263 + "navigationBarTitleText": "新增规格变更单",
  264 + "navigationBarBackgroundColor": "#ffffff",
  265 + "navigationBarTextStyle": "black"
  266 + }
  267 + },
  268 + {
  269 + "path": "pages/change_list/detail",
  270 + "style": {
  271 + "navigationBarTitleText": "查看规格变更单",
  272 + "navigationBarBackgroundColor": "#ffffff",
  273 + "navigationBarTextStyle": "black"
  274 + }
  275 + },
  276 + {
  277 + "path": "pages/change_list/modify",
  278 + "style": {
  279 + "navigationBarTitleText": "编辑规格变更单",
  280 + "navigationBarBackgroundColor": "#ffffff",
  281 + "navigationBarTextStyle": "black"
  282 + }
  283 + },
  284 + {
  285 + "path": "pages/contract_framework/index",
  286 + "style": {
  287 + "navigationBarTitleText": "框架合同",
  288 + "navigationBarBackgroundColor": "#ffffff",
  289 + "navigationBarTextStyle": "black"
  290 + }
  291 + },
  292 + {
257 293 "path": "pages/contract_framework/add",
258 294 "style": {
259 295 "navigationBarTitleText": "新增框架合同",
260 296 "navigationBarBackgroundColor": "#ffffff",
261 297 "navigationBarTextStyle": "black"
262 298 }
263   - }, {
264   - "path": "pages/contract_framework/detail",
265   - "style": {
266   - "navigationBarTitleText": "框架合同详情",
267   - "navigationBarBackgroundColor": "#ffffff",
268   - "navigationBarTextStyle": "black"
269   - }
270   - }, {
271   - "path": "pages/contract_framework/modify",
272   - "style": {
273   - "navigationBarTitleText": "编辑框架合同",
274   - "navigationBarBackgroundColor": "#ffffff",
275   - "navigationBarTextStyle": "black"
276   - }
277   - },{
278   - "path": "pages/contract_retail/index",
279   - "style": {
280   - "navigationBarTitleText": "经销标准合同",
281   - "navigationBarBackgroundColor": "#ffffff",
282   - "navigationBarTextStyle": "black"
283   - }
284   - }, {
  299 + },
  300 + {
  301 + "path": "pages/contract_framework/detail",
  302 + "style": {
  303 + "navigationBarTitleText": "框架合同详情",
  304 + "navigationBarBackgroundColor": "#ffffff",
  305 + "navigationBarTextStyle": "black"
  306 + }
  307 + },
  308 + {
  309 + "path": "pages/contract_framework/modify",
  310 + "style": {
  311 + "navigationBarTitleText": "编辑框架合同",
  312 + "navigationBarBackgroundColor": "#ffffff",
  313 + "navigationBarTextStyle": "black"
  314 + }
  315 + },
  316 + {
  317 + "path": "pages/contract_retail/index",
  318 + "style": {
  319 + "navigationBarTitleText": "经销标准合同",
  320 + "navigationBarBackgroundColor": "#ffffff",
  321 + "navigationBarTextStyle": "black"
  322 + }
  323 + },
  324 + {
285 325 "path": "pages/contract_retail/add",
286 326 "style": {
287 327 "navigationBarTitleText": "新增经销标准合同",
288 328 "navigationBarBackgroundColor": "#ffffff",
289 329 "navigationBarTextStyle": "black"
290 330 }
291   - },{
  331 + },
  332 + {
292 333 "path": "pages/contract_retail/detail",
293 334 "style": {
294 335 "navigationBarTitleText": "经销标准合同详情",
295 336 "navigationBarBackgroundColor": "#ffffff",
296 337 "navigationBarTextStyle": "black"
297 338 }
298   - },{
  339 + },
  340 + {
299 341 "path": "pages/contract_retail/modify",
300 342 "style": {
301 343 "navigationBarTitleText": "编辑经销标准合同",
302 344 "navigationBarBackgroundColor": "#ffffff",
303 345 "navigationBarTextStyle": "black"
304 346 }
305   - },{
  347 + },
  348 + {
306 349 "path": "pages/contract_stock/index",
307 350 "style": {
308 351 "navigationBarTitleText": "经销库存合同",
309 352 "navigationBarBackgroundColor": "#ffffff",
310 353 "navigationBarTextStyle": "black"
311 354 }
312   - }, {
  355 + },
  356 + {
313 357 "path": "pages/contract_stock/add",
314 358 "style": {
315 359 "navigationBarTitleText": "新增经销库存合同",
316 360 "navigationBarBackgroundColor": "#ffffff",
317 361 "navigationBarTextStyle": "black"
318 362 }
319   - },{
  363 + },
  364 + {
320 365 "path": "pages/contract_stock/detail",
321 366 "style": {
322 367 "navigationBarTitleText": "经销库存合同详情",
323 368 "navigationBarBackgroundColor": "#ffffff",
324 369 "navigationBarTextStyle": "black"
325 370 }
326   - },{
  371 + },
  372 + {
327 373 "path": "pages/contract_stock/modify",
328 374 "style": {
329 375 "navigationBarTitleText": "编辑经销库存合同",
330 376 "navigationBarBackgroundColor": "#ffffff",
331 377 "navigationBarTextStyle": "black"
332 378 }
333   - },{
  379 + },
  380 + {
334 381 "path": "pages/contract_stock/lock",
335 382 "style": {
336 383 "navigationBarTitleText": "锁价",
337 384 "navigationBarBackgroundColor": "#ffffff",
338 385 "navigationBarTextStyle": "black"
339 386 }
340   - },{
  387 + },
  388 + {
341 389 "path": "pages/contract_unplan/index",
342 390 "style": {
343 391 "navigationBarTitleText": "经销未锁规合同",
344 392 "navigationBarBackgroundColor": "#ffffff",
345 393 "navigationBarTextStyle": "black"
346 394 }
347   - },{
  395 + },
  396 + {
348 397 "path": "pages/contract_unplan/add",
349 398 "style": {
350 399 "navigationBarTitleText": "新增经销未锁规合同",
351 400 "navigationBarBackgroundColor": "#ffffff",
352 401 "navigationBarTextStyle": "black"
353 402 }
354   - },{
  403 + },
  404 + {
355 405 "path": "pages/contract_unplan/detail",
356 406 "style": {
357 407 "navigationBarTitleText": "经销未锁规合同详情",
358 408 "navigationBarBackgroundColor": "#ffffff",
359 409 "navigationBarTextStyle": "black"
360 410 }
361   - },{
  411 + },
  412 + {
362 413 "path": "pages/contract_unplan/modify",
363 414 "style": {
364 415 "navigationBarTitleText": "编辑经销未锁规合同",
365 416 "navigationBarBackgroundColor": "#ffffff",
366 417 "navigationBarTextStyle": "black"
367 418 }
368   - },{
  419 + },
  420 + {
369 421 "path": "pages/contract_unplan/lock",
370 422 "style": {
371 423 "navigationBarTitleText": "锁规",
372 424 "navigationBarBackgroundColor": "#ffffff",
373 425 "navigationBarTextStyle": "black"
374 426 }
375   - }, {
  427 + },
  428 + {
376 429 "path": "pages/contract_unplan/lock_apply",
377 430 "style": {
378 431 "navigationBarTitleText": "锁规延期申请",
379 432 "navigationBarBackgroundColor": "#ffffff",
380 433 "navigationBarTextStyle": "black"
381 434 }
382   - },{
  435 + },
  436 + {
383 437 "path": "pages/contract_process/index",
384 438 "style": {
385 439 "navigationBarTitleText": "加工标准合同",
386 440 "navigationBarBackgroundColor": "#ffffff",
387 441 "navigationBarTextStyle": "black"
388 442 }
389   - },{
  443 + },
  444 + {
390 445 "path": "pages/contract_process/add",
391 446 "style": {
392 447 "navigationBarTitleText": "新增加工标准合同",
393 448 "navigationBarBackgroundColor": "#ffffff",
394 449 "navigationBarTextStyle": "black"
395 450 }
396   - },{
  451 + },
  452 + {
397 453 "path": "pages/contract_process/detail",
398 454 "style": {
399 455 "navigationBarTitleText": "加工标准合同详情",
400 456 "navigationBarBackgroundColor": "#ffffff",
401 457 "navigationBarTextStyle": "black"
402 458 }
403   - },{
  459 + },
  460 + {
404 461 "path": "pages/contract_process/modify",
405 462 "style": {
406 463 "navigationBarTitleText": "编辑加工标准合同",
407 464 "navigationBarBackgroundColor": "#ffffff",
408 465 "navigationBarTextStyle": "black"
409 466 }
410   - }, {
  467 + },
  468 + {
411 469 "path": "pages/contract_foreign_std/index",
412 470 "style": {
413 471 "navigationBarTitleText": "外贸标准合同",
414 472 "navigationBarBackgroundColor": "#ffffff",
415 473 "navigationBarTextStyle": "black"
416 474 }
417   - },{
  475 + },
  476 + {
418 477 "path": "pages/contract_foreign_std/add",
419 478 "style": {
420 479 "navigationBarTitleText": "新增外贸标准合同",
421 480 "navigationBarBackgroundColor": "#ffffff",
422 481 "navigationBarTextStyle": "black"
423 482 }
424   - },{
  483 + },
  484 + {
425 485 "path": "pages/contract_foreign_std/detail",
426 486 "style": {
427 487 "navigationBarTitleText": "外贸标准合同详情",
428 488 "navigationBarBackgroundColor": "#ffffff",
429 489 "navigationBarTextStyle": "black"
430 490 }
431   - },{
  491 + },
  492 + {
432 493 "path": "pages/contract_foreign_std/modify",
433 494 "style": {
434 495 "navigationBarTitleText": "编辑外贸标准合同",
435 496 "navigationBarBackgroundColor": "#ffffff",
436 497 "navigationBarTextStyle": "black"
437 498 }
438   - }, {
  499 + },
  500 + {
439 501 "path": "pages/contract_foreign_stock/index",
440 502 "style": {
441 503 "navigationBarTitleText": "外贸库存合同",
442 504 "navigationBarBackgroundColor": "#ffffff",
443 505 "navigationBarTextStyle": "black"
444 506 }
445   - },{
  507 + },
  508 + {
446 509 "path": "pages/contract_foreign_stock/add",
447 510 "style": {
448 511 "navigationBarTitleText": "新增外贸库存合同",
449 512 "navigationBarBackgroundColor": "#ffffff",
450 513 "navigationBarTextStyle": "black"
451 514 }
452   - },{
  515 + },
  516 + {
453 517 "path": "pages/contract_foreign_stock/detail",
454 518 "style": {
455 519 "navigationBarTitleText": "外贸库存合同详情",
456 520 "navigationBarBackgroundColor": "#ffffff",
457 521 "navigationBarTextStyle": "black"
458 522 }
459   - },{
  523 + },
  524 + {
460 525 "path": "pages/contract_foreign_stock/modify",
461 526 "style": {
462 527 "navigationBarTitleText": "编辑外贸库存合同",
463 528 "navigationBarBackgroundColor": "#ffffff",
464 529 "navigationBarTextStyle": "black"
465 530 }
466   - },{
  531 + },
  532 + {
467 533 "path": "pages/contract_foreign_stock/lock",
468 534 "style": {
469 535 "navigationBarTitleText": "锁价",
470 536 "navigationBarBackgroundColor": "#ffffff",
471 537 "navigationBarTextStyle": "black"
472 538 }
473   - },{
  539 + },
  540 + {
474 541 "path": "pages/contract_foreign_unplan/index",
475 542 "style": {
476 543 "navigationBarTitleText": "外贸未锁规合同",
477 544 "navigationBarBackgroundColor": "#ffffff",
478 545 "navigationBarTextStyle": "black"
479 546 }
480   - },{
  547 + },
  548 + {
481 549 "path": "pages/contract_foreign_unplan/add",
482 550 "style": {
483 551 "navigationBarTitleText": "新增外贸未锁规合同",
484 552 "navigationBarBackgroundColor": "#ffffff",
485 553 "navigationBarTextStyle": "black"
486 554 }
487   - },{
  555 + },
  556 + {
488 557 "path": "pages/contract_foreign_unplan/detail",
489 558 "style": {
490 559 "navigationBarTitleText": "外贸未锁规合同详情",
491 560 "navigationBarBackgroundColor": "#ffffff",
492 561 "navigationBarTextStyle": "black"
493 562 }
494   - },{
  563 + },
  564 + {
495 565 "path": "pages/contract_foreign_unplan/modify",
496 566 "style": {
497 567 "navigationBarTitleText": "编辑外贸未锁规合同",
498 568 "navigationBarBackgroundColor": "#ffffff",
499 569 "navigationBarTextStyle": "black"
500 570 }
501   - },{
  571 + },
  572 + {
502 573 "path": "pages/contract_foreign_unplan/lock",
503 574 "style": {
504 575 "navigationBarTitleText": "锁规",
505 576 "navigationBarBackgroundColor": "#ffffff",
506 577 "navigationBarTextStyle": "black"
507 578 }
508   - },{
  579 + },
  580 + {
509 581 "path": "pages/contract_foreign_unplan/lock_apply",
510 582 "style": {
511 583 "navigationBarTitleText": "锁规延期申请",
512 584 "navigationBarBackgroundColor": "#ffffff",
513 585 "navigationBarTextStyle": "black"
514 586 }
515   - },{
  587 + },
  588 + {
516 589 "path": "pages/contract_unlocked_operation/detail",
517 590 "style": {
518 591 "navigationBarTitleText": "锁价无规格操作申请单详情",
519 592 "navigationBarBackgroundColor": "#ffffff",
520 593 "navigationBarTextStyle": "black"
521 594 }
522   - },{
  595 + },
  596 + {
523 597 "path": "pages/contract_unlocked_operation/modify",
524 598 "style": {
525 599 "navigationBarTitleText": "编辑锁价无规格操作申请单",
526 600 "navigationBarBackgroundColor": "#ffffff",
527 601 "navigationBarTextStyle": "black"
528 602 }
529   - },{
  603 + },
  604 + {
530 605 "path": "pages/contract_unlocked_operation/index",
531 606 "style": {
532 607 "navigationBarTitleText": "锁价无规格操作申请单",
533 608 "navigationBarBackgroundColor": "#ffffff",
534 609 "navigationBarTextStyle": "black"
535 610 }
  611 + },
  612 + {
  613 + "path": "pages/message/index",
  614 + "style": {
  615 + "navigationBarTitleText": "消息列表",
  616 + "navigationBarBackgroundColor": "#ffffff",
  617 + "navigationBarTextStyle": "black"
  618 + }
536 619 }
537 620 ],
538   - "subPackages": [{
  621 + "subPackages": [
  622 + {
539 623 "root": "pages-business",
540   - "pages": [{
  624 + "pages": [
  625 + {
541 626 "path": "purchase/config",
542 627 "style": {
543 628 "navigationBarTitleText": "采购设置"
... ... @@ -571,7 +656,8 @@
571 656 },
572 657 {
573 658 "root": "pages-data",
574   - "pages": [{
  659 + "pages": [
  660 + {
575 661 "path": "address/index",
576 662 "style": {
577 663 "navigationBarTitleText": "地址管理"
... ... @@ -656,17 +742,20 @@
656 742 "color": "rgba(0,0,0,0.9)",
657 743 "backgroundColor": "#ffffff",
658 744 "borderStyle": "white",
659   - "list": [{
660   - "pagePath": "pages/index",
661   - "iconPath": "static/images/tabbar/home.png",
662   - "selectedIconPath": "static/images/tabbar/home_act.png",
663   - "text": "首页"
664   - }, {
665   - "pagePath": "pages/mine/index",
666   - "iconPath": "static/images/tabbar/mine.png",
667   - "selectedIconPath": "static/images/tabbar/mine_act.png",
668   - "text": "我的"
669   - }]
  745 + "list": [
  746 + {
  747 + "pagePath": "pages/index",
  748 + "iconPath": "static/images/tabbar/home.png",
  749 + "selectedIconPath": "static/images/tabbar/home_act.png",
  750 + "text": "首页"
  751 + },
  752 + {
  753 + "pagePath": "pages/mine/index",
  754 + "iconPath": "static/images/tabbar/mine.png",
  755 + "selectedIconPath": "static/images/tabbar/mine_act.png",
  756 + "text": "我的"
  757 + }
  758 + ]
670 759 },
671 760 "globalStyle": {
672 761 "navigationBarTitleText": "ERP",
... ...
... ... @@ -37,14 +37,14 @@
37 37
38 38 <uni-list-item title="交货方式">
39 39 <template v-slot:footer>
40   - <uni-easyinput v-model="form.deliveryMethod" placeholder="请输入交货方式" :inputBorder="false" />
  40 + <view class="readonly-text">{{ form.deliveryMethod }}</view>
41 41 </template>
42 42 </uni-list-item>
43 43 </view>
44 44
45 45 <!-- 产品 -->
46 46 <view class="section2">
47   - <Product mode="add" :list="initPurchaseOrderLineList" @change="purchaseOrderLineListChange" />
  47 + <Product mode="add" :list="initPurchaseOrderLineList" @change="purchaseOrderLineListChange" :orderDate="form.orderDate" />
48 48 </view>
49 49
50 50 <view class="section">
... ... @@ -69,17 +69,6 @@
69 69 </view>
70 70 </template>
71 71 </uni-list-item>
72   - <uni-list-item class="amount-item">
73   - <template v-slot:body>
74   - <view class="item-title"><text>包装费</text></view>
75   - </template>
76   - <template v-slot:footer>
77   - <view class="amount-row">
78   - <uni-easyinput type="number" v-model="form.packagingFee" placeholder="0.00" :inputBorder="false" />
79   - <text class="unit">元</text>
80   - </view>
81   - </template>
82   - </uni-list-item>
83 72 <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
84 73 @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
85 74 <template v-slot:body>
... ... @@ -91,6 +80,11 @@
91 80 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入标准" :inputBorder="false" />
92 81 </template>
93 82 </uni-list-item>
  83 + <uni-list-item title="变更说明">
  84 + <template v-slot:footer>
  85 + <uni-easyinput v-model="form.changeDescription" placeholder="请输入变更说明" :inputBorder="false" />
  86 + </template>
  87 + </uni-list-item>
94 88 </view>
95 89
96 90
... ... @@ -185,6 +179,7 @@ export default {
185 179 packagingFee: '',
186 180 executionStandard: '',
187 181 executionStandardRemarks: '',
  182 + changeDescription: '',
188 183 totalQuantity: '',
189 184 afterTotalQuantity: '',
190 185 pieceWeightHeader: '',
... ... @@ -297,7 +292,7 @@ export default {
297 292 delete next.id
298 293 delete next.status
299 294 this.form = next
300   - const lines = Array.isArray(item.purchaseOrderLineList) ? item.purchaseOrderLineList.map(x => ({ ...x, purchaseOrderId: x.id, id: '' })) : []
  295 + const lines = Array.isArray(item.purchaseOrderLineList) ? item.purchaseOrderLineList.map(x => ({ ...x, purchaseOrderId: x.id, afterId: x.id, id: '' })) : []
301 296 this.initPurchaseOrderLineList = lines
302 297 const sum = lines.reduce((acc, it) => {
303 298 const v = Number(it && it.quantity)
... ...
... ... @@ -29,10 +29,10 @@
29 29 <view class="row"><text class="label">价格表编号</text><text class="value">{{ form.priceListNo }}</text></view>
30 30 <view class="row"><text class="label">开票情况</text><text class="value">{{ form.invoicingStatus }}</text></view>
31 31 <view class="row"><text class="label">运费</text><text class="value">{{ form.shippingCost }}</text></view>
32   - <view class="row"><text class="label">包装费</text><text class="value">{{ form.packagingFee }}</text></view>
33 32 <view class="row"><text class="label">执行标准</text><text class="value">{{ getDicName('APPLICABLE_STANDARD',
34 33 form.executionStandard, dicOptions.APPLICABLE_STANDARD) }}</text></view>
35 34 <view v-if="form.executionStandard === 'OTHER'" class="row"><text class="label">标准</text><text class="value">{{ form.executionStandardRemarks }}</text></view>
  35 + <view class="row"><text class="label">变更说明</text><text class="value">{{ form.changeDescription }}</text></view>
36 36 </view>
37 37
38 38 <view class="title-header">
... ... @@ -102,11 +102,11 @@ export default {
102 102 displayButtons() {
103 103 const f = this.statusFlags
104 104 return [
105   - { ...this.buttons[0], visible: f.canEdit },
106   - { ...this.buttons[1], visible: true },
107   - { ...this.buttons[2], visible: f.canAudit },
108   - { ...this.buttons[3], visible: f.canConfirmChange },
109   - { ...this.buttons[4], visible: f.canCancel },
  105 + { ...this.buttons[0], visible: f.canEdit && this.$auth.hasPermi('order-manage:change-list:modify') },
  106 + { ...this.buttons[1], visible: this.$auth.hasPermi('order-manage:change-list:review') },
  107 + { ...this.buttons[2], visible: f.canAudit && this.$auth.hasPermi('order-manage:change-list:approve') },
  108 + { ...this.buttons[3], visible: f.canConfirmChange && this.$auth.hasPermi('order-manage:change-list:confirm') },
  109 + { ...this.buttons[4], visible: f.canCancel && this.$auth.hasPermi('order-manage:change-list:cancel') },
110 110 ]
111 111 }
112 112 },
... ...
... ... @@ -5,7 +5,7 @@
5 5 <uni-search-bar v-model="searchKeyword" radius="6" placeholder="请输入订货单位或订单编号" clearButton="auto"
6 6 cancelButton="none" bgColor="#F3F3F3" textColor="rgba(0,0,0,0.4)" @confirm="onSearchConfirm"
7 7 @input="onSearchInput" />
8   - <image class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
  8 + <image v-if="$auth.hasPermi('order-manage:change-list:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
9 9 <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
10 10 </view>
11 11 </view>
... ... @@ -17,8 +17,9 @@
17 17 <view class="card" @click.stop="onCardClick(item)">
18 18 <view class="card-header">
19 19 <text class="title omit2">{{ item.orderingUnitName }}</text>
20   - <text v-if="item.examineStatus" :class="['status', `status_${item.examineStatus}`]">{{ filterStatus(item.examineStatus)
21   - }}</text>
  20 + <text v-if="item.examineStatus" :class="['status', `status_${item.examineStatus}`]">{{
  21 + filterStatus(item.examineStatus)
  22 + }}</text>
22 23 </view>
23 24 <view class="info-row"><text>订单编号</text><text>{{ item.orderNo }}</text></view>
24 25 <view class="info-row"><text>生产厂</text><text>{{ item.workshopName }}</text></view>
... ... @@ -289,12 +290,12 @@ export default {
289 290 }
290 291
291 292 text {
292   - width: 60%;
  293 + width: 50%;
293 294 line-height: 32rpx;
  295 + word-wrap: break-word;
294 296
295 297 &:last-child {
296 298 color: rgba(0, 0, 0, 0.9);
297   - width: 40%;
298 299 }
299 300 }
300 301 }
... ...
... ... @@ -36,14 +36,14 @@
36 36
37 37 <uni-list-item title="交货方式">
38 38 <template v-slot:footer>
39   - <uni-easyinput v-model="form.deliveryMethod" placeholder="请输入交货方式" :inputBorder="false" />
  39 + <view class="readonly-text">{{ form.deliveryMethod }}</view>
40 40 </template>
41 41 </uni-list-item>
42 42 </view>
43 43
44 44 <!-- 产品 -->
45 45 <view class="section2">
46   - <Product mode="add" :list="initPurchaseOrderLineList" @change="purchaseOrderLineListChange" />
  46 + <Product mode="add" :list="initPurchaseOrderLineList" @change="purchaseOrderLineListChange" :orderDate="form.orderDate" />
47 47 </view>
48 48
49 49 <view class="section">
... ... @@ -68,17 +68,6 @@
68 68 </view>
69 69 </template>
70 70 </uni-list-item>
71   - <uni-list-item class="amount-item">
72   - <template v-slot:body>
73   - <view class="item-title"><text>包装费</text></view>
74   - </template>
75   - <template v-slot:footer>
76   - <view class="amount-row">
77   - <uni-easyinput type="number" v-model="form.packagingFee" placeholder="0.00" :inputBorder="false" />
78   - <text class="unit">元</text>
79   - </view>
80   - </template>
81   - </uni-list-item>
82 71 <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
83 72 @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
84 73 <template v-slot:body>
... ... @@ -90,6 +79,11 @@
90 79 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入标准" :inputBorder="false" />
91 80 </template>
92 81 </uni-list-item>
  82 + <uni-list-item title="变更说明">
  83 + <template v-slot:footer>
  84 + <uni-easyinput v-model="form.changeDescription" placeholder="请输入变更说明" :inputBorder="false" />
  85 + </template>
  86 + </uni-list-item>
93 87 </view>
94 88
95 89
... ... @@ -182,6 +176,7 @@ export default {
182 176 packagingFee: '',
183 177 executionStandard: '',
184 178 executionStandardRemarks: '',
  179 + changeDescription: '',
185 180 totalQuantity: '',
186 181 afterTotalQuantity: '',
187 182 pieceWeightHeader: '',
... ...
... ... @@ -34,58 +34,74 @@
34 34 </template>
35 35 </uni-list-item>
36 36 <view v-show="!item.collapsed">
37   - <uni-list-item title="厚度">
  37 + <uni-list-item title="厚度(mm)">
38 38 <template v-slot:footer>
39   - <uni-easyinput type="digit" v-model="item.thickness" placeholder="请输入厚度" :inputBorder="false"
40   - @input="onNonNegativeNumberInput($event, item, idx, 'thickness')" @blur="onNonNegativeNumberBlur(item, idx, 'thickness')" />
  39 + <uni-easyinput type="digit" v-model="item.thickness" placeholder="请输入厚度"
  40 + :inputBorder="false"
  41 + @input="onNonNegativeNumberInput($event, item, idx, 'thickness')"
  42 + @blur="onNonNegativeNumberBlur(item, idx, 'thickness')" />
41 43 </template>
42 44 </uni-list-item>
43   - <uni-list-item title="厚度公差 +">
  45 + <uni-list-item title="厚度公差 +(mm)">
44 46 <template v-slot:footer>
45 47 <uni-easyinput type="digit" v-model="item.thicknessTolPos" placeholder="请输入厚度公差 +"
46   - :inputBorder="false" @input="onNonNegativeNumberInput($event, item, idx, 'thicknessTolPos')" @blur="onNonNegativeNumberBlur(item, idx, 'thicknessTolPos')" />
  48 + :inputBorder="false"
  49 + @input="onNonNegativeNumberInput($event, item, idx, 'thicknessTolPos')"
  50 + @blur="onNonNegativeNumberBlur(item, idx, 'thicknessTolPos')" />
47 51 </template>
48 52 </uni-list-item>
49   - <uni-list-item title="厚度公差 -">
  53 + <uni-list-item title="厚度公差 -(mm)">
50 54 <template v-slot:footer>
51 55 <uni-easyinput type="digit" v-model="item.thicknessTolNeg" placeholder="请输入厚度公差 -"
52   - :inputBorder="false" @input="onNonNegativeNumberInput($event, item, idx, 'thicknessTolNeg')" @blur="onNonNegativeNumberBlur(item, idx, 'thicknessTolNeg')" />
  56 + :inputBorder="false"
  57 + @input="onNonNegativeNumberInput($event, item, idx, 'thicknessTolNeg')"
  58 + @blur="onNonNegativeNumberBlur(item, idx, 'thicknessTolNeg')" />
53 59 </template>
54 60 </uni-list-item>
55   - <uni-list-item title="宽度">
  61 + <uni-list-item title="宽度(mm)">
56 62 <template v-slot:footer>
57   - <uni-easyinput type="digit" v-model="item.width" placeholder="请输入宽度" :inputBorder="false"
58   - @input="onNonNegativeNumberInput($event, item, idx, 'width')" @blur="onNonNegativeNumberBlur(item, idx, 'width')" />
  63 + <uni-easyinput type="digit" v-model="item.width" placeholder="请输入宽度"
  64 + :inputBorder="false" @input="onNonNegativeNumberInput($event, item, idx, 'width')"
  65 + @blur="onNonNegativeNumberBlur(item, idx, 'width')" />
59 66 </template>
60 67 </uni-list-item>
61   - <uni-list-item title="宽度公差 +">
  68 + <uni-list-item title="宽度公差 +(mm)">
62 69 <template v-slot:footer>
63 70 <uni-easyinput type="digit" v-model="item.widthTolPos" placeholder="请输入宽度公差 +"
64   - :inputBorder="false" @input="onNonNegativeNumberInput($event, item, idx, 'widthTolPos')" @blur="onNonNegativeNumberBlur(item, idx, 'widthTolPos')" />
  71 + :inputBorder="false"
  72 + @input="onNonNegativeNumberInput($event, item, idx, 'widthTolPos')"
  73 + @blur="onNonNegativeNumberBlur(item, idx, 'widthTolPos')" />
65 74 </template>
66 75 </uni-list-item>
67   - <uni-list-item title="宽度公差 -">
  76 + <uni-list-item title="宽度公差 -(mm)">
68 77 <template v-slot:footer>
69 78 <uni-easyinput type="digit" v-model="item.widthTolNeg" placeholder="请输入宽度公差 -"
70   - :inputBorder="false" @input="onNonNegativeNumberInput($event, item, idx, 'widthTolNeg')" @blur="onNonNegativeNumberBlur(item, idx, 'widthTolNeg')" />
  79 + :inputBorder="false"
  80 + @input="onNonNegativeNumberInput($event, item, idx, 'widthTolNeg')"
  81 + @blur="onNonNegativeNumberBlur(item, idx, 'widthTolNeg')" />
71 82 </template>
72 83 </uni-list-item>
73   - <uni-list-item title="长度">
  84 + <uni-list-item title="长度(mm)">
74 85 <template v-slot:footer>
75   - <uni-easyinput type="digit" v-model="item.length" placeholder="请输入长度" :inputBorder="false"
76   - @input="onNonNegativeNumberInput($event, item, idx, 'length')" @blur="onNonNegativeNumberBlur(item, idx, 'length')" />
  86 + <uni-easyinput type="digit" v-model="item.length" placeholder="请输入长度"
  87 + :inputBorder="false" @input="onNonNegativeNumberInput($event, item, idx, 'length')"
  88 + @blur="onNonNegativeNumberBlur(item, idx, 'length')" />
77 89 </template>
78 90 </uni-list-item>
79   - <uni-list-item title="长度公差 +">
  91 + <uni-list-item title="长度公差 +(mm)">
80 92 <template v-slot:footer>
81 93 <uni-easyinput type="digit" v-model="item.lengthTolPos" placeholder="请输入长度公差 +"
82   - :inputBorder="false" @input="onNonNegativeNumberInput($event, item, idx, 'lengthTolPos')" @blur="onNonNegativeNumberBlur(item, idx, 'lengthTolPos')" />
  94 + :inputBorder="false"
  95 + @input="onNonNegativeNumberInput($event, item, idx, 'lengthTolPos')"
  96 + @blur="onNonNegativeNumberBlur(item, idx, 'lengthTolPos')" />
83 97 </template>
84 98 </uni-list-item>
85   - <uni-list-item title="长度公差 -">
  99 + <uni-list-item title="长度公差 -(mm)">
86 100 <template v-slot:footer>
87 101 <uni-easyinput type="digit" v-model="item.lengthTolNeg" placeholder="请输入长度公差 -"
88   - :inputBorder="false" @input="onNonNegativeNumberInput($event, item, idx, 'lengthTolNeg')" @blur="onNonNegativeNumberBlur(item, idx, 'lengthTolNeg')" />
  102 + :inputBorder="false"
  103 + @input="onNonNegativeNumberInput($event, item, idx, 'lengthTolNeg')"
  104 + @blur="onNonNegativeNumberBlur(item, idx, 'lengthTolNeg')" />
89 105 </template>
90 106 </uni-list-item>
91 107 <uni-list-item title="状态">
... ... @@ -95,19 +111,38 @@
95 111 </uni-list-item>
96 112 <uni-list-item title="数量kg">
97 113 <template v-slot:footer>
98   - <uni-easyinput type="digit" v-model="item.quantity" placeholder="请输入数量kg" :inputBorder="false"
99   - @input="onNonNegativeNumberInput($event, item, idx, 'quantity')" @blur="onNonNegativeNumberBlur(item, idx, 'quantity')" />
  114 + <uni-easyinput type="digit" v-model="item.quantity" placeholder="请输入数量kg"
  115 + :inputBorder="false"
  116 + @input="onNonNegativeNumberInput($event, item, idx, 'quantity')"
  117 + @blur="onNonNegativeNumberBlur(item, idx, 'quantity')" />
100 118 </template>
101 119 </uni-list-item>
102 120 <uni-list-item v-if="item.showSalesPrice" title="销售价格">
103 121 <template v-slot:footer>
104   - <uni-easyinput type="digit" v-model="item.salesPrice" placeholder="请输入销售价格" :inputBorder="false"
105   - @input="onNonNegativeNumberInput($event, item, idx, 'salesPrice')" @blur="onNonNegativeNumberBlur(item, idx, 'salesPrice')" />
  122 + <uni-easyinput type="digit" v-model="item.salesPrice" placeholder="请输入销售价格"
  123 + :inputBorder="false"
  124 + @input="onNonNegativeNumberInput($event, item, idx, 'salesPrice')"
  125 + @blur="onNonNegativeNumberBlur(item, idx, 'salesPrice')" />
  126 + </template>
  127 + </uni-list-item>
  128 + <uni-list-item class="amount-item">
  129 + <template v-slot:body>
  130 + <view class="item-title"><text>包装费</text></view>
  131 + </template>
  132 + <template v-slot:footer>
  133 + <view class="amount-row">
  134 + <uni-easyinput type="digit" v-model="item.packagingFee" placeholder="0.00"
  135 + :inputBorder="false"
  136 + @input="onNonNegativeNumberInput($event, item, idx, 'packagingFee')"
  137 + @blur="onNonNegativeNumberBlur(item, idx, 'packagingFee')" />
  138 + <text class="unit">元</text>
  139 + </view>
106 140 </template>
107 141 </uni-list-item>
108 142 <uni-list-item title="发货日期">
109 143 <template v-slot:footer>
110   - <uni-datetime-picker type="date" v-model="item.deliveryDate" />
  144 + <uni-datetime-picker type="date" v-model="item.deliveryDate" :start="minDeliveryDate"
  145 + @change="onDeliveryChange($event, item, idx)" />
111 146 </template>
112 147 </uni-list-item>
113 148 <uni-list-item title="考核超协">
... ... @@ -167,10 +202,12 @@
167 202 <!-- showSalesPrice 判断是否显示 -->
168 203 <view class="row" v-if="item.showSalesPrice"><text class="label">销售价格</text><text class="value">{{
169 204 item.salesPrice }}</text></view>
  205 + <view class="row"><text class="label">包装费</text><text class="value">{{
  206 + item.packagingFee }}</text></view>
170 207 <view class="row"><text class="label">发货日期</text><text class="value">{{ item.deliveryDate }}</text>
171 208 </view>
172 209 <view class="row"><text class="label">考核超协</text><text class="value">{{ item.assessmentExceedsAgreement
173   - }}</text></view>
  210 + }}</text></view>
174 211 </view>
175 212 <view class="view-total">
176 213 <view class="head">合计</view>
... ... @@ -191,7 +228,8 @@ export default {
191 228 mode: { type: String, default: 'add' },
192 229 list: { type: Array, default: () => [] },
193 230 max: { type: Number, default: 8 },
194   - totalQuantity: { type: Number, default: 0 }
  231 + totalQuantity: { type: Number, default: 0 },
  232 + orderDate: { type: String, default: '' }
195 233 },
196 234 data() {
197 235 return {
... ... @@ -200,6 +238,21 @@ export default {
200 238 }
201 239 },
202 240 computed: {
  241 + minDeliveryDate() {
  242 + const s = this.orderDate
  243 + if (!s) return ''
  244 + const parts = String(s).split('-')
  245 + const y = Number(parts[0])
  246 + const m = Number(parts[1])
  247 + const d = Number(parts[2])
  248 + if (!y || !m || !d) return ''
  249 + const dt = new Date(y, m - 1, d)
  250 + dt.setDate(dt.getDate() + 1)
  251 + const yy = dt.getFullYear()
  252 + const mm = String(dt.getMonth() + 1).padStart(2, '0')
  253 + const dd = String(dt.getDate()).padStart(2, '0')
  254 + return `${yy}/${mm}/${dd}`
  255 + }
203 256 },
204 257 watch: {
205 258 items: {
... ... @@ -247,7 +300,7 @@ export default {
247 300 assessmentExceedsAgreement: ''
248 301 }
249 302 },
250   -
  303 +
251 304 onAdd() {
252 305 if (this.items.length >= this.max) return uni.showToast({ title: `最多添加${this.max}个`, icon: 'none' })
253 306 const obj = this.defaultItem()
... ... @@ -307,6 +360,29 @@ export default {
307 360 },
308 361 toggleViewCollapse() {
309 362 this.collapsedView = !this.collapsedView
  363 + },
  364 + onDeliveryChange(e, item, idx) {
  365 + const getStr = (x) => {
  366 + if (x && x.detail && x.detail.value !== undefined) return x.detail.value
  367 + if (typeof x === 'string') return x
  368 + return item && item.deliveryDate ? item.deliveryDate : ''
  369 + }
  370 + const val = getStr(e)
  371 + if (!val || !this.orderDate) return
  372 + const parse = (s) => {
  373 + const p = String(s).replace(/\//g, '-').split('-')
  374 + const y = Number(p[0])
  375 + const m = Number(p[1])
  376 + const d = Number(p[2])
  377 + return new Date(y, m - 1, d)
  378 + }
  379 + const sel = parse(val)
  380 + const ord = parse(this.orderDate)
  381 + if (!(sel > ord)) {
  382 + item.deliveryDate = ''
  383 + this.$set(this.items, idx, { ...item })
  384 + uni.showToast({ title: '发货日期必须大于订货日期', icon: 'none' })
  385 + }
310 386 }
311 387 }
312 388 }
... ...
... ... @@ -29,11 +29,12 @@
29 29 <view class="row"><text class="label">价格表编号</text><text class="value">{{ form.priceListNo }}</text></view>
30 30 <view class="row"><text class="label">开票情况</text><text class="value">{{ form.invoicingStatus }}</text></view>
31 31 <view class="row"><text class="label">运费</text><text class="value">{{ form.shippingCost }}</text></view>
32   - <view class="row"><text class="label">包装费</text><text class="value">{{ form.packagingFee }}</text></view>
33 32 <view class="row"><text class="label">执行标准</text><text class="value">{{ getDicName('APPLICABLE_STANDARD',
34 33 form.executionStandard, dicOptions.APPLICABLE_STANDARD) }}</text></view>
35 34 <view v-if="form.executionStandard === 'OTHER'" class="row"><text class="label">标准</text><text class="value">{{
36 35 form.executionStandardRemarks }}</text></view>
  36 + <view class="row"><text class="label">变更说明</text><text class="value">{{
  37 + form.changeDescription }}</text></view>
37 38 </view>
38 39
39 40 <view class="title-header">
... ...
... ... @@ -39,7 +39,7 @@
39 39 <view class="item-title"><text class="required">*</text><text>生产厂</text></view>
40 40 </template>
41 41 </uni-list-item>
42   - <ProductRel mode="add" :orderDateBase="form.orderDate" @change="onProductsChange" :options="productList" />
  42 + <ProductRel mode="add" :deliveryDate="form.orderDate" :deliveryDateBase="form.deliveryDate" @change="onProductsChange" :options="productList" />
43 43 <uni-list-item title="合计人民币金额(大写)">
44 44 <template v-slot:footer>
45 45 <uni-easyinput v-model="form.totalAmountCapital" placeholder="自动计算" :inputBorder="false" disabled />
... ... @@ -92,33 +92,25 @@
92 92 :inputBorder="false" />
93 93 </template>
94 94 </uni-list-item>
95   - <view class="group">
96   - <view class="group-title">特别条款要求</view>
97   - <view class="radio-list">
98   - <view v-for="(opt, i) in specialTermsList" :key="'cr-' + i" class="radio-item"
99   - @click="onRadioSelect('specialTerms', 'specialTermsName', opt)">
100   - <view :class="['radio', { checked: form.specialTerms === opt.value }]" />
101   - <text class="label">{{ opt.label }}</text>
102   - </view>
103   - </view>
104   - </view>
105   - <view class="group">
106   - <view class="group-title">执行标准</view>
107   - <view class="radio-list">
108   - <view v-for="(opt, i) in executionStandardList" :key="'es-' + i" class="radio-item"
109   - @click="onRadioSelect('executionStandard', 'executionStandardName', opt)">
110   - <view :class="['radio', { checked: form.executionStandard === opt.value }]" />
111   - <text class="label">{{ opt.label }}</text>
112   - </view>
113   - </view>
114   - </view>
  95 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  96 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  97 + <template v-slot:body>
  98 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  99 + </template>
  100 + </uni-list-item>
  101 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  102 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  103 + <template v-slot:body>
  104 + <view class="item-title"><text>执行标准</text></view>
  105 + </template>
  106 + </uni-list-item>
115 107 <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
116 108 <template v-slot:footer>
117 109 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注"
118 110 :inputBorder="false" />
119 111 </template>
120 112 </uni-list-item>
121   - <uni-list-item title="特别说明">
  113 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
122 114 <template v-slot:footer>
123 115 <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
124 116 </template>
... ... @@ -181,23 +173,23 @@
181 173 数量
182 174 </div>
183 175 <div class="total-item-price">
184   - {{ (sumQuantity || 0).toFixed(2) }}t
  176 + {{ (totalQuantity || 0).toFixed(2) }}kg
185 177 </div>
186 178 </div>
187   - <div class="total-item">
  179 + <!-- <div class="total-item">
188 180 <div class="total-item-text">
189 181 不含税金额
190 182 </div>
191 183 <div class="total-item-price text-red">
192   - ¥{{ (sumAmountExcl || 0).toFixed(2) }}
  184 + ¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}
193 185 </div>
194   - </div>
  186 + </div> -->
195 187 <div class="total-item">
196 188 <div class="total-item-text">
197 189 总金额
198 190 </div>
199 191 <div class="total-item-price text-red">
200   - ¥{{ (sumTotal || 0).toFixed(2) }}
  192 + ¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}
201 193 </div>
202 194 </div>
203 195 </div>
... ... @@ -233,6 +225,7 @@ export default {
233 225 buyer: '',
234 226 buyerName: '',
235 227 orderDate: '',
  228 + deliveryDate: '',
236 229 designatedConsignee: '',
237 230 specialTerms: '',
238 231 specialTermsName: '',
... ... @@ -243,7 +236,7 @@ export default {
243 236 includesPackagingFeeName: '',
244 237 includesTransportFee: false,
245 238 includesTransportFeeName: '',
246   - unit: '元、公斤、元/公斤',
  239 + unit: '美元、公斤、元美/公斤',
247 240 totalAmountCapital: '',
248 241 destinationId: [],
249 242 destinationLabel: '',
... ... @@ -263,9 +256,9 @@ export default {
263 256 yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
264 257 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
265 258 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
266   - sumQuantity: 0,
267   - sumAmountExcl: 0,
268   - sumTotal: 0,
  259 + totalQuantity: 0,
  260 + // totalAmountExcludingTax: 0,
  261 + totalAmountIncludingTax: 0,
269 262 productLineList: [],
270 263 productList: [],
271 264 customerRemarks: [],
... ... @@ -365,11 +358,11 @@ export default {
365 358 onProductsChange(products) {
366 359 const list = Array.isArray(products) ? products : []
367 360 const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
368   - const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
  361 + // const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
369 362 const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
370   - this.sumQuantity = sumQ
371   - this.sumAmountExcl = sumE
372   - this.sumTotal = sumT
  363 + this.totalQuantity = sumQ
  364 + // this.totalAmountExcludingTax = sumE
  365 + this.totalAmountIncludingTax = sumT
373 366 this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
374 367 this.productLineList = list
375 368 },
... ... @@ -445,6 +438,10 @@ export default {
445 438 setSheet('生产厂', opts)
446 439 } else if (field === 'supplier') {
447 440 setSheet('供方', this.supplierList)
  441 + } else if (field === 'specialTerms') {
  442 + setSheet('特别条款要求', this.specialTermsList)
  443 + } else if (field === 'executionStandard') {
  444 + setSheet('执行标准', this.executionStandardList)
448 445 } else if (field === 'includesPackagingFee') {
449 446 setSheet('单价中是否已包含包装费', this.yesNoList)
450 447 } else if (field === 'includesTransportFee') {
... ... @@ -515,9 +512,9 @@ export default {
515 512 ...formForSubmit,
516 513 destination,
517 514 type: 'INTL_STD_CONTRACT',
518   - sumQuantity: this.sumQuantity,
519   - sumAmountExcl: this.sumAmountExcl,
520   - sumTotal: this.sumTotal,
  515 + totalQuantity: this.totalQuantity,
  516 + // totalAmountExcludingTax: this.totalAmountExcludingTax,
  517 + totalAmountIncludingTax: this.totalAmountIncludingTax,
521 518 contractDistributorLineList: lines
522 519 })
523 520 console.log('onSubmit__payload', payload)
... ... @@ -536,18 +533,31 @@ export default {
536 533 { key: 'supplier', label: '供方' },
537 534 { key: 'buyer', label: '需方' },
538 535 { key: 'orderDate', label: '订货日期' },
  536 + { key: 'unit', label: '单位' },
539 537 { key: 'workshopId', label: '生产厂' },
  538 + { key: 'specialTerms', label: '特别条款要求' },
540 539 ]
541 540 for (const it of checks) {
542 541 const val = this.form[it.key]
543 542 const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
544 543 if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
545 544 }
546   - if (!Array.isArray(this.productLineList) || this.productLineList.length === 0) {
  545 + const list = Array.isArray(this.productLineList) ? this.productLineList : []
  546 + if (list.length === 0) {
547 547 uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
548 548 }
549   - for (const [idx, it] of this.productLineList.entries()) {
550   - if (!it.productName || !it.quantity || !it.unitPrice) {
  549 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  550 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  551 + for (const [idx, it] of list.entries()) {
  552 + if (
  553 + strEmpty(it.productName) ||
  554 + strEmpty(it.industry) ||
  555 + strEmpty(it.quality) ||
  556 + strEmpty(it.brand) ||
  557 + numEmpty(it.quantity) ||
  558 + numEmpty(it.unitPrice) ||
  559 + strEmpty(it.deliveryDate)
  560 + ) {
551 561 uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
552 562 }
553 563 }
... ... @@ -575,7 +585,7 @@ export default {
575 585 color: rgba(0, 0, 0, 0.6);
576 586 line-height: 32rpx;
577 587 width: 240rpx;
578   - padding: 24rpx 0;
  588 + padding: 12rpx 0;
579 589 }
580 590 .total-item-price {
581 591 font-weight: 600;
... ... @@ -597,7 +607,7 @@ export default {
597 607
598 608 .scroll {
599 609 flex: 1;
600   - padding: 12rpx 0 480rpx !important;
  610 + padding: 12rpx 0 392rpx !important;
601 611 }
602 612
603 613 .footer {
... ...
... ... @@ -211,12 +211,12 @@ export default {
211 211 const t = this.detail.standardApproved || false
212 212 const e = this.detail.standardShowExamine || false
213 213 return [
214   - { ...this.buttons[0], visible: (s === 'DRAFT') },
215   - { ...this.buttons[1], visible: (s === 'DRAFT') },
216   - { ...this.buttons[2], visible: (s !== 'DELETED' && t !== 'AUDIT' && t !== 'PASS') },
217   - { ...this.buttons[3], visible: (s === 'STANDARD') },
218   - { ...this.buttons[4], visible: (s === 'STANDARD' && e && t === 'AUDIT') },
219   - { ...this.buttons[5], visible: (s === 'STANDARD') }
  214 + { ...this.buttons[0], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:foreign-trade-standard-contract:modifyx')) },
  215 + { ...this.buttons[1], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:foreign-trade-standard-contract:delete')) },
  216 + { ...this.buttons[2], visible: (s !== 'DELETED' && t !== 'AUDIT' && t !== 'PASS' && this.$auth.hasPermi('contract-manage:foreign-trade-standard-contract:upload')) },
  217 + { ...this.buttons[3], visible: (s === 'STANDARD' && this.$auth.hasPermi('contract-manage:foreign-trade-standard-contract:upload-seal')) },
  218 + { ...this.buttons[4], visible: (s === 'STANDARD' && e && t === 'AUDIT' && this.$auth.hasPermi('contract-manage:foreign-trade-standard-contract:approve')) },
  219 + { ...this.buttons[5], visible: (s === 'STANDARD' && this.$auth.hasPermi('contract-manage:foreign-trade-standard-contract:review')) }
220 220 ]
221 221 }
222 222 },
... ...
... ... @@ -14,7 +14,7 @@
14 14 @input="onSearchInput"
15 15 />
16 16 <view class="tool-icons">
17   - <image class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
  17 + <image v-if="$auth.hasPermi('contract-manage:foreign-trade-standard-contract:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
18 18 <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
19 19 </view>
20 20 </view>
... ...
... ... @@ -40,9 +40,7 @@
40 40 <uni-easyinput v-model="form.unit" :inputBorder="false" disabled />
41 41 </template>
42 42 </uni-list-item>
43   -
44   - <ProductRel mode="add" :orderDateBase="form.orderDate" :list="productLineList" @change="onProductsChange" :options="productList" />
45   -
  43 + <ProductRel mode="add" :deliveryDateBase="form.deliveryDate" :deliveryDate="form.orderDate" :list="productLineList" @change="onProductsChange" :options="productList" />
46 44 <uni-list-item title="合计人民币金额(大写)">
47 45 <template v-slot:footer>
48 46 <uni-easyinput v-model="form.totalAmountCapital" placeholder="自动计算" :inputBorder="false"
... ... @@ -98,34 +96,25 @@
98 96 :inputBorder="false" />
99 97 </template>
100 98 </uni-list-item>
101   -
102   - <view class="group">
103   - <view class="group-title">特别条款要求</view>
104   - <view class="radio-list">
105   - <view v-for="(opt, i) in specialTermsList" :key="'cr-' + i" class="radio-item"
106   - @click="onRadioSelect('specialTerms', 'specialTermsName', opt)">
107   - <view :class="['radio', { checked: form.specialTerms === opt.value }]" />
108   - <text class="label">{{ opt.label }}</text>
109   - </view>
110   - </view>
111   - </view>
112   - <view class="group">
113   - <view class="group-title">执行标准</view>
114   - <view class="radio-list">
115   - <view v-for="(opt, i) in executionStandardList" :key="'es-' + i" class="radio-item"
116   - @click="onRadioSelect('executionStandard', 'executionStandardName', opt)">
117   - <view :class="['radio', { checked: form.executionStandard === opt.value }]" />
118   - <text class="label">{{ opt.label }}</text>
119   - </view>
120   - </view>
121   - </view>
  99 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  100 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  101 + <template v-slot:body>
  102 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  103 + </template>
  104 + </uni-list-item>
  105 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  106 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  107 + <template v-slot:body>
  108 + <view class="item-title"><text>执行标准</text></view>
  109 + </template>
  110 + </uni-list-item>
122 111 <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
123 112 <template v-slot:footer>
124 113 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注"
125 114 :inputBorder="false" />
126 115 </template>
127 116 </uni-list-item>
128   - <uni-list-item title="特别说明">
  117 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
129 118 <template v-slot:footer>
130 119 <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
131 120 </template>
... ... @@ -177,15 +166,15 @@
177 166 <div class="total-text">合计</div>
178 167 <div class="total-item">
179 168 <div class="total-item-text">数量</div>
180   - <div class="total-item-price">{{ (sumQuantity || 0).toFixed(2) }}t</div>
  169 + <div class="total-item-price">{{ (totalQuantity || 0).toFixed(2) }}kg</div>
181 170 </div>
182   - <div class="total-item">
  171 + <!-- <div class="total-item">
183 172 <div class="total-item-text">不含税金额</div>
184   - <div class="total-item-price text-red">¥{{ (sumAmountExcl || 0).toFixed(2) }}</div>
185   - </div>
  173 + <div class="total-item-price text-red">¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}</div>
  174 + </div> -->
186 175 <div class="total-item">
187 176 <div class="total-item-text">总金额</div>
188   - <div class="total-item-price text-red">¥{{ (sumTotal || 0).toFixed(2) }}</div>
  177 + <div class="total-item-price text-red">¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}</div>
189 178 </div>
190 179 </div>
191 180 <button class="btn submit" type="primary" @click="onSubmit">保存</button>
... ... @@ -223,6 +212,7 @@ export default {
223 212 workshopId: '',
224 213 workshopName: '',
225 214 orderDate: '',
  215 + deliveryDate: '',
226 216 designatedConsignee: '',
227 217 specialTerms: '',
228 218 specialTermsName: '',
... ... @@ -233,7 +223,7 @@ export default {
233 223 includesPackagingFeeName: '',
234 224 includesTransportFee: false,
235 225 includesTransportFeeName: '',
236   - unit: '元、公斤、元/公斤',
  226 + unit: '美元、公斤、美元/公斤',
237 227 totalAmountCapital: '',
238 228 depositInfo: '',
239 229 packagingRequirements: '',
... ... @@ -256,9 +246,9 @@ export default {
256 246 yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
257 247 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
258 248 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
259   - sumQuantity: 0,
260   - sumAmountExcl: 0,
261   - sumTotal: 0,
  249 + totalQuantity: 0,
  250 + // totalAmountExcludingTax: 0,
  251 + totalAmountIncludingTax: 0,
262 252 productLineList: [],
263 253 newProductLineList: [],
264 254 productList: []
... ... @@ -347,11 +337,11 @@ export default {
347 337 const list = Array.isArray(products) ? products : []
348 338 this.newProductLineList = list
349 339 const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
350   - const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
  340 + // const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
351 341 const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
352   - this.sumQuantity = sumQ
353   - this.sumAmountExcl = sumE
354   - this.sumTotal = sumT
  342 + this.totalQuantity = sumQ
  343 + // this.totalAmountExcludingTax = sumE
  344 + this.totalAmountIncludingTax = sumT
355 345 this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
356 346 },
357 347 async loadSuppliers() {
... ... @@ -399,6 +389,10 @@ export default {
399 389 setSheet('生产厂', opts)
400 390 } else if (field === 'supplier') {
401 391 setSheet('供方', this.supplierList)
  392 + } else if (field === 'specialTerms') {
  393 + setSheet('特别条款要求', this.specialTermsList)
  394 + } else if (field === 'executionStandard') {
  395 + setSheet('执行标准', this.executionStandardList)
402 396 } else if (field === 'includesPackagingFee') {
403 397 setSheet('单价中是否已包含包装费', this.yesNoList)
404 398 } else if (field === 'includesTransportFee') {
... ... @@ -443,18 +437,32 @@ export default {
443 437 { key: 'supplier', label: '供方' },
444 438 { key: 'buyer', label: '需方' },
445 439 { key: 'orderDate', label: '订货日期' },
  440 + { key: 'unit', label: '单位' },
446 441 { key: 'workshopId', label: '生产厂' },
  442 + { key: 'specialTerms', label: '特别条款要求' },
447 443 ]
448 444 for (const it of checks) {
449 445 const val = this.form[it.key]
450 446 const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
451 447 if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
452 448 }
453   - if (!Array.isArray(this.productLineList) || this.productLineList.length === 0) {
  449 + const list = Array.isArray(this.newProductLineList) ? this.newProductLineList : []
  450 + if (list.length === 0) {
454 451 uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
455 452 }
456   - for (const [idx, it] of this.productLineList.entries()) {
457   - if (!it.productName || !it.quantity || !it.unitPrice) {
  453 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  454 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  455 + for (const [idx, it] of list.entries()) {
  456 + console.log('it111', it)
  457 + if (
  458 + strEmpty(it.productName) ||
  459 + strEmpty(it.industry) ||
  460 + strEmpty(it.quality) ||
  461 + strEmpty(it.brand) ||
  462 + numEmpty(it.quantity) ||
  463 + numEmpty(it.unitPrice) ||
  464 + strEmpty(it.deliveryDate)
  465 + ) {
458 466 uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
459 467 }
460 468 }
... ... @@ -479,25 +487,25 @@ export default {
479 487 return out
480 488 }
481 489 const lines = (this.newProductLineList || []).map(it => clean(it))
482   - const { destinationLabel, destinationId, ...formForSubmit } = this.form;
483   - const destination = destinationId && destinationId.length > 0 ? destinationId[destinationId.length - 1] : '';
484   - const payload = clean({
485   - ...formForSubmit,
486   - id: this.form.id,
487   - destination,
488   - type: 'INTL_STD_CONTRACT',
489   - sumQuantity: this.sumQuantity,
490   - sumAmountExcl: this.sumAmountExcl,
491   - sumTotal: this.sumTotal,
492   - contractDistributorLineList: lines
493   - })
494   - try {
495   - await updateContractApi(payload)
496   - uni.showToast({ title: '保存成功', icon: 'none' })
497   - setTimeout(() => { uni.redirectTo({ url: '/pages/contract_foreign_std/index' }) }, 400)
498   - } catch (e) {
499   - uni.showToast({ title: '提交失败', icon: 'none' })
500   - }
  490 + const { destinationLabel, destinationId, ...formForSubmit } = this.form;
  491 + const destination = destinationId && destinationId.length > 0 ? destinationId[destinationId.length - 1] : '';
  492 + const payload = clean({
  493 + ...formForSubmit,
  494 + id: this.form.id,
  495 + destination,
  496 + type: 'INTL_STD_CONTRACT',
  497 + totalQuantity: this.totalQuantity,
  498 + // totalAmountExcludingTax: this.totalAmountExcludingTax,
  499 + totalAmountIncludingTax: this.totalAmountIncludingTax,
  500 + contractDistributorLineList: lines
  501 + })
  502 + try {
  503 + await updateContractApi(payload)
  504 + uni.showToast({ title: '保存成功', icon: 'none' })
  505 + setTimeout(() => { uni.redirectTo({ url: '/pages/contract_foreign_std/index' }) }, 400)
  506 + } catch (e) {
  507 + uni.showToast({ title: '提交失败', icon: 'none' })
  508 + }
501 509 }
502 510 }
503 511 }
... ... @@ -524,7 +532,7 @@ export default {
524 532 color: rgba(0, 0, 0, 0.6);
525 533 line-height: 32rpx;
526 534 width: 240rpx;
527   - padding: 24rpx 0;
  535 + padding: 12rpx 0;
528 536 }
529 537
530 538 .total-item-price {
... ... @@ -547,7 +555,7 @@ export default {
547 555
548 556 .scroll {
549 557 flex: 1;
550   - padding: 12rpx 0 480rpx !important;
  558 + padding: 12rpx 0 392rpx !important;
551 559 }
552 560
553 561 .footer {
... ...
... ... @@ -53,53 +53,53 @@
53 53 <uni-easyinput v-model="item.quality" :inputBorder="false" placeholder="请输入品质" />
54 54 </template>
55 55 </uni-list-item>
56   - <uni-list-item title="厚度">
  56 + <uni-list-item title="厚度(mm)">
57 57 <template v-slot:footer>
58   - <uni-easyinput v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" />
  58 + <uni-easyinput type="digit" v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" @input="onNonNegativeInput(idx, 'thickness')" @blur="onNonNegativeBlur(idx, 'thickness', 2)" />
59 59 </template>
60 60 </uni-list-item>
61   - <uni-list-item title="厚度公差(单项+)">
  61 + <uni-list-item title="厚度公差上限(mm)">
62 62 <template v-slot:footer>
63   - <uni-easyinput v-model="item.thicknessTolPos" :inputBorder="false"
64   - placeholder="请输入厚度公差(单项+)" />
  63 + <uni-easyinput type="digit" v-model="item.thicknessTolPos" :inputBorder="false"
  64 + placeholder="请输入厚度公差上限" @input="onNonNegativeInput(idx, 'thicknessTolPos')" @blur="onNonNegativeBlur(idx, 'thicknessTolPos', 2)" />
65 65 </template>
66 66 </uni-list-item>
67   - <uni-list-item title="厚度公差(单项-)">
  67 + <uni-list-item title="厚度公差下限(mm)">
68 68 <template v-slot:footer>
69   - <uni-easyinput v-model="item.thicknessTolNeg" :inputBorder="false"
70   - placeholder="请输入厚度公差(单项-)" />
  69 + <uni-easyinput type="digit" v-model="item.thicknessTolNeg" :inputBorder="false"
  70 + placeholder="请输入厚度公差下限" @input="onNonNegativeInput(idx, 'thicknessTolNeg')" @blur="onNonNegativeBlur(idx, 'thicknessTolNeg', 2)" />
71 71 </template>
72 72 </uni-list-item>
73   - <uni-list-item title="宽度">
  73 + <uni-list-item title="宽度(mm)">
74 74 <template v-slot:footer>
75   - <uni-easyinput v-model="item.width" :inputBorder="false" placeholder="请输入宽度" />
  75 + <uni-easyinput type="digit" v-model="item.width" :inputBorder="false" placeholder="请输入宽度" @input="onNonNegativeInput(idx, 'width')" @blur="onNonNegativeBlur(idx, 'width', 2)" />
76 76 </template>
77 77 </uni-list-item>
78   - <uni-list-item title="宽度公差(单项+)">
  78 + <uni-list-item title="宽度公差上限(mm)">
79 79 <template v-slot:footer>
80   - <uni-easyinput v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差(单项+)" />
  80 + <uni-easyinput type="digit" v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差上限" @input="onNonNegativeInput(idx, 'widthTolPos')" @blur="onNonNegativeBlur(idx, 'widthTolPos', 2)" />
81 81 </template>
82 82 </uni-list-item>
83   - <uni-list-item title="宽度公差(单项-)">
  83 + <uni-list-item title="宽度公差下限(mm)">
84 84 <template v-slot:footer>
85   - <uni-easyinput v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差(单项-)" />
  85 + <uni-easyinput type="digit" v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差下限" @input="onNonNegativeInput(idx, 'widthTolNeg')" @blur="onNonNegativeBlur(idx, 'widthTolNeg', 2)" />
86 86 </template>
87 87 </uni-list-item>
88   - <uni-list-item title="长度">
  88 + <uni-list-item title="长度(mm)">
89 89 <template v-slot:footer>
90   - <uni-easyinput v-model="item.length" :inputBorder="false" placeholder="请输入长度" />
  90 + <uni-easyinput type="digit" v-model="item.length" :inputBorder="false" placeholder="请输入长度" @input="onNonNegativeInput(idx, 'length')" @blur="onNonNegativeBlur(idx, 'length', 2)" />
91 91 </template>
92 92 </uni-list-item>
93   - <uni-list-item title="长度公差(单项+)">
  93 + <uni-list-item title="长度公差上限(mm)">
94 94 <template v-slot:footer>
95   - <uni-easyinput v-model="item.lengthTolPos" :inputBorder="false"
96   - placeholder="请输入长度公差(单项+)" />
  95 + <uni-easyinput type="digit" v-model="item.lengthTolPos" :inputBorder="false"
  96 + placeholder="请输入长度公差上限" @input="onNonNegativeInput(idx, 'lengthTolPos')" @blur="onNonNegativeBlur(idx, 'lengthTolPos', 2)" />
97 97 </template>
98 98 </uni-list-item>
99   - <uni-list-item title="长度公差(单项-)">
  99 + <uni-list-item title="长度公差下限(mm)">
100 100 <template v-slot:footer>
101   - <uni-easyinput v-model="item.lengthTolNeg" :inputBorder="false"
102   - placeholder="请输入长度公差(单项-)" />
  101 + <uni-easyinput type="digit" v-model="item.lengthTolNeg" :inputBorder="false"
  102 + placeholder="请输入长度公差下限" @input="onNonNegativeInput(idx, 'lengthTolNeg')" @blur="onNonNegativeBlur(idx, 'lengthTolNeg', 2)" />
103 103 </template>
104 104 </uni-list-item>
105 105 <uni-list-item title="状态">
... ... @@ -109,12 +109,12 @@
109 109 </uni-list-item>
110 110 <uni-list-item title="数量">
111 111 <template v-slot:footer>
112   - <uni-easyinput v-model="item.quantity" type="number" :inputBorder="false" placeholder="请输入数量" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'quantity', 0)" />
  112 + <uni-easyinput v-model="item.quantity" type="digit" :inputBorder="false" placeholder="请输入数量kg" @input="onNonNegativeInput(idx, 'quantity')" @blur="onNonNegativeBlur(idx, 'quantity', 2)" />
113 113 </template>
114 114 </uni-list-item>
115 115 <uni-list-item title="单价">
116 116 <template v-slot:footer>
117   - <uni-easyinput v-model="item.unitPrice" disabled type="number" :inputBorder="false" placeholder="请输入单价" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'unitPrice', 0)" />
  117 + <uni-easyinput v-model="item.unitPrice" type="digit" :inputBorder="false" placeholder="请输入销售价格" @input="onNonNegativeInput(idx, 'unitPrice')" @blur="onNonNegativeBlur(idx, 'unitPrice', 2)" />
118 118 </template>
119 119 </uni-list-item>
120 120 <uni-list-item title="外贸加工费">
... ... @@ -122,11 +122,11 @@
122 122 <uni-easyinput v-model="item.processingFee" type="number" :inputBorder="false" placeholder="请输入外贸加工费" />
123 123 </template>
124 124 </uni-list-item>
125   - <uni-list-item title="不含税金额">
  125 + <!-- <uni-list-item title="不含税金额">
126 126 <template v-slot:footer>
127 127 <uni-easyinput v-model="item.amountExcludingTax" type="number" :inputBorder="false" disabled placeholder="自动计算" />
128 128 </template>
129   - </uni-list-item>
  129 + </uni-list-item> -->
130 130 <uni-list-item title="总金额">
131 131 <template v-slot:footer>
132 132 <uni-easyinput v-model="item.totalAmount" type="number" :inputBorder="false" disabled placeholder="自动计算" />
... ... @@ -134,7 +134,7 @@
134 134 </uni-list-item>
135 135 <uni-list-item title="发货日期">
136 136 <template v-slot:footer>
137   - <uni-datetime-picker type="date" v-model="item.orderDate" @change="onDateChange(idx, $event)" />
  137 + <uni-datetime-picker :start="minDeliveryDate" type="date" v-model="item.deliveryDate" @change="onDateChange(idx, $event)" />
138 138 </template>
139 139 </uni-list-item>
140 140 </uni-list>
... ... @@ -156,18 +156,41 @@
156 156 <view class="row"><text class="label">行业</text><text class="value">{{ item.industry }}</text></view>
157 157 <view class="row"><text class="label">牌号</text><text class="value">{{ item.brand }}</text></view>
158 158 <view class="row"><text class="label">品质</text><text class="value">{{ item.quality }}</text></view>
159   - <view class="row"><text class="label">规格</text><text class="value">{{ item.specDisplay }}</text></view>
  159 + <!-- 厚(公差) * 宽(公差) * 长(公差) -->
  160 + <view class="row row-spec"><text class="label">规格(mm)</text>
  161 + <view class="value value-spec">
  162 + <view v-if="item.thickness" class="value-spec_val">{{ item.thickness }}</view>
  163 + <view v-if="item.thickness" class="value-spec_box">
  164 + <view v-if="item.thicknessTolPos" class="value-spec_box_1">+{{ item.thicknessTolPos }}
  165 + </view>
  166 + <view v-if="item.thicknessTolNeg" class="value-spec_box_2">-{{ item.thicknessTolNeg }}
  167 + </view>
  168 + </view>
  169 + <view v-if="item.width" class="value-spec_val p12">*</view>
  170 + <view v-if="item.width" class="value-spec_val">{{ item.width }}</view>
  171 + <view v-if="item.width" class="value-spec_box">
  172 + <view v-if="item.widthTolPos" class="value-spec_box_1">+{{ item.widthTolPos }}</view>
  173 + <view v-if="item.widthTolNeg" class="value-spec_box_2">-{{ item.widthTolNeg }}</view>
  174 + </view>
  175 + <view v-if="item.length" class="value-spec_val p12">*</view>
  176 + <view v-if="item.length" class="value-spec_val">{{ item.length }}</view>
  177 + <view v-if="item.length" class="value-spec_box">
  178 + <view v-if="item.lengthTolPos" class="value-spec_box_1">+{{ item.lengthTolPos }}</view>
  179 + <view v-if="item.lengthTolNeg" class="value-spec_box_2">-{{ item.lengthTolNeg }}</view>
  180 + </view>
  181 + </view>
  182 + </view>
160 183 <view class="row"><text class="label">状态</text><text class="value">{{ item.status }}</text></view>
161 184 <view class="row"><text class="label">数量</text><text class="value">{{ item.quantity }}</text></view>
162 185 <view class="row"><text class="label">单价</text><text class="value">{{ formatCurrency(item.unitPrice)
163 186 }}</text>
164 187 </view>
165   - <view class="row"><text class="label">不含税金额</text><text class="value">{{
  188 + <!-- <view class="row"><text class="label">不含税金额</text><text class="value">{{
166 189 formatCurrency(item.amountExcludingTax)
167   - }}</text></view>
  190 + }}</text></view> -->
168 191 <view class="row"><text class="label">总金额</text><text class="value">{{ formatCurrency(item.totalAmount)
169 192 }}</text></view>
170   - <view class="row"><text class="label">发货日期</text><text class="value">{{ item.orderDate }}</text></view>
  193 + <view class="row"><text class="label">发货日期</text><text class="value">{{ item.deliveryDate }}</text></view>
171 194 </view>
172 195 </view>
173 196 <SingleSelectSheet :visible.sync="sheet.visible" :title="sheet.title" :options="sheet.options" v-model="sheet.value" @confirm="onProductConfirm" />
... ... @@ -181,7 +204,8 @@ export default {
181 204 mode: { type: String, default: 'add' },
182 205 list: { type: Array, default: () => [] },
183 206 max: { type: Number, default: 8 },
184   - orderDateBase: { type: String, default: '' },
  207 + deliveryDateBase: { type: String, default: '' },
  208 + deliveryDate: { type: String, default: '' },
185 209 options: { type: Array, default: () => [] }
186 210 },
187 211 components: { SingleSelectSheet },
... ... @@ -199,6 +223,21 @@ export default {
199 223 label: o.label != null ? o.label : (o.text != null ? o.text : (o.name != null ? o.name : '')),
200 224 value: o.value != null ? o.value : (o.id != null ? o.id : o.productId)
201 225 }))
  226 + },
  227 + minDeliveryDate() {
  228 + const s = this.deliveryDate
  229 + if (!s) return ''
  230 + const parts = String(s).split('-')
  231 + const y = Number(parts[0])
  232 + const m = Number(parts[1])
  233 + const d = Number(parts[2])
  234 + if (!y || !m || !d) return ''
  235 + const dt = new Date(y, m - 1, d)
  236 + dt.setDate(dt.getDate() + 1)
  237 + const yy = dt.getFullYear()
  238 + const mm = String(dt.getMonth() + 1).padStart(2, '0')
  239 + const dd = String(dt.getDate() - 1).padStart(2, '0')
  240 + return `${yy}/${mm}/${dd}`
202 241 }
203 242 },
204 243 watch: {
... ... @@ -223,10 +262,18 @@ export default {
223 262 },
224 263 methods: {
225 264 defaultItem() {
226   - return { productId: '', productName: '', industry: '', brand: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', status: '', quantity: '', unitPrice: '', processingFee: undefined, amountExcludingTax: 0, totalAmount: 0, orderDate: '' }
  265 + return { productId: '', productName: '', industry: '', brand: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '',processingFee: undefined, status: '', quantity: '', unitPrice: '', totalAmount: 0, deliveryDate: '' }
227 266 },
228   - onImmediateChange(idx) {
229   - this.$nextTick(() => this.recalculate(idx))
  267 + onNonNegativeInput(idx, field) {
  268 + const it = this.items[idx]
  269 + if (!it) return
  270 + let v = String(it[field] != null ? it[field] : '')
  271 + v = v.replace(/[^0-9.]/g, '')
  272 + v = v.replace(/(\..*)\./g, '$1')
  273 + if (v.startsWith('.')) v = '0' + v
  274 + it[field] = v
  275 + this.$set(this.items, idx, it)
  276 + if (field === 'quantity' || field === 'unitPrice') this.$nextTick(() => this.recalculate(idx))
230 277 },
231 278 toNumber(val) {
232 279 if (typeof val === 'number') return isNaN(val) ? 0 : val
... ... @@ -239,21 +286,21 @@ export default {
239 286 const m = Math.pow(10, digits)
240 287 return Math.round(n * m) / m
241 288 },
242   - onNumberBlur(idx, field, digits) {
  289 + onNonNegativeBlur(idx, field, digits) {
243 290 const it = this.items[idx]
244 291 if (!it) return
245 292 const raw = it[field]
246   - // 如果为空则保持为空,不自动置为0,仅重新计算依赖字段
247 293 if (raw === '' || raw === null || raw === undefined) {
248 294 this.$set(this.items, idx, it)
249   - this.recalculate(idx)
  295 + if (field === 'quantity' || field === 'unitPrice') this.recalculate(idx)
250 296 return
251 297 }
252   - const num = this.toNumber(raw)
  298 + let num = this.toNumber(raw)
  299 + if (isNaN(num) || num < 0) num = 0
253 300 const rounded = this.round(num, digits)
254 301 it[field] = rounded
255 302 this.$set(this.items, idx, it)
256   - this.recalculate(idx)
  303 + if (field === 'quantity' || field === 'unitPrice') this.recalculate(idx)
257 304 },
258 305 formatCurrency(val) {
259 306 if (val == null || val === '') return ''
... ... @@ -291,8 +338,8 @@ export default {
291 338 const qty = this.toNumber(it.quantity)
292 339 const price = this.toNumber(it.unitPrice)
293 340 const total = this.round(qty * price, 2)
294   - const excl = this.round(total / (1 + TAX_RATE), 2)
295   - const next = { ...it, totalAmount: total, amountExcludingTax: excl }
  341 + // const excl = this.round(total / (1 + TAX_RATE), 2)
  342 + const next = { ...it, totalAmount: total }
296 343 this.$set(this.items, idx, next)
297 344 },
298 345 recalculateAll() {
... ... @@ -324,15 +371,15 @@ export default {
324 371 onDateChange(idx, e) {
325 372 const it = this.items[idx]
326 373 if (!it) return
327   - const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.orderDate
  374 + const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.deliveryDate
328 375 const dateStr = String(val).slice(0, 10)
329   - const base = this.orderDateBase ? new Date(this.orderDateBase) : null
  376 + const base = this.deliveryDateBase ? new Date(this.deliveryDateBase) : null
330 377 const d = new Date(dateStr)
331 378 if (base && !isNaN(d.getTime()) && d.getTime() < base.getTime()) {
332 379 uni.showToast({ title: '发货日期不得早于订货日期', icon: 'none' })
333   - it.orderDate = this.orderDateBase
  380 + it.deliveryDate = this.deliveryDateBase
334 381 } else {
335   - it.orderDate = dateStr
  382 + it.deliveryDate = dateStr
336 383 }
337 384 this.$set(this.items, idx, it)
338 385 },
... ... @@ -388,12 +435,13 @@ export default {
388 435 height: 40rpx;
389 436 }
390 437
391   - .opCollapse {
392   - color: rgba(0, 0, 0, 0.6);
393   - width: 32rpx;
394   - height: 28rpx;
395   - margin-right: 16rpx;
396   - }
  438 +.opCollapse {
  439 + color: rgba(0, 0, 0, 0.6);
  440 + width: 32rpx;
  441 + height: 28rpx;
  442 + margin-right: 16rpx;
  443 + margin-top: 8rpx;
  444 +}
397 445
398 446
399 447 .block {
... ... @@ -504,8 +552,46 @@ export default {
504 552
505 553 .value {
506 554 flex: 1;
507   - text-align: right;
  555 + // text-align: right;
508 556 color: rgba(0, 0, 0, 0.9);
509 557 font-size: 28rpx;
510 558 }
  559 + .value-spec {
  560 + height: 48rpx;
  561 + display: flex;
  562 + align-items: center;
  563 + color: #000000;
  564 + // justify-content: end;
  565 + &_box {
  566 + position: relative;
  567 + width: 60rpx;
  568 + height: 48rpx;
  569 +
  570 + &_1 {
  571 + font-size: 16rpx;
  572 + position: absolute;
  573 + top: -10rpx;
  574 + left: 0;
  575 + }
  576 +
  577 + &_2 {
  578 + font-size: 16rpx;
  579 + position: absolute;
  580 + bottom: -10rpx;
  581 + left: 0;
  582 + }
  583 + }
  584 +
  585 + &_val {
  586 + font-size: 28rpx;
  587 +
  588 + &.p12 {
  589 + padding-right: 12rpx;
  590 + }
  591 + }
  592 + }
  593 + .row-spec {
  594 + height: 60rpx;
  595 + align-items: center;
  596 + }
511 597 </style>
... ...
... ... @@ -39,7 +39,7 @@
39 39 <view class="item-title"><text class="required">*</text><text>生产厂</text></view>
40 40 </template>
41 41 </uni-list-item>
42   - <ProductRel mode="add" :orderDateBase="form.orderDate" @change="onProductsChange" :options="productList" />
  42 + <ProductRel mode="add" :deliveryDate="form.orderDate" :deliveryDateBase="form.deliveryDate" @change="onProductsChange" :options="productList" />
43 43 <uni-list-item title="合计人民币金额(大写)">
44 44 <template v-slot:footer>
45 45 <uni-easyinput v-model="form.totalAmountCapital" placeholder="自动计算" :inputBorder="false" disabled />
... ... @@ -92,33 +92,25 @@
92 92 :inputBorder="false" />
93 93 </template>
94 94 </uni-list-item>
95   - <view class="group">
96   - <view class="group-title">特别条款要求</view>
97   - <view class="radio-list">
98   - <view v-for="(opt, i) in specialTermsList" :key="'cr-' + i" class="radio-item"
99   - @click="onRadioSelect('specialTerms', 'specialTermsName', opt)">
100   - <view :class="['radio', { checked: form.specialTerms === opt.value }]" />
101   - <text class="label">{{ opt.label }}</text>
102   - </view>
103   - </view>
104   - </view>
105   - <view class="group">
106   - <view class="group-title">执行标准</view>
107   - <view class="radio-list">
108   - <view v-for="(opt, i) in executionStandardList" :key="'es-' + i" class="radio-item"
109   - @click="onRadioSelect('executionStandard', 'executionStandardName', opt)">
110   - <view :class="['radio', { checked: form.executionStandard === opt.value }]" />
111   - <text class="label">{{ opt.label }}</text>
112   - </view>
113   - </view>
114   - </view>
  95 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  96 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  97 + <template v-slot:body>
  98 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  99 + </template>
  100 + </uni-list-item>
  101 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  102 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  103 + <template v-slot:body>
  104 + <view class="item-title"><text>执行标准</text></view>
  105 + </template>
  106 + </uni-list-item>
115 107 <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
116 108 <template v-slot:footer>
117 109 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注"
118 110 :inputBorder="false" />
119 111 </template>
120 112 </uni-list-item>
121   - <uni-list-item title="特别说明">
  113 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
122 114 <template v-slot:footer>
123 115 <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
124 116 </template>
... ... @@ -181,23 +173,23 @@
181 173 数量
182 174 </div>
183 175 <div class="total-item-price">
184   - {{ (sumQuantity || 0).toFixed(2) }}t
  176 + {{ (totalQuantity || 0).toFixed(2) }}kg
185 177 </div>
186 178 </div>
187   - <div class="total-item">
  179 + <!-- <div class="total-item">
188 180 <div class="total-item-text">
189 181 不含税金额
190 182 </div>
191 183 <div class="total-item-price text-red">
192   - ¥{{ (sumAmountExcl || 0).toFixed(2) }}
  184 + ¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}
193 185 </div>
194   - </div>
  186 + </div> -->
195 187 <div class="total-item">
196 188 <div class="total-item-text">
197 189 总金额
198 190 </div>
199 191 <div class="total-item-price text-red">
200   - ¥{{ (sumTotal || 0).toFixed(2) }}
  192 + ¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}
201 193 </div>
202 194 </div>
203 195 </div>
... ... @@ -233,6 +225,7 @@ export default {
233 225 buyer: '',
234 226 buyerName: '',
235 227 orderDate: '',
  228 + deliveryDate: '',
236 229 designatedConsignee: '',
237 230 specialTerms: '',
238 231 specialTermsName: '',
... ... @@ -243,7 +236,7 @@ export default {
243 236 includesPackagingFeeName: '',
244 237 includesTransportFee: false,
245 238 includesTransportFeeName: '',
246   - unit: '元、公斤、元/公斤',
  239 + unit: '美元、公斤、美元/公斤',
247 240 totalAmountCapital: '',
248 241 destinationId: [],
249 242 destinationLabel: '',
... ... @@ -263,9 +256,9 @@ export default {
263 256 yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
264 257 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
265 258 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
266   - sumQuantity: 0,
267   - sumAmountExcl: 0,
268   - sumTotal: 0,
  259 + totalQuantity: 0,
  260 + // totalAmountExcludingTax: 0,
  261 + totalAmountIncludingTax: 0,
269 262 productLineList: [],
270 263 productList: [],
271 264 customerRemarks: [],
... ... @@ -367,11 +360,11 @@ export default {
367 360 onProductsChange(products) {
368 361 const list = Array.isArray(products) ? products : []
369 362 const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
370   - const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
  363 + // const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
371 364 const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
372   - this.sumQuantity = sumQ
373   - this.sumAmountExcl = sumE
374   - this.sumTotal = sumT
  365 + this.totalQuantity = sumQ
  366 + // this.totalAmountExcludingTax = sumE
  367 + this.totalAmountIncludingTax = sumT
375 368 this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
376 369 this.productLineList = list
377 370 },
... ... @@ -447,6 +440,10 @@ export default {
447 440 setSheet('生产厂', opts)
448 441 } else if (field === 'supplier') {
449 442 setSheet('供方', this.supplierList)
  443 + } else if (field === 'specialTerms') {
  444 + setSheet('特别条款要求', this.specialTermsList)
  445 + } else if (field === 'executionStandard') {
  446 + setSheet('执行标准', this.executionStandardList)
450 447 } else if (field === 'includesPackagingFee') {
451 448 setSheet('单价中是否已包含包装费', this.yesNoList)
452 449 } else if (field === 'includesTransportFee') {
... ... @@ -517,9 +514,9 @@ export default {
517 514 ...formForSubmit,
518 515 destination,
519 516 type: 'INTL_INVENTORY_AGMT',
520   - sumQuantity: this.sumQuantity,
521   - sumAmountExcl: this.sumAmountExcl,
522   - sumTotal: this.sumTotal,
  517 + totalQuantity: this.totalQuantity,
  518 + // totalAmountExcludingTax: this.totalAmountExcludingTax,
  519 + totalAmountIncludingTax: this.totalAmountIncludingTax,
523 520 contractDistributorLineList: lines
524 521 })
525 522 console.log('onSubmit__payload', payload)
... ... @@ -538,18 +535,30 @@ export default {
538 535 { key: 'supplier', label: '供方' },
539 536 { key: 'buyer', label: '需方' },
540 537 { key: 'orderDate', label: '订货日期' },
  538 + { key: 'unit', label: '单位' },
541 539 { key: 'workshopId', label: '生产厂' },
  540 + { key: 'specialTerms', label: '特别条款要求' },
542 541 ]
543 542 for (const it of checks) {
544 543 const val = this.form[it.key]
545 544 const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
546 545 if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
547 546 }
548   - if (!Array.isArray(this.productLineList) || this.productLineList.length === 0) {
  547 + const list = Array.isArray(this.productLineList) ? this.productLineList : []
  548 + if (list.length === 0) {
549 549 uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
550 550 }
551   - for (const [idx, it] of this.productLineList.entries()) {
552   - if (!it.productName || !it.quantity || !it.unitPrice) {
  551 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  552 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  553 + for (const [idx, it] of list.entries()) {
  554 + if (
  555 + strEmpty(it.productName) ||
  556 + strEmpty(it.industry) ||
  557 + strEmpty(it.quality) ||
  558 + strEmpty(it.brand) ||
  559 + numEmpty(it.quantity) ||
  560 + strEmpty(it.deliveryDate)
  561 + ) {
553 562 uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
554 563 }
555 564 }
... ... @@ -577,7 +586,7 @@ export default {
577 586 color: rgba(0, 0, 0, 0.6);
578 587 line-height: 32rpx;
579 588 width: 240rpx;
580   - padding: 24rpx 0;
  589 + padding: 12rpx 0;
581 590 }
582 591 .total-item-price {
583 592 font-weight: 600;
... ... @@ -599,7 +608,7 @@ export default {
599 608
600 609 .scroll {
601 610 flex: 1;
602   - padding: 12rpx 0 480rpx !important;
  611 + padding: 12rpx 0 392rpx !important;
603 612 }
604 613
605 614 .footer {
... ...
... ... @@ -53,13 +53,13 @@
53 53 }}</text></view>
54 54 </view>
55 55
56   - <view class="section" v-if="status === 'STANDARD'">
  56 + <view class="section" v-if="detail.status === 'STANDARD'">
57 57 <view class="row"><text class="label">规范性合同</text><text class="value" style="color: #3D48A3;">{{
58 58 detail.standardFileName || '-' }}</text></view>
59 59 <view class="row"><text class="label">合同是否规范</text><text class="value">{{
60 60 detail.standardStandardized ? '是' : '否' }}</text></view>
61 61 </view>
62   - <view class="section" v-if="status === 'FORMAL'">
  62 + <view class="section" v-if="detail.status === 'FORMAL'">
63 63 <view class="row"><text class="label">规范性合同</text><text class="value" style="color: #3D48A3;">{{
64 64 detail.formalFileName || '-' }}</text></view>
65 65 <view class="row"><text class="label">合同是否规范</text><text class="value">{{ detail.formalStandardized
... ... @@ -265,19 +265,19 @@ export default {
265 265 const e = this.detail.showExamine || false
266 266 const f = this.detail.standardShowExamine || false
267 267 return [
268   - { ...this.buttons[0], visible: (s === 'DRAFT') }, //编辑
269   - { ...this.buttons[1], visible: (s === 'DRAFT') }, //删除
270   - { ...this.buttons[2], visible: (s === 'FORMAL' && !l) }, //锁价
271   - { ...this.buttons[3], visible: ((s === 'DRAFT' || s === 'FORMAL') && t !== 'AUDIT' && t !== 'PASS') },
272   - { ...this.buttons[4], visible: (s === 'STANDARD' && t !== 'AUDIT' && t !== 'PASS') },
273   - { ...this.buttons[5], visible: (s === 'STANDARD' && a !== 'AUDIT' && a !== 'PASS') },
274   - { ...this.buttons[6], visible: (s === 'FORMAL' && e && t === 'AUDIT') },
275   - { ...this.buttons[7], visible: (s === 'STANDARD' && e && t === 'AUDIT') },
276   - { ...this.buttons[8], visible: (s === 'STANDARD' && f && a === 'AUDIT') },
277   - { ...this.buttons[9], visible: (s === 'FORMAL' && t) },
278   - { ...this.buttons[10], visible: (s === 'STANDARD' && t) },
279   - { ...this.buttons[11], visible: (s === 'STANDARD' && a) },
280   - { ...this.buttons[12], visible: (s === 'STANDARD') },
  268 + { ...this.buttons[0], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:modify')) }, //编辑
  269 + { ...this.buttons[1], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:delete')) }, //删除
  270 + { ...this.buttons[2], visible: (s === 'FORMAL' && !l && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:lock')) }, //锁价
  271 + { ...this.buttons[3], visible: ((s === 'DRAFT' || s === 'FORMAL') && t !== 'AUDIT' && t !== 'PASS' && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:upload')) },
  272 + { ...this.buttons[4], visible: (s === 'STANDARD' && t !== 'AUDIT' && t !== 'PASS' && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:upload')) },
  273 + { ...this.buttons[5], visible: (s === 'STANDARD' && a !== 'AUDIT' && a !== 'PASS' && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:standard-upload')) },
  274 + { ...this.buttons[6], visible: (s === 'FORMAL' && e && t === 'AUDIT' && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:approve')) },
  275 + { ...this.buttons[7], visible: (s === 'STANDARD' && e && t === 'AUDIT' && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:approve')) },
  276 + { ...this.buttons[8], visible: (s === 'STANDARD' && f && a === 'AUDIT' && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:standard-approve')) },
  277 + { ...this.buttons[9], visible: (s === 'FORMAL' && t && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:review')) },
  278 + { ...this.buttons[10], visible: (s === 'STANDARD' && t && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:review')) },
  279 + { ...this.buttons[11], visible: (s === 'STANDARD' && a && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:standard-review')) },
  280 + { ...this.buttons[12], visible: (s === 'STANDARD' && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:upload-seal')) },
281 281 ]
282 282 }
283 283 },
... ...
... ... @@ -14,7 +14,7 @@
14 14 @input="onSearchInput"
15 15 />
16 16 <view class="tool-icons">
17   - <image class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
  17 + <image v-if="$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
18 18 <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
19 19 </view>
20 20 </view>
... ... @@ -61,7 +61,9 @@
61 61 <text>订单总额</text><text class="amount" :style="{ color: '#b67a76' }">{{ item.totalAmountIncludingTax ? '¥' : '' }}{{ formatAmount(item.totalAmountIncludingTax) || '-' }}</text>
62 62 </view>
63 63 <view class="info-row" v-if="item.status === 'STANDARD' || item.status === 'FORMAL'">
64   - <text>{{ item.status === 'STANDARD' ? '标准合同' : '正式合同' }}规范性审核状态</text><span class="info-status" :style="item.standardApprovedName ? getStatusCss(item.standardApprovedName) : ''">{{ item.standardApprovedName || '-' }}</span>
  64 + <text>{{ item.status === 'STANDARD' ? '标准合同' : '正式合同' }}规范性审核状态</text>
  65 + <span v-if="item.status === 'STANDARD' ? item.standardApprovedName : item.formalApprovedName" class="info-status" :style="getStatusCss(item.status === 'STANDARD' ? item.standardApprovedName : item.formalApprovedName)">{{ item.status === 'STANDARD' ? item.standardApprovedName : item.formalApprovedName }}</span>
  66 + <span v-else>-</span>
65 67 </view>
66 68 <view class="info-row">
67 69 <text>订货日期</text><text>{{ item.orderDate }}</text>
... ...
... ... @@ -108,23 +108,23 @@
108 108 数量
109 109 </div>
110 110 <div class="total-item-price">
111   - {{ (sumQuantity || 0).toFixed(2) }}t
  111 + {{ (totalQuantity || 0).toFixed(2) }}kg
112 112 </div>
113 113 </div>
114   - <div class="total-item">
  114 + <!-- <div class="total-item">
115 115 <div class="total-item-text">
116 116 不含税金额
117 117 </div>
118 118 <div class="total-item-price text-red">
119   - ¥{{ (sumAmountExcl || 0).toFixed(2) }}
  119 + ¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}
120 120 </div>
121   - </div>
  121 + </div> -->
122 122 <div class="total-item">
123 123 <div class="total-item-text">
124 124 总金额
125 125 </div>
126 126 <div class="total-item-price text-red">
127   - ¥{{ (sumTotal || 0).toFixed(2) }}
  127 + ¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}
128 128 </div>
129 129 </div>
130 130 </div>
... ... @@ -147,15 +147,15 @@ export default {
147 147 }
148 148 },
149 149 computed: {
150   - sumQuantity() {
  150 + totalQuantity() {
151 151 const qty = this.items.filter(it => it.locked).reduce((p, c) => p + this.toNumber(c.quantity), 0)
152 152 return this.round(qty, 2)
153 153 },
154   - sumAmountExcl() {
155   - const sum = this.items.filter(it => it.locked).reduce((p, c) => p + this.toNumber(c.amountExcludingTax), 0)
156   - return this.round(sum, 2)
157   - },
158   - sumTotal() { return this.totalAmount },
  154 + // totalAmountExcludingTax() {
  155 + // const sum = this.items.filter(it => it.locked).reduce((p, c) => p + this.toNumber(c.amountExcludingTax), 0)
  156 + // return this.round(sum, 2)
  157 + // },
  158 + totalAmountIncludingTax() { return this.totalAmount },
159 159 totalAmount() {
160 160 let sum = 0
161 161 for (const it of this.items) {
... ... @@ -213,7 +213,7 @@ export default {
213 213 status: v.status || '',
214 214 quantity: v.productQuantity || v.quantity || '',
215 215 unitPrice: v.unitPrice || '',
216   - amountExcludingTax: v.amountExcludingTax || 0,
  216 + // amountExcludingTax: v.amountExcludingTax || 0,
217 217 totalAmount: v.totalAmount || 0,
218 218 deliveryDate: v.deliveryDate || '',
219 219 specDisplay: ''
... ... @@ -255,8 +255,8 @@ export default {
255 255 const qty = this.toNumber(it.quantity)
256 256 const price = this.toNumber(it.unitPrice)
257 257 const total = this.round(qty * price, 2)
258   - const excl = this.round(total / (1 + TAX_RATE), 2)
259   - it.amountExcludingTax = excl
  258 + // const excl = this.round(total / (1 + TAX_RATE), 2)
  259 + // it.amountExcludingTax = excl
260 260 it.totalAmount = total
261 261 this.$set(this.items, idx, it)
262 262 },
... ... @@ -292,7 +292,7 @@ export default {
292 292 ...it,
293 293 quantity: '',
294 294 unitPrice: '',
295   - amountExcludingTax: 0
  295 + // amountExcludingTax: 0
296 296 }))
297 297 },
298 298 async onSubmit() {
... ... @@ -301,12 +301,12 @@ export default {
301 301 const qty = this.toNumber(it.quantity)
302 302 const price = this.toNumber(it.unitPrice)
303 303 const total = this.toNumber(it.totalAmount)
304   - const excl = this.toNumber(it.amountExcludingTax)
  304 + // const excl = this.toNumber(it.amountExcludingTax)
305 305 if (Object.prototype.hasOwnProperty.call(raw, 'productQuantity')) raw.productQuantity = qty
306 306 else raw.quantity = qty
307 307 raw.unitPrice = price
308 308 raw.totalAmount = total
309   - raw.amountExcludingTax = excl
  309 + // raw.amountExcludingTax = excl
310 310 return raw
311 311 })
312 312 if (!selected.length) {
... ... @@ -325,9 +325,9 @@ export default {
325 325 const payload = {
326 326 id: this.id,
327 327 totalAmountCapital: formatCurrencyToChinese(this.sumTotal),
328   - totalAmountExcludingTax: this.sumAmountExcl,
329   - totalAmountIncludingTax: this.sumTotal,
330   - totalQuantity: this.sumQuantity,
  328 + // totalAmountExcludingTax: this.totalAmountExcludingTax,
  329 + totalAmountIncludingTax: this.totalAmountIncludingTax,
  330 + totalQuantity: this.totalQuantity,
331 331 type:'INTL_INVENTORY_AGMT',
332 332 contractDistributorLineList: selected
333 333 }
... ... @@ -362,7 +362,7 @@ export default {
362 362
363 363 .scroll {
364 364 flex: 1;
365   - padding: 12rpx 0 480rpx !important;
  365 + padding: 12rpx 0 392rpx !important;
366 366 }
367 367
368 368 .header {
... ... @@ -646,7 +646,7 @@ export default {
646 646 color: rgba(0, 0, 0, 0.6);
647 647 line-height: 32rpx;
648 648 width: 240rpx;
649   - padding: 24rpx 0;
  649 + padding: 12rpx 0;
650 650 }
651 651
652 652 .total-item-price {
... ...
... ... @@ -41,7 +41,7 @@
41 41 </template>
42 42 </uni-list-item>
43 43
44   - <ProductRel mode="add" :orderDateBase="form.orderDate" :list="productLineList" @change="onProductsChange" :options="productList" />
  44 + <ProductRel mode="add" :deliveryDate="form.orderDate" :deliveryDateBase="form.deliveryDate" :list="productLineList" @change="onProductsChange" :options="productList" />
45 45
46 46 <uni-list-item title="合计人民币金额(大写)">
47 47 <template v-slot:footer>
... ... @@ -98,34 +98,25 @@
98 98 :inputBorder="false" />
99 99 </template>
100 100 </uni-list-item>
101   -
102   - <view class="group">
103   - <view class="group-title">特别条款要求</view>
104   - <view class="radio-list">
105   - <view v-for="(opt, i) in specialTermsList" :key="'cr-' + i" class="radio-item"
106   - @click="onRadioSelect('specialTerms', 'specialTermsName', opt)">
107   - <view :class="['radio', { checked: form.specialTerms === opt.value }]" />
108   - <text class="label">{{ opt.label }}</text>
109   - </view>
110   - </view>
111   - </view>
112   - <view class="group">
113   - <view class="group-title">执行标准</view>
114   - <view class="radio-list">
115   - <view v-for="(opt, i) in executionStandardList" :key="'es-' + i" class="radio-item"
116   - @click="onRadioSelect('executionStandard', 'executionStandardName', opt)">
117   - <view :class="['radio', { checked: form.executionStandard === opt.value }]" />
118   - <text class="label">{{ opt.label }}</text>
119   - </view>
120   - </view>
121   - </view>
  101 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  102 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  103 + <template v-slot:body>
  104 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  105 + </template>
  106 + </uni-list-item>
  107 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  108 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  109 + <template v-slot:body>
  110 + <view class="item-title"><text>执行标准</text></view>
  111 + </template>
  112 + </uni-list-item>
122 113 <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
123 114 <template v-slot:footer>
124 115 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注"
125 116 :inputBorder="false" />
126 117 </template>
127 118 </uni-list-item>
128   - <uni-list-item title="特别说明">
  119 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
129 120 <template v-slot:footer>
130 121 <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
131 122 </template>
... ... @@ -177,15 +168,15 @@
177 168 <div class="total-text">合计</div>
178 169 <div class="total-item">
179 170 <div class="total-item-text">数量</div>
180   - <div class="total-item-price">{{ (sumQuantity || 0).toFixed(2) }}t</div>
  171 + <div class="total-item-price">{{ (totalQuantity || 0).toFixed(2) }}kg</div>
181 172 </div>
182   - <div class="total-item">
  173 + <!-- <div class="total-item">
183 174 <div class="total-item-text">不含税金额</div>
184   - <div class="total-item-price text-red">¥{{ (sumAmountExcl || 0).toFixed(2) }}</div>
185   - </div>
  175 + <div class="total-item-price text-red">¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}</div>
  176 + </div> -->
186 177 <div class="total-item">
187 178 <div class="total-item-text">总金额</div>
188   - <div class="total-item-price text-red">¥{{ (sumTotal || 0).toFixed(2) }}</div>
  179 + <div class="total-item-price text-red">¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}</div>
189 180 </div>
190 181 </div>
191 182 <button class="btn submit" type="primary" @click="onSubmit">保存</button>
... ... @@ -223,6 +214,7 @@ export default {
223 214 workshopId: '',
224 215 workshopName: '',
225 216 orderDate: '',
  217 + deliveryDate: '',
226 218 designatedConsignee: '',
227 219 specialTerms: '',
228 220 specialTermsName: '',
... ... @@ -233,7 +225,7 @@ export default {
233 225 includesPackagingFeeName: '',
234 226 includesTransportFee: false,
235 227 includesTransportFeeName: '',
236   - unit: '元、公斤、元/公斤',
  228 + unit: '美元、公斤、美元/公斤',
237 229 totalAmountCapital: '',
238 230 depositInfo: '',
239 231 packagingRequirements: '',
... ... @@ -256,9 +248,9 @@ export default {
256 248 yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
257 249 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
258 250 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
259   - sumQuantity: 0,
260   - sumAmountExcl: 0,
261   - sumTotal: 0,
  251 + totalQuantity: 0,
  252 + // totalAmountExcludingTax: 0,
  253 + totalAmountIncludingTax: 0,
262 254 productLineList: [],
263 255 newProductLineList: [],
264 256 productList: []
... ... @@ -347,11 +339,11 @@ export default {
347 339 const list = Array.isArray(products) ? products : []
348 340 this.newProductLineList = list
349 341 const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
350   - const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
  342 + // const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
351 343 const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
352   - this.sumQuantity = sumQ
353   - this.sumAmountExcl = sumE
354   - this.sumTotal = sumT
  344 + this.totalQuantity = sumQ
  345 + // this.totalAmountExcludingTax = sumE
  346 + this.totalAmountIncludingTax = sumT
355 347 this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
356 348 },
357 349 async loadSuppliers() {
... ... @@ -399,6 +391,10 @@ export default {
399 391 setSheet('生产厂', opts)
400 392 } else if (field === 'supplier') {
401 393 setSheet('供方', this.supplierList)
  394 + } else if (field === 'specialTerms') {
  395 + setSheet('特别条款要求', this.specialTermsList)
  396 + } else if (field === 'executionStandard') {
  397 + setSheet('执行标准', this.executionStandardList)
402 398 } else if (field === 'includesPackagingFee') {
403 399 setSheet('单价中是否已包含包装费', this.yesNoList)
404 400 } else if (field === 'includesTransportFee') {
... ... @@ -443,18 +439,30 @@ export default {
443 439 { key: 'supplier', label: '供方' },
444 440 { key: 'buyer', label: '需方' },
445 441 { key: 'orderDate', label: '订货日期' },
  442 + { key: 'unit', label: '单位' },
446 443 { key: 'workshopId', label: '生产厂' },
  444 + { key: 'specialTerms', label: '特别条款要求' },
447 445 ]
448 446 for (const it of checks) {
449 447 const val = this.form[it.key]
450 448 const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
451 449 if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
452 450 }
453   - if (!Array.isArray(this.productLineList) || this.productLineList.length === 0) {
  451 + const list = Array.isArray(this.newProductLineList) ? this.newProductLineList : []
  452 + if (list.length === 0) {
454 453 uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
455 454 }
456   - for (const [idx, it] of this.productLineList.entries()) {
457   - if (!it.productName || !it.quantity || !it.unitPrice) {
  455 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  456 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  457 + for (const [idx, it] of list.entries()) {
  458 + if (
  459 + strEmpty(it.productName) ||
  460 + strEmpty(it.industry) ||
  461 + strEmpty(it.quality) ||
  462 + strEmpty(it.brand) ||
  463 + numEmpty(it.quantity) ||
  464 + strEmpty(it.deliveryDate)
  465 + ) {
458 466 uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
459 467 }
460 468 }
... ... @@ -486,9 +494,9 @@ export default {
486 494 id: this.form.id,
487 495 destination,
488 496 type: 'INTL_INVENTORY_AGMT',
489   - sumQuantity: this.sumQuantity,
490   - sumAmountExcl: this.sumAmountExcl,
491   - sumTotal: this.sumTotal,
  497 + totalQuantity: this.totalQuantity,
  498 + // totalAmountExcludingTax: this.totalAmountExcludingTax,
  499 + totalAmountIncludingTax: this.totalAmountIncludingTax,
492 500 contractDistributorLineList: lines
493 501 })
494 502 try {
... ... @@ -524,7 +532,7 @@ export default {
524 532 color: rgba(0, 0, 0, 0.6);
525 533 line-height: 32rpx;
526 534 width: 240rpx;
527   - padding: 24rpx 0;
  535 + padding: 12rpx 0;
528 536 }
529 537
530 538 .total-item-price {
... ... @@ -547,7 +555,7 @@ export default {
547 555
548 556 .scroll {
549 557 flex: 1;
550   - padding: 12rpx 0 480rpx !important;
  558 + padding: 12rpx 0 392rpx !important;
551 559 }
552 560
553 561 .footer {
... ...
... ... @@ -53,53 +53,53 @@
53 53 <uni-easyinput v-model="item.quality" :inputBorder="false" placeholder="请输入品质" />
54 54 </template>
55 55 </uni-list-item>
56   - <uni-list-item title="厚度">
  56 + <uni-list-item title="厚度(mm)">
57 57 <template v-slot:footer>
58   - <uni-easyinput v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" />
  58 + <uni-easyinput type="digit" v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" @input="onNonNegativeInput(idx, 'thickness')" @blur="onNonNegativeBlur(idx, 'thickness', 2)" />
59 59 </template>
60 60 </uni-list-item>
61   - <uni-list-item title="厚度公差(单项+)">
  61 + <uni-list-item title="厚度公差上限(mm)">
62 62 <template v-slot:footer>
63   - <uni-easyinput v-model="item.thicknessTolPos" :inputBorder="false"
64   - placeholder="请输入厚度公差(单项+)" />
  63 + <uni-easyinput type="digit" v-model="item.thicknessTolPos" :inputBorder="false"
  64 + placeholder="请输入厚度公差上限" @input="onNonNegativeInput(idx, 'thicknessTolPos')" @blur="onNonNegativeBlur(idx, 'thicknessTolPos', 2)" />
65 65 </template>
66 66 </uni-list-item>
67   - <uni-list-item title="厚度公差(单项-)">
  67 + <uni-list-item title="厚度公差下限(mm)">
68 68 <template v-slot:footer>
69   - <uni-easyinput v-model="item.thicknessTolNeg" :inputBorder="false"
70   - placeholder="请输入厚度公差(单项-)" />
  69 + <uni-easyinput type="digit" v-model="item.thicknessTolNeg" :inputBorder="false"
  70 + placeholder="请输入厚度公差下限" @input="onNonNegativeInput(idx, 'thicknessTolNeg')" @blur="onNonNegativeBlur(idx, 'thicknessTolNeg', 2)" />
71 71 </template>
72 72 </uni-list-item>
73   - <uni-list-item title="宽度">
  73 + <uni-list-item title="宽度(mm)">
74 74 <template v-slot:footer>
75   - <uni-easyinput v-model="item.width" :inputBorder="false" placeholder="请输入宽度" />
  75 + <uni-easyinput type="digit" v-model="item.width" :inputBorder="false" placeholder="请输入宽度" @input="onNonNegativeInput(idx, 'width')" @blur="onNonNegativeBlur(idx, 'width', 2)" />
76 76 </template>
77 77 </uni-list-item>
78   - <uni-list-item title="宽度公差(单项+)">
  78 + <uni-list-item title="宽度公差上限(mm)">
79 79 <template v-slot:footer>
80   - <uni-easyinput v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差(单项+)" />
  80 + <uni-easyinput type="digit" v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差(单项+)" @input="onNonNegativeInput(idx, 'widthTolPos')" @blur="onNonNegativeBlur(idx, 'widthTolPos', 2)" />
81 81 </template>
82 82 </uni-list-item>
83   - <uni-list-item title="宽度公差(单项-)">
  83 + <uni-list-item title="宽度公差下限(mm)">
84 84 <template v-slot:footer>
85   - <uni-easyinput v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差(单项-)" />
  85 + <uni-easyinput type="digit" v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差下限" @input="onNonNegativeInput(idx, 'widthTolNeg')" @blur="onNonNegativeBlur(idx, 'widthTolNeg', 2)" />
86 86 </template>
87 87 </uni-list-item>
88   - <uni-list-item title="长度">
  88 + <uni-list-item title="长度(mm)">
89 89 <template v-slot:footer>
90   - <uni-easyinput v-model="item.length" :inputBorder="false" placeholder="请输入长度" />
  90 + <uni-easyinput type="digit" v-model="item.length" :inputBorder="false" placeholder="请输入长度" @input="onNonNegativeInput(idx, 'length')" @blur="onNonNegativeBlur(idx, 'length', 2)" />
91 91 </template>
92 92 </uni-list-item>
93   - <uni-list-item title="长度公差(单项+)">
  93 + <uni-list-item title="长度公差上限(mm)">
94 94 <template v-slot:footer>
95   - <uni-easyinput v-model="item.lengthTolPos" :inputBorder="false"
96   - placeholder="请输入长度公差(单项+)" />
  95 + <uni-easyinput type="digit" v-model="item.lengthTolPos" :inputBorder="false"
  96 + placeholder="请输入长度公差上限" @input="onNonNegativeInput(idx, 'lengthTolPos')" @blur="onNonNegativeBlur(idx, 'lengthTolPos', 2)" />
97 97 </template>
98 98 </uni-list-item>
99   - <uni-list-item title="长度公差(单项-)">
  99 + <uni-list-item title="长度公差下限(mm)">
100 100 <template v-slot:footer>
101   - <uni-easyinput v-model="item.lengthTolNeg" :inputBorder="false"
102   - placeholder="请输入长度公差(单项-)" />
  101 + <uni-easyinput type="digit" v-model="item.lengthTolNeg" :inputBorder="false"
  102 + placeholder="请输入长度公差下限" @input="onNonNegativeInput(idx, 'lengthTolNeg')" @blur="onNonNegativeBlur(idx, 'lengthTolNeg', 2)" />
103 103 </template>
104 104 </uni-list-item>
105 105 <uni-list-item title="状态">
... ... @@ -109,7 +109,7 @@
109 109 </uni-list-item>
110 110 <uni-list-item title="数量">
111 111 <template v-slot:footer>
112   - <uni-easyinput v-model="item.quantity" type="number" :inputBorder="false" placeholder="请输入数量" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'quantity', 0)" />
  112 + <uni-easyinput v-model="item.quantity" type="digit" :inputBorder="false" placeholder="请输入数量" @input="onNonNegativeInput(idx, 'quantity')" @blur="onNonNegativeBlur(idx, 'quantity', 2)" />
113 113 </template>
114 114 </uni-list-item>
115 115 <uni-list-item title="单价">
... ... @@ -122,11 +122,11 @@
122 122 <uni-easyinput v-model="item.processingFee" type="number" :inputBorder="false" placeholder="请输入外贸加工费" />
123 123 </template>
124 124 </uni-list-item>
125   - <uni-list-item title="不含税金额">
  125 + <!-- <uni-list-item title="不含税金额">
126 126 <template v-slot:footer>
127 127 <uni-easyinput v-model="item.amountExcludingTax" type="number" :inputBorder="false" disabled placeholder="自动计算" />
128 128 </template>
129   - </uni-list-item>
  129 + </uni-list-item> -->
130 130 <uni-list-item title="总金额">
131 131 <template v-slot:footer>
132 132 <uni-easyinput v-model="item.totalAmount" type="number" :inputBorder="false" disabled placeholder="自动计算" />
... ... @@ -134,7 +134,7 @@
134 134 </uni-list-item>
135 135 <uni-list-item title="发货日期">
136 136 <template v-slot:footer>
137   - <uni-datetime-picker type="date" v-model="item.orderDate" @change="onDateChange(idx, $event)" />
  137 + <uni-datetime-picker :start="minDeliveryDate" type="date" v-model="item.deliveryDate" @change="onDateChange(idx, $event)" />
138 138 </template>
139 139 </uni-list-item>
140 140 </uni-list>
... ... @@ -156,18 +156,41 @@
156 156 <view class="row"><text class="label">行业</text><text class="value">{{ item.industry }}</text></view>
157 157 <view class="row"><text class="label">牌号</text><text class="value">{{ item.brand }}</text></view>
158 158 <view class="row"><text class="label">品质</text><text class="value">{{ item.quality }}</text></view>
159   - <view class="row"><text class="label">规格</text><text class="value">{{ item.specDisplay }}</text></view>
  159 + <!-- 厚(公差) * 宽(公差) * 长(公差) -->
  160 + <view class="row row-spec"><text class="label">规格(mm)</text>
  161 + <view class="value value-spec">
  162 + <view v-if="item.thickness" class="value-spec_val">{{ item.thickness }}</view>
  163 + <view v-if="item.thickness" class="value-spec_box">
  164 + <view v-if="item.thicknessTolPos" class="value-spec_box_1">+{{ item.thicknessTolPos }}
  165 + </view>
  166 + <view v-if="item.thicknessTolNeg" class="value-spec_box_2">-{{ item.thicknessTolNeg }}
  167 + </view>
  168 + </view>
  169 + <view v-if="item.width" class="value-spec_val p12">*</view>
  170 + <view v-if="item.width" class="value-spec_val">{{ item.width }}</view>
  171 + <view v-if="item.width" class="value-spec_box">
  172 + <view v-if="item.widthTolPos" class="value-spec_box_1">+{{ item.widthTolPos }}</view>
  173 + <view v-if="item.widthTolNeg" class="value-spec_box_2">-{{ item.widthTolNeg }}</view>
  174 + </view>
  175 + <view v-if="item.length" class="value-spec_val p12">*</view>
  176 + <view v-if="item.length" class="value-spec_val">{{ item.length }}</view>
  177 + <view v-if="item.length" class="value-spec_box">
  178 + <view v-if="item.lengthTolPos" class="value-spec_box_1">+{{ item.lengthTolPos }}</view>
  179 + <view v-if="item.lengthTolNeg" class="value-spec_box_2">-{{ item.lengthTolNeg }}</view>
  180 + </view>
  181 + </view>
  182 + </view>
160 183 <view class="row"><text class="label">状态</text><text class="value">{{ item.status }}</text></view>
161 184 <view class="row"><text class="label">数量</text><text class="value">{{ item.quantity }}</text></view>
162 185 <view class="row"><text class="label">单价</text><text class="value">{{ formatCurrency(item.unitPrice)
163 186 }}</text>
164 187 </view>
165   - <view class="row"><text class="label">不含税金额</text><text class="value">{{
  188 + <!-- <view class="row"><text class="label">不含税金额</text><text class="value">{{
166 189 formatCurrency(item.amountExcludingTax)
167   - }}</text></view>
  190 + }}</text></view> -->
168 191 <view class="row"><text class="label">总金额</text><text class="value">{{ formatCurrency(item.totalAmount)
169 192 }}</text></view>
170   - <view class="row"><text class="label">发货日期</text><text class="value">{{ item.orderDate }}</text></view>
  193 + <view class="row"><text class="label">发货日期</text><text class="value">{{ item.deliveryDate }}</text></view>
171 194 </view>
172 195 </view>
173 196 <SingleSelectSheet :visible.sync="sheet.visible" :title="sheet.title" :options="sheet.options" v-model="sheet.value" @confirm="onProductConfirm" />
... ... @@ -181,7 +204,8 @@ export default {
181 204 mode: { type: String, default: 'add' },
182 205 list: { type: Array, default: () => [] },
183 206 max: { type: Number, default: 8 },
184   - orderDateBase: { type: String, default: '' },
  207 + deliveryDateBase: { type: String, default: '' },
  208 + deliveryDate: { type: String, default: '' },
185 209 options: { type: Array, default: () => [] }
186 210 },
187 211 components: { SingleSelectSheet },
... ... @@ -192,15 +216,6 @@ export default {
192 216 sheet: { visible: false, title: '请选择产品', options: [], value: '', idx: -1 }
193 217 }
194 218 },
195   - computed: {
196   - selectOptions() {
197   - const list = Array.isArray(this.options) ? this.options : []
198   - return list.map(o => ({
199   - label: o.label != null ? o.label : (o.text != null ? o.text : (o.name != null ? o.name : '')),
200   - value: o.value != null ? o.value : (o.id != null ? o.id : o.productId)
201   - }))
202   - }
203   - },
204 219 watch: {
205 220 items: {
206 221 handler() { this.emitChange() },
... ... @@ -221,9 +236,44 @@ export default {
221 236 this.items = init
222 237 this.recalculateAll()
223 238 },
  239 + computed: {
  240 + selectOptions() {
  241 + const list = Array.isArray(this.options) ? this.options : []
  242 + return list.map(o => ({
  243 + label: o.label != null ? o.label : (o.text != null ? o.text : (o.name != null ? o.name : '')),
  244 + value: o.value != null ? o.value : (o.id != null ? o.id : o.productId)
  245 + }))
  246 + },
  247 + minDeliveryDate() {
  248 + const s = this.deliveryDate
  249 + if (!s) return ''
  250 + const parts = String(s).split('-')
  251 + const y = Number(parts[0])
  252 + const m = Number(parts[1])
  253 + const d = Number(parts[2])
  254 + if (!y || !m || !d) return ''
  255 + const dt = new Date(y, m - 1, d)
  256 + dt.setDate(dt.getDate() + 1)
  257 + const yy = dt.getFullYear()
  258 + const mm = String(dt.getMonth() + 1).padStart(2, '0')
  259 + const dd = String(dt.getDate() - 1).padStart(2, '0')
  260 + return `${yy}/${mm}/${dd}`
  261 + }
  262 + },
224 263 methods: {
225 264 defaultItem() {
226   - return { productId: '', productName: '', industry: '', brand: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', status: '', quantity: '', unitPrice: '', processingFee: undefined, amountExcludingTax: 0, totalAmount: 0, orderDate: '' }
  265 + return { productId: '', productName: '', industry: '', brand: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', status: '', quantity: '', unitPrice: '', processingFee: undefined, totalAmount: 0, deliveryDate: '' }
  266 + },
  267 + onNonNegativeInput(idx, field) {
  268 + const it = this.items[idx]
  269 + if (!it) return
  270 + let v = String(it[field] != null ? it[field] : '')
  271 + v = v.replace(/[^0-9.]/g, '')
  272 + v = v.replace(/(\..*)\./g, '$1')
  273 + if (v.startsWith('.')) v = '0' + v
  274 + it[field] = v
  275 + this.$set(this.items, idx, it)
  276 + if (field === 'quantity' || field === 'unitPrice') this.$nextTick(() => this.recalculate(idx))
227 277 },
228 278 onImmediateChange(idx) {
229 279 this.$nextTick(() => this.recalculate(idx))
... ... @@ -239,21 +289,21 @@ export default {
239 289 const m = Math.pow(10, digits)
240 290 return Math.round(n * m) / m
241 291 },
242   - onNumberBlur(idx, field, digits) {
  292 + onNonNegativeBlur(idx, field, digits) {
243 293 const it = this.items[idx]
244 294 if (!it) return
245 295 const raw = it[field]
246   - // 如果为空则保持为空,不自动置为0,仅重新计算依赖字段
247 296 if (raw === '' || raw === null || raw === undefined) {
248 297 this.$set(this.items, idx, it)
249   - this.recalculate(idx)
  298 + if (field === 'quantity' || field === 'unitPrice') this.recalculate(idx)
250 299 return
251 300 }
252   - const num = this.toNumber(raw)
  301 + let num = this.toNumber(raw)
  302 + if (isNaN(num) || num < 0) num = 0
253 303 const rounded = this.round(num, digits)
254 304 it[field] = rounded
255 305 this.$set(this.items, idx, it)
256   - this.recalculate(idx)
  306 + if (field === 'quantity' || field === 'unitPrice') this.recalculate(idx)
257 307 },
258 308 formatCurrency(val) {
259 309 if (val == null || val === '') return ''
... ... @@ -269,9 +319,9 @@ export default {
269 319 return [t, w, l].filter(Boolean).join(' × ')
270 320 },
271 321 openProductSheet(idx) {
272   - const opts = this.selectOptions
  322 + const opts = Array.isArray(this.selectOptions) ? this.selectOptions : []
273 323 const current = this.items[idx] && this.items[idx].productId
274   - const match = opts.find(o => o.value === current)
  324 + const match = (opts || []).find(o => String(o.value) === String(current))
275 325 this.sheet = { ...this.sheet, visible: true, title: '请选择产品', options: opts, idx, value: match ? match.value : '' }
276 326 },
277 327 onProductConfirm({ value, label }) {
... ... @@ -285,14 +335,14 @@ export default {
285 335 this.emitChange()
286 336 },
287 337 recalculate(idx) {
288   - const TAX_RATE = 0.13
  338 + // const TAX_RATE = 0.13
289 339 const it = this.items[idx]
290 340 if (!it) return
291 341 const qty = this.toNumber(it.quantity)
292 342 const price = this.toNumber(it.unitPrice)
293 343 const total = this.round(qty * price, 2)
294   - const excl = this.round(total / (1 + TAX_RATE), 2)
295   - const next = { ...it, totalAmount: total, amountExcludingTax: excl }
  344 + // const excl = this.round(total / (1 + TAX_RATE), 2)
  345 + const next = { ...it, totalAmount: total }
296 346 this.$set(this.items, idx, next)
297 347 },
298 348 recalculateAll() {
... ... @@ -324,15 +374,15 @@ export default {
324 374 onDateChange(idx, e) {
325 375 const it = this.items[idx]
326 376 if (!it) return
327   - const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.orderDate
  377 + const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.deliveryDate
328 378 const dateStr = String(val).slice(0, 10)
329   - const base = this.orderDateBase ? new Date(this.orderDateBase) : null
  379 + const base = this.deliveryDateBase ? new Date(this.deliveryDateBase) : null
330 380 const d = new Date(dateStr)
331 381 if (base && !isNaN(d.getTime()) && d.getTime() < base.getTime()) {
332 382 uni.showToast({ title: '发货日期不得早于订货日期', icon: 'none' })
333   - it.orderDate = this.orderDateBase
  383 + it.deliveryDate = this.deliveryDateBase
334 384 } else {
335   - it.orderDate = dateStr
  385 + it.deliveryDate = dateStr
336 386 }
337 387 this.$set(this.items, idx, it)
338 388 },
... ... @@ -505,8 +555,46 @@ export default {
505 555
506 556 .value {
507 557 flex: 1;
508   - text-align: right;
  558 + // text-align: right;
509 559 color: rgba(0, 0, 0, 0.9);
510 560 font-size: 28rpx;
511 561 }
  562 + .value-spec {
  563 + height: 48rpx;
  564 + display: flex;
  565 + align-items: center;
  566 + color: #000000;
  567 + // justify-content: end;
  568 + &_box {
  569 + position: relative;
  570 + width: 60rpx;
  571 + height: 48rpx;
  572 +
  573 + &_1 {
  574 + font-size: 16rpx;
  575 + position: absolute;
  576 + top: -10rpx;
  577 + left: 0;
  578 + }
  579 +
  580 + &_2 {
  581 + font-size: 16rpx;
  582 + position: absolute;
  583 + bottom: -10rpx;
  584 + left: 0;
  585 + }
  586 + }
  587 +
  588 + &_val {
  589 + font-size: 28rpx;
  590 +
  591 + &.p12 {
  592 + padding-right: 12rpx;
  593 + }
  594 + }
  595 + }
  596 + .row-spec {
  597 + height: 60rpx;
  598 + align-items: center;
  599 + }
512 600 </style>
... ...
... ... @@ -39,7 +39,7 @@
39 39 <view class="item-title"><text class="required">*</text><text>生产厂</text></view>
40 40 </template>
41 41 </uni-list-item>
42   - <ProductRel mode="add" :orderDateBase="form.orderDate" @change="onProductsChange" :options="productList" />
  42 + <ProductRel mode="add" :deliveryDate="form.orderDate" :deliveryDateBase="form.deliveryDate" @change="onProductsChange" :options="productList" />
43 43 <uni-list-item title="合计人民币金额(大写)">
44 44 <template v-slot:footer>
45 45 <uni-easyinput v-model="form.totalAmountCapital" placeholder="自动计算" :inputBorder="false" disabled />
... ... @@ -92,33 +92,25 @@
92 92 :inputBorder="false" />
93 93 </template>
94 94 </uni-list-item>
95   - <view class="group">
96   - <view class="group-title">特别条款要求</view>
97   - <view class="radio-list">
98   - <view v-for="(opt, i) in specialTermsList" :key="'cr-' + i" class="radio-item"
99   - @click="onRadioSelect('specialTerms', 'specialTermsName', opt)">
100   - <view :class="['radio', { checked: form.specialTerms === opt.value }]" />
101   - <text class="label">{{ opt.label }}</text>
102   - </view>
103   - </view>
104   - </view>
105   - <view class="group">
106   - <view class="group-title">执行标准</view>
107   - <view class="radio-list">
108   - <view v-for="(opt, i) in executionStandardList" :key="'es-' + i" class="radio-item"
109   - @click="onRadioSelect('executionStandard', 'executionStandardName', opt)">
110   - <view :class="['radio', { checked: form.executionStandard === opt.value }]" />
111   - <text class="label">{{ opt.label }}</text>
112   - </view>
113   - </view>
114   - </view>
  95 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  96 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  97 + <template v-slot:body>
  98 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  99 + </template>
  100 + </uni-list-item>
  101 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  102 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  103 + <template v-slot:body>
  104 + <view class="item-title"><text>执行标准</text></view>
  105 + </template>
  106 + </uni-list-item>
115 107 <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
116 108 <template v-slot:footer>
117 109 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注"
118 110 :inputBorder="false" />
119 111 </template>
120 112 </uni-list-item>
121   - <uni-list-item title="特别说明">
  113 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
122 114 <template v-slot:footer>
123 115 <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
124 116 </template>
... ... @@ -180,24 +172,24 @@
180 172 <div class="total-item-text">
181 173 数量
182 174 </div>
183   - <div class="total-item-price">
184   - {{ (sumQuantity || 0).toFixed(2) }}t
  175 + <div class="total-item-price">
  176 + {{ (totalQuantity || 0).toFixed(2) }}kg
185 177 </div>
186 178 </div>
187   - <div class="total-item">
  179 + <!-- <div class="total-item">
188 180 <div class="total-item-text">
189 181 不含税金额
190 182 </div>
191 183 <div class="total-item-price text-red">
192   - ¥{{ (sumAmountExcl || 0).toFixed(2) }}
  184 + ¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}
193 185 </div>
194   - </div>
  186 + </div> -->
195 187 <div class="total-item">
196 188 <div class="total-item-text">
197 189 总金额
198 190 </div>
199 191 <div class="total-item-price text-red">
200   - ¥{{ (sumTotal || 0).toFixed(2) }}
  192 + ¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}
201 193 </div>
202 194 </div>
203 195 </div>
... ... @@ -233,6 +225,7 @@ export default {
233 225 buyer: '',
234 226 buyerName: '',
235 227 orderDate: '',
  228 + deliveryDate: '',
236 229 designatedConsignee: '',
237 230 specialTerms: '',
238 231 specialTermsName: '',
... ... @@ -243,7 +236,7 @@ export default {
243 236 includesPackagingFeeName: '',
244 237 includesTransportFee: false,
245 238 includesTransportFeeName: '',
246   - unit: '元、公斤、元/公斤',
  239 + unit: '美元、公斤、美元/公斤',
247 240 totalAmountCapital: '',
248 241 destinationId: [],
249 242 destinationLabel: '',
... ... @@ -263,9 +256,9 @@ export default {
263 256 yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
264 257 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
265 258 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
266   - sumQuantity: 0,
267   - sumAmountExcl: 0,
268   - sumTotal: 0,
  259 + totalQuantity: 0,
  260 + // totalAmountExcludingTax: 0,
  261 + totalAmountIncludingTax: 0,
269 262 productLineList: [],
270 263 productList: [],
271 264 customerRemarks: [],
... ... @@ -366,11 +359,11 @@ export default {
366 359 onProductsChange(products) {
367 360 const list = Array.isArray(products) ? products : []
368 361 const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
369   - const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
  362 + // const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
370 363 const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
371   - this.sumQuantity = sumQ
372   - this.sumAmountExcl = sumE
373   - this.sumTotal = sumT
  364 + this.totalQuantity = sumQ
  365 + // this.totalAmountExcludingTax = sumE
  366 + this.totalAmountIncludingTax = sumT
374 367 this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
375 368 this.productLineList = list
376 369 },
... ... @@ -446,6 +439,10 @@ export default {
446 439 setSheet('生产厂', opts)
447 440 } else if (field === 'supplier') {
448 441 setSheet('供方', this.supplierList)
  442 + } else if (field === 'specialTerms') {
  443 + setSheet('特别条款要求', this.specialTermsList)
  444 + } else if (field === 'executionStandard') {
  445 + setSheet('执行标准', this.executionStandardList)
449 446 } else if (field === 'includesPackagingFee') {
450 447 setSheet('单价中是否已包含包装费', this.yesNoList)
451 448 } else if (field === 'includesTransportFee') {
... ... @@ -516,9 +513,9 @@ export default {
516 513 ...formForSubmit,
517 514 destination,
518 515 type: 'INTL_OPEN_SPEC_AGMT',
519   - sumQuantity: this.sumQuantity,
520   - sumAmountExcl: this.sumAmountExcl,
521   - sumTotal: this.sumTotal,
  516 + totalQuantity: this.totalQuantity,
  517 + // totalAmountExcludingTax: this.totalAmountExcludingTax,
  518 + totalAmountIncludingTax: this.totalAmountIncludingTax,
522 519 contractDistributorLineList: lines
523 520 })
524 521 console.log('onSubmit__payload', payload)
... ... @@ -537,18 +534,31 @@ export default {
537 534 { key: 'supplier', label: '供方' },
538 535 { key: 'buyer', label: '需方' },
539 536 { key: 'orderDate', label: '订货日期' },
  537 + { key: 'unit', label: '单位' },
540 538 { key: 'workshopId', label: '生产厂' },
  539 + { key: 'specialTerms', label: '特别条款要求' },
541 540 ]
542 541 for (const it of checks) {
543 542 const val = this.form[it.key]
544 543 const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
545 544 if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
546 545 }
547   - if (!Array.isArray(this.productLineList) || this.productLineList.length === 0) {
  546 + const list = Array.isArray(this.productLineList) ? this.productLineList : []
  547 + if (list.length === 0) {
548 548 uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
549 549 }
550   - for (const [idx, it] of this.productLineList.entries()) {
551   - if (!it.productName || !it.quantity || !it.unitPrice) {
  550 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  551 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  552 + for (const [idx, it] of list.entries()) {
  553 + if (
  554 + strEmpty(it.productName) ||
  555 + strEmpty(it.industry) ||
  556 + strEmpty(it.quality) ||
  557 + strEmpty(it.brand) ||
  558 + numEmpty(it.quantity) ||
  559 + numEmpty(it.unitPrice) ||
  560 + strEmpty(it.deliveryDate)
  561 + ) {
552 562 uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
553 563 }
554 564 }
... ... @@ -576,7 +586,7 @@ export default {
576 586 color: rgba(0, 0, 0, 0.6);
577 587 line-height: 32rpx;
578 588 width: 240rpx;
579   - padding: 24rpx 0;
  589 + padding: 12rpx 0;
580 590 }
581 591 .total-item-price {
582 592 font-weight: 600;
... ... @@ -598,7 +608,7 @@ export default {
598 608
599 609 .scroll {
600 610 flex: 1;
601   - padding: 12rpx 0 480rpx !important;
  611 + padding: 12rpx 0 392rpx !important;
602 612 }
603 613
604 614 .footer {
... ...
... ... @@ -53,7 +53,7 @@
53 53 }}</text></view>
54 54 </view>
55 55
56   - <view class="section">
  56 + <view class="section" v-if="detail.status === 'STANDARD'">
57 57 <view class="row"><text class="label">规范性合同</text><text class="value" style="color: #3D48A3;">{{
58 58 detail.standardFileName || '-'
59 59 }}</text></view>
... ... @@ -61,7 +61,7 @@
61 61 detail.standardStandardized ? '是' : '否'
62 62 }}</text></view>
63 63 </view>
64   - <view class="section" v-if="status === 'FORMAL'">
  64 + <view class="section" v-if="detail.status === 'FORMAL'">
65 65 <view class="row"><text class="label">规范性合同</text><text class="value" style="color: #3D48A3;">{{
66 66 detail.formalFileName || '-' }}</text></view>
67 67 <view class="row"><text class="label">合同是否规范</text><text class="value">{{ detail.formalStandardized
... ... @@ -271,20 +271,20 @@ export default {
271 271 const e = this.detail.showExamine || false
272 272 const f = this.detail.standardShowExamine || false
273 273 return [
274   - { ...this.buttons[0], visible: (s === 'DRAFT') }, //编辑
275   - { ...this.buttons[1], visible: (s === 'DRAFT') }, //删除
276   - { ...this.buttons[2], visible: (s === 'FORMAL' && !l) }, //锁规
277   - { ...this.buttons[3], visible: (s === 'FORMAL' && !l) }, //锁规延期申请
278   - { ...this.buttons[4], visible: ((s === 'DRAFT' || s === 'FORMAL') && a !== 'AUDIT' && a !== 'PASS') }, //上传正式合同附件
279   - { ...this.buttons[5], visible: (s === 'STANDARD' && a !== 'AUDIT' && a !== 'PASS') }, //上传正式合同附件
280   - { ...this.buttons[6], visible: (s === 'STANDARD' && t !== 'AUDIT' && t !== 'PASS') }, //上传标准合同附件
281   - { ...this.buttons[7], visible: (s === 'FORMAL' && e && a === 'AUDIT') }, //审核正式合同
282   - { ...this.buttons[8], visible: (s === 'STANDARD' && e && a === 'AUDIT') }, //审核正式合同
283   - { ...this.buttons[9], visible: (s === 'STANDARD' && f && t === 'AUDIT') }, //审核标准合同
284   - { ...this.buttons[10], visible: (s === 'FORMAL' && a) }, //正式合同审核详情
285   - { ...this.buttons[11], visible: (s === 'STANDARD' && a) }, //正式合同审核详情
286   - { ...this.buttons[12], visible: (s === 'STANDARD' && t) }, //标准合同审核详情
287   - { ...this.buttons[13], visible: (s === 'STANDARD') }, //上传双方盖章合同附件
  274 + { ...this.buttons[0], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:foreign-trade-unlocked-contract:modify')) }, //编辑
  275 + { ...this.buttons[1], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:foreign-trade-unlocked-contract:delete')) }, //删除
  276 + { ...this.buttons[2], visible: (s === 'FORMAL' && !l && this.$auth.hasPermi('contract-manage:foreign-trade-unlocked-contract:lock')) }, //锁规
  277 + { ...this.buttons[3], visible: (s === 'FORMAL' && !l && this.$auth.hasPermi('contract-manage:foreign-trade-unlocked-contract:lock-apply')) }, //锁规延期申请
  278 + { ...this.buttons[4], visible: ((s === 'DRAFT' || s === 'FORMAL') && a !== 'AUDIT' && a !== 'PASS' && this.$auth.hasPermi('contract-manage:foreign-trade-unlocked-contract:upload')) }, //上传正式合同附件
  279 + { ...this.buttons[5], visible: (s === 'STANDARD' && a !== 'AUDIT' && a !== 'PASS' && this.$auth.hasPermi('contract-manage:foreign-trade-unlocked-contract:upload')) }, //上传正式合同附件
  280 + { ...this.buttons[6], visible: (s === 'STANDARD' && t !== 'AUDIT' && t !== 'PASS' && this.$auth.hasPermi('contract-manage:foreign-trade-unlocked-contract:standard-upload')) }, //上传标准合同附件
  281 + { ...this.buttons[7], visible: (s === 'FORMAL' && e && a === 'AUDIT' && this.$auth.hasPermi('contract-manage:foreign-trade-unlocked-contract:approve')) }, //审核正式合同
  282 + { ...this.buttons[8], visible: (s === 'STANDARD' && e && a === 'AUDIT' && this.$auth.hasPermi('contract-manage:foreign-trade-unlocked-contract:approve')) }, //审核正式合同
  283 + { ...this.buttons[9], visible: (s === 'STANDARD' && f && t === 'AUDIT' && this.$auth.hasPermi('contract-manage:foreign-trade-unlocked-contract:standard-approve')) }, //审核标准合同
  284 + { ...this.buttons[10], visible: (s === 'FORMAL' && a && this.$auth.hasPermi('contract-manage:foreign-trade-unlocked-contract:review')) }, //正式合同审核详情
  285 + { ...this.buttons[11], visible: (s === 'STANDARD' && a && this.$auth.hasPermi('contract-manage:foreign-trade-unlocked-contract:review')) }, //正式合同审核详情
  286 + { ...this.buttons[12], visible: (s === 'STANDARD' && t && this.$auth.hasPermi('contract-manage:foreign-trade-unlocked-contract:standard-review')) }, //标准合同审核详情
  287 + { ...this.buttons[13], visible: (s === 'STANDARD' && this.$auth.hasPermi('contract-manage:foreign-trade-unlcoked-contract:upload-seal')) }, //上传双方盖章合同附件
288 288 ]
289 289 }
290 290 },
... ...
... ... @@ -14,7 +14,7 @@
14 14 @input="onSearchInput"
15 15 />
16 16 <view class="tool-icons">
17   - <image class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
  17 + <image v-if="$auth.hasPermi('contract-manage:foreign-trade-unlocked-contract:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
18 18 <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
19 19 </view>
20 20 </view>
... ... @@ -61,7 +61,9 @@
61 61 <text>订单总额</text><text class="amount" :style="{ color: '#b67a76' }">{{ item.totalAmountIncludingTax ? '¥' : '' }}{{ formatAmount(item.totalAmountIncludingTax) || '-' }}</text>
62 62 </view>
63 63 <view class="info-row" v-if="item.status === 'STANDARD' || item.status === 'FORMAL'">
64   - <text>{{ item.status === 'STANDARD' ? '标准合同' : '正式合同' }}规范性审核状态</text><span class="info-status" :style="item.standardApprovedName ? getStatusCss(item.standardApprovedName) : ''">{{ item.standardApprovedName || '-' }}</span>
  64 + <text>{{ item.status === 'STANDARD' ? '标准合同' : '正式合同' }}规范性审核状态</text>
  65 + <span v-if="item.status === 'STANDARD' ? item.standardApprovedName : item.formalApprovedName" class="info-status" :style="getStatusCss(item.status === 'STANDARD' ? item.standardApprovedName : item.formalApprovedName)">{{ item.status === 'STANDARD' ? item.standardApprovedName : item.formalApprovedName }}</span>
  66 + <span v-else>-</span>
65 67 </view>
66 68 <view class="info-row">
67 69 <text>订货日期</text><text>{{ item.orderDate }}</text>
... ...
... ... @@ -59,11 +59,11 @@
59 59 <uni-easyinput v-model="item.unitPrice" type="number" :inputBorder="false" placeholder="请输入单价" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'unitPrice', 0)" />
60 60 </template>
61 61 </uni-list-item>
62   - <uni-list-item title="不含税金额">
  62 + <!-- <uni-list-item title="不含税金额">
63 63 <template v-slot:footer>
64 64 <uni-easyinput v-model="item.amountExcludingTax" type="number" :inputBorder="false" disabled placeholder="自动计算" />
65 65 </template>
66   - </uni-list-item>
  66 + </uni-list-item> -->
67 67 <uni-list-item title="总金额">
68 68 <template v-slot:footer>
69 69 <uni-easyinput v-model="item.totalAmount" type="number" :inputBorder="false" disabled placeholder="自动计算" />
... ... @@ -107,23 +107,23 @@
107 107 数量
108 108 </div>
109 109 <div class="total-item-price">
110   - {{ (sumQuantity || 0).toFixed(2) }}t
  110 + {{ (totalQuantity || 0).toFixed(2) }}kg
111 111 </div>
112 112 </div>
113   - <div class="total-item">
  113 + <!-- <div class="total-item">
114 114 <div class="total-item-text">
115 115 不含税金额
116 116 </div>
117 117 <div class="total-item-price text-red">
118   - ¥{{ (sumAmountExcl || 0).toFixed(2) }}
  118 + ¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}
119 119 </div>
120   - </div>
  120 + </div> -->
121 121 <div class="total-item">
122 122 <div class="total-item-text">
123 123 总金额
124 124 </div>
125 125 <div class="total-item-price text-red">
126   - ¥{{ (sumTotal || 0).toFixed(2) }}
  126 + ¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}
127 127 </div>
128 128 </div>
129 129 </div>
... ... @@ -146,15 +146,15 @@ export default {
146 146 }
147 147 },
148 148 computed: {
149   - sumQuantity() {
  149 + totalQuantity() {
150 150 const qty = this.items.filter(it => it.locked).reduce((p, c) => p + this.toNumber(c.quantity), 0)
151 151 return this.round(qty, 2)
152 152 },
153   - sumAmountExcl() {
154   - const sum = this.items.filter(it => it.locked).reduce((p, c) => p + this.toNumber(c.amountExcludingTax), 0)
155   - return this.round(sum, 2)
156   - },
157   - sumTotal() { return this.totalAmount },
  153 + // totalAmountExcludingTax() {
  154 + // const sum = this.items.filter(it => it.locked).reduce((p, c) => p + this.toNumber(c.amountExcludingTax), 0)
  155 + // return this.round(sum, 2)
  156 + // },
  157 + totalAmountIncludingTax() { return this.totalAmount },
158 158 totalAmount() {
159 159 let sum = 0
160 160 for (const it of this.items) {
... ... @@ -212,7 +212,7 @@ export default {
212 212 status: v.status || '',
213 213 quantity: v.productQuantity || v.quantity || '',
214 214 unitPrice: v.unitPrice || '',
215   - amountExcludingTax: v.amountExcludingTax || 0,
  215 + // amountExcludingTax: v.amountExcludingTax || 0,
216 216 totalAmount: v.totalAmount || 0,
217 217 deliveryDate: v.deliveryDate || '',
218 218 specDisplay: ''
... ... @@ -248,14 +248,14 @@ export default {
248 248 this.recalculate(idx)
249 249 },
250 250 recalculate(idx) {
251   - const TAX_RATE = 0.13
  251 + // const TAX_RATE = 0.13
252 252 const it = this.items[idx]
253 253 if (!it) return
254 254 const qty = this.toNumber(it.quantity)
255 255 const price = this.toNumber(it.unitPrice)
256 256 const total = this.round(qty * price, 2)
257   - const excl = this.round(total / (1 + TAX_RATE), 2)
258   - it.amountExcludingTax = excl
  257 + // const excl = this.round(total / (1 + TAX_RATE), 2)
  258 + // it.amountExcludingTax = excl
259 259 it.totalAmount = total
260 260 this.$set(this.items, idx, it)
261 261 },
... ... @@ -291,7 +291,7 @@ export default {
291 291 ...it,
292 292 quantity: '',
293 293 unitPrice: '',
294   - amountExcludingTax: 0
  294 + // amountExcludingTax: 0,
295 295 }))
296 296 },
297 297 async onSubmit() {
... ... @@ -300,12 +300,12 @@ export default {
300 300 const qty = this.toNumber(it.quantity)
301 301 const price = this.toNumber(it.unitPrice)
302 302 const total = this.toNumber(it.totalAmount)
303   - const excl = this.toNumber(it.amountExcludingTax)
  303 + // const excl = this.toNumber(it.amountExcludingTax)
304 304 if (Object.prototype.hasOwnProperty.call(raw, 'productQuantity')) raw.productQuantity = qty
305 305 else raw.quantity = qty
306 306 raw.unitPrice = price
307 307 raw.totalAmount = total
308   - raw.amountExcludingTax = excl
  308 + // raw.amountExcludingTax = excl
309 309 return raw
310 310 })
311 311 if (!selected.length) {
... ... @@ -325,9 +325,9 @@ export default {
325 325 const payload = {
326 326 id: this.id,
327 327 totalAmountCapital: formatCurrencyToChinese(this.sumTotal),
328   - totalAmountExcludingTax: this.sumAmountExcl,
329   - totalAmountIncludingTax: this.sumTotal,
330   - totalQuantity: this.sumQuantity,
  328 + // totalAmountExcludingTax: this.totalAmountExcludingTax,
  329 + totalAmountIncludingTax: this.totalAmountIncludingTax,
  330 + totalQuantity: this.totalQuantity,
331 331 type:'INTL_OPEN_SPEC_AGMT',
332 332 contractDistributorLineList: selected
333 333 }
... ... @@ -362,7 +362,7 @@ export default {
362 362
363 363 .scroll {
364 364 flex: 1;
365   - padding: 12rpx 0 480rpx !important;
  365 + padding: 12rpx 0 392rpx !important;
366 366 }
367 367
368 368 .header {
... ... @@ -646,7 +646,7 @@ export default {
646 646 color: rgba(0, 0, 0, 0.6);
647 647 line-height: 32rpx;
648 648 width: 240rpx;
649   - padding: 24rpx 0;
  649 + padding: 12rpx 0;
650 650 }
651 651
652 652 .total-item-price {
... ...
... ... @@ -41,7 +41,7 @@
41 41 </template>
42 42 </uni-list-item>
43 43
44   - <ProductRel mode="add" :orderDateBase="form.orderDate" :list="productLineList" @change="onProductsChange" :options="productList" />
  44 + <ProductRel mode="add" :deliveryDate="form.orderDate" :deliveryDateBase="form.deliveryDate" :list="productLineList" @change="onProductsChange" :options="productList" />
45 45
46 46 <uni-list-item title="合计人民币金额(大写)">
47 47 <template v-slot:footer>
... ... @@ -98,34 +98,25 @@
98 98 :inputBorder="false" />
99 99 </template>
100 100 </uni-list-item>
101   -
102   - <view class="group">
103   - <view class="group-title">特别条款要求</view>
104   - <view class="radio-list">
105   - <view v-for="(opt, i) in specialTermsList" :key="'cr-' + i" class="radio-item"
106   - @click="onRadioSelect('specialTerms', 'specialTermsName', opt)">
107   - <view :class="['radio', { checked: form.specialTerms === opt.value }]" />
108   - <text class="label">{{ opt.label }}</text>
109   - </view>
110   - </view>
111   - </view>
112   - <view class="group">
113   - <view class="group-title">执行标准</view>
114   - <view class="radio-list">
115   - <view v-for="(opt, i) in executionStandardList" :key="'es-' + i" class="radio-item"
116   - @click="onRadioSelect('executionStandard', 'executionStandardName', opt)">
117   - <view :class="['radio', { checked: form.executionStandard === opt.value }]" />
118   - <text class="label">{{ opt.label }}</text>
119   - </view>
120   - </view>
121   - </view>
  101 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  102 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  103 + <template v-slot:body>
  104 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  105 + </template>
  106 + </uni-list-item>
  107 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  108 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  109 + <template v-slot:body>
  110 + <view class="item-title"><text>执行标准</text></view>
  111 + </template>
  112 + </uni-list-item>
122 113 <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
123 114 <template v-slot:footer>
124 115 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注"
125 116 :inputBorder="false" />
126 117 </template>
127 118 </uni-list-item>
128   - <uni-list-item title="特别说明">
  119 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
129 120 <template v-slot:footer>
130 121 <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
131 122 </template>
... ... @@ -177,15 +168,15 @@
177 168 <div class="total-text">合计</div>
178 169 <div class="total-item">
179 170 <div class="total-item-text">数量</div>
180   - <div class="total-item-price">{{ (sumQuantity || 0).toFixed(2) }}t</div>
  171 + <div class="total-item-price">{{ (totalQuantity || 0).toFixed(2) }}kg</div>
181 172 </div>
182   - <div class="total-item">
  173 + <!-- <div class="total-item">
183 174 <div class="total-item-text">不含税金额</div>
184   - <div class="total-item-price text-red">¥{{ (sumAmountExcl || 0).toFixed(2) }}</div>
185   - </div>
  175 + <div class="total-item-price text-red">¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}</div>
  176 + </div> -->
186 177 <div class="total-item">
187 178 <div class="total-item-text">总金额</div>
188   - <div class="total-item-price text-red">¥{{ (sumTotal || 0).toFixed(2) }}</div>
  179 + <div class="total-item-price text-red">¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}</div>
189 180 </div>
190 181 </div>
191 182 <button class="btn submit" type="primary" @click="onSubmit">保存</button>
... ... @@ -223,6 +214,7 @@ export default {
223 214 workshopId: '',
224 215 workshopName: '',
225 216 orderDate: '',
  217 + deliveryDate: '',
226 218 designatedConsignee: '',
227 219 specialTerms: '',
228 220 specialTermsName: '',
... ... @@ -233,7 +225,7 @@ export default {
233 225 includesPackagingFeeName: '',
234 226 includesTransportFee: false,
235 227 includesTransportFeeName: '',
236   - unit: '元、公斤、元/公斤',
  228 + unit: '美元、公斤、美元/公斤',
237 229 totalAmountCapital: '',
238 230 depositInfo: '',
239 231 packagingRequirements: '',
... ... @@ -256,9 +248,9 @@ export default {
256 248 yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
257 249 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
258 250 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
259   - sumQuantity: 0,
260   - sumAmountExcl: 0,
261   - sumTotal: 0,
  251 + totalQuantity: 0,
  252 + // totalAmountExcludingTax: 0,
  253 + totalAmountIncludingTax: 0,
262 254 productLineList: [],
263 255 newProductLineList: [],
264 256 productList: []
... ... @@ -347,11 +339,11 @@ export default {
347 339 const list = Array.isArray(products) ? products : []
348 340 this.newProductLineList = list
349 341 const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
350   - const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
  342 + // const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
351 343 const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
352   - this.sumQuantity = sumQ
353   - this.sumAmountExcl = sumE
354   - this.sumTotal = sumT
  344 + this.totalQuantity = sumQ
  345 + // this.totalAmountExcludingTax = sumE
  346 + this.totalAmountIncludingTax = sumT
355 347 this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
356 348 },
357 349 async loadSuppliers() {
... ... @@ -399,6 +391,10 @@ export default {
399 391 setSheet('生产厂', opts)
400 392 } else if (field === 'supplier') {
401 393 setSheet('供方', this.supplierList)
  394 + } else if (field === 'specialTerms') {
  395 + setSheet('特别条款要求', this.specialTermsList)
  396 + } else if (field === 'executionStandard') {
  397 + setSheet('执行标准', this.executionStandardList)
402 398 } else if (field === 'includesPackagingFee') {
403 399 setSheet('单价中是否已包含包装费', this.yesNoList)
404 400 } else if (field === 'includesTransportFee') {
... ... @@ -443,18 +439,31 @@ export default {
443 439 { key: 'supplier', label: '供方' },
444 440 { key: 'buyer', label: '需方' },
445 441 { key: 'orderDate', label: '订货日期' },
  442 + { key: 'unit', label: '单位' },
446 443 { key: 'workshopId', label: '生产厂' },
  444 + { key: 'specialTerms', label: '特别条款要求' },
447 445 ]
448 446 for (const it of checks) {
449 447 const val = this.form[it.key]
450 448 const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
451 449 if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
452 450 }
453   - if (!Array.isArray(this.productLineList) || this.productLineList.length === 0) {
  451 + const list = Array.isArray(this.newProductLineList) ? this.newProductLineList : []
  452 + if (list.length === 0) {
454 453 uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
455 454 }
456   - for (const [idx, it] of this.productLineList.entries()) {
457   - if (!it.productName || !it.quantity || !it.unitPrice) {
  455 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  456 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  457 + for (const [idx, it] of list.entries()) {
  458 + if (
  459 + strEmpty(it.productName) ||
  460 + strEmpty(it.industry) ||
  461 + strEmpty(it.quality) ||
  462 + strEmpty(it.brand) ||
  463 + numEmpty(it.quantity) ||
  464 + strEmpty(it.unitPrice) ||
  465 + strEmpty(it.deliveryDate)
  466 + ) {
458 467 uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
459 468 }
460 469 }
... ... @@ -486,9 +495,9 @@ export default {
486 495 id: this.form.id,
487 496 destination,
488 497 type: 'INTL_OPEN_SPEC_AGMT',
489   - sumQuantity: this.sumQuantity,
490   - sumAmountExcl: this.sumAmountExcl,
491   - sumTotal: this.sumTotal,
  498 + totalQuantity: this.totalQuantity,
  499 + // totalAmountExcludingTax: this.totalAmountExcludingTax,
  500 + totalAmountIncludingTax: this.totalAmountIncludingTax,
492 501 contractDistributorLineList: lines
493 502 })
494 503 try {
... ... @@ -524,7 +533,7 @@ export default {
524 533 color: rgba(0, 0, 0, 0.6);
525 534 line-height: 32rpx;
526 535 width: 240rpx;
527   - padding: 24rpx 0;
  536 + padding: 12rpx 0;
528 537 }
529 538
530 539 .total-item-price {
... ... @@ -547,7 +556,7 @@ export default {
547 556
548 557 .scroll {
549 558 flex: 1;
550   - padding: 12rpx 0 480rpx !important;
  559 + padding: 12rpx 0 392rpx !important;
551 560 }
552 561
553 562 .footer {
... ...
... ... @@ -53,53 +53,53 @@
53 53 <uni-easyinput v-model="item.quality" :inputBorder="false" placeholder="请输入品质" />
54 54 </template>
55 55 </uni-list-item>
56   - <uni-list-item title="厚度">
  56 + <uni-list-item title="厚度(mm)">
57 57 <template v-slot:footer>
58   - <uni-easyinput v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" />
  58 + <uni-easyinput type="digit" v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" @input="onNonNegativeInput(idx, 'thickness')" @blur="onNonNegativeBlur(idx, 'thickness', 2)" />
59 59 </template>
60 60 </uni-list-item>
61   - <uni-list-item title="厚度公差(单项+)">
  61 + <uni-list-item title="厚度公差上限(mm)">
62 62 <template v-slot:footer>
63   - <uni-easyinput v-model="item.thicknessTolPos" :inputBorder="false"
64   - placeholder="请输入厚度公差(单项+)" />
  63 + <uni-easyinput type="digit" v-model="item.thicknessTolPos" :inputBorder="false"
  64 + placeholder="请输入厚度公差上限" @input="onNonNegativeInput(idx, 'thicknessTolPos')" @blur="onNonNegativeBlur(idx, 'thicknessTolPos', 2)" />
65 65 </template>
66 66 </uni-list-item>
67   - <uni-list-item title="厚度公差(单项-)">
  67 + <uni-list-item title="厚度公差下限(mm)">
68 68 <template v-slot:footer>
69   - <uni-easyinput v-model="item.thicknessTolNeg" :inputBorder="false"
70   - placeholder="请输入厚度公差(单项-)" />
  69 + <uni-easyinput type="digit" v-model="item.thicknessTolNeg" :inputBorder="false"
  70 + placeholder="请输入厚度公差下限" @input="onNonNegativeInput(idx, 'thicknessTolNeg')" @blur="onNonNegativeBlur(idx, 'thicknessTolNeg', 2)" />
71 71 </template>
72 72 </uni-list-item>
73   - <uni-list-item title="宽度">
  73 + <uni-list-item title="宽度(mm)">
74 74 <template v-slot:footer>
75   - <uni-easyinput v-model="item.width" :inputBorder="false" placeholder="请输入宽度" />
  75 + <uni-easyinput type="digit" v-model="item.width" :inputBorder="false" placeholder="请输入宽度" @input="onNonNegativeInput(idx, 'width')" @blur="onNonNegativeBlur(idx, 'width', 2)" />
76 76 </template>
77 77 </uni-list-item>
78   - <uni-list-item title="宽度公差(单项+)">
  78 + <uni-list-item title="宽度公差上限(mm)">
79 79 <template v-slot:footer>
80   - <uni-easyinput v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差(单项+)" />
  80 + <uni-easyinput type="digit" v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差上限" @input="onNonNegativeInput(idx, 'widthTolPos')" @blur="onNonNegativeBlur(idx, 'widthTolPos', 2)" />
81 81 </template>
82 82 </uni-list-item>
83   - <uni-list-item title="宽度公差(单项-)">
  83 + <uni-list-item title="宽度公差下限(mm)">
84 84 <template v-slot:footer>
85   - <uni-easyinput v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差(单项-)" />
  85 + <uni-easyinput type="digit" v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差下限" @input="onNonNegativeInput(idx, 'widthTolNeg')" @blur="onNonNegativeBlur(idx, 'widthTolNeg', 2)" />
86 86 </template>
87 87 </uni-list-item>
88   - <uni-list-item title="长度">
  88 + <uni-list-item title="长度(mm)">
89 89 <template v-slot:footer>
90   - <uni-easyinput v-model="item.length" :inputBorder="false" placeholder="请输入长度" />
  90 + <uni-easyinput type="digit" v-model="item.length" :inputBorder="false" placeholder="请输入长度" @input="onNonNegativeInput(idx, 'length')" @blur="onNonNegativeBlur(idx, 'length', 2)" />
91 91 </template>
92 92 </uni-list-item>
93   - <uni-list-item title="长度公差(单项+)">
  93 + <uni-list-item title="长度公差上限(mm)">
94 94 <template v-slot:footer>
95   - <uni-easyinput v-model="item.lengthTolPos" :inputBorder="false"
96   - placeholder="请输入长度公差(单项+)" />
  95 + <uni-easyinput type="digit" v-model="item.lengthTolPos" :inputBorder="false"
  96 + placeholder="请输入长度公差上限" @input="onNonNegativeInput(idx, 'lengthTolPos')" @blur="onNonNegativeBlur(idx, 'lengthTolPos', 2)" />
97 97 </template>
98 98 </uni-list-item>
99   - <uni-list-item title="长度公差(单项-)">
  99 + <uni-list-item title="长度公差下限(mm)">
100 100 <template v-slot:footer>
101   - <uni-easyinput v-model="item.lengthTolNeg" :inputBorder="false"
102   - placeholder="请输入长度公差(单项-)" />
  101 + <uni-easyinput type="digit" v-model="item.lengthTolNeg" :inputBorder="false"
  102 + placeholder="请输入长度公差下限" @input="onNonNegativeInput(idx, 'lengthTolNeg')" @blur="onNonNegativeBlur(idx, 'lengthTolNeg', 2)" />
103 103 </template>
104 104 </uni-list-item>
105 105 <uni-list-item title="状态">
... ... @@ -109,19 +109,24 @@
109 109 </uni-list-item>
110 110 <uni-list-item title="数量">
111 111 <template v-slot:footer>
112   - <uni-easyinput v-model="item.quantity" type="number" :inputBorder="false" placeholder="请输入数量" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'quantity', 0)" />
  112 + <uni-easyinput v-model="item.quantity" type="digit" :inputBorder="false" placeholder="请输入数量kg" @input="onNonNegativeInput(idx, 'quantity')" @blur="onNonNegativeBlur(idx, 'quantity', 2)" />
113 113 </template>
114 114 </uni-list-item>
115 115 <uni-list-item title="单价">
116 116 <template v-slot:footer>
117   - <uni-easyinput v-model="item.unitPrice" type="number" :inputBorder="false" placeholder="请输入单价" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'unitPrice', 0)" />
  117 + <uni-easyinput v-model="item.unitPrice" type="digit" :inputBorder="false" placeholder="请输入销售价格" @input="onNonNegativeInput(idx, 'unitPrice')" @blur="onNonNegativeBlur(idx, 'unitPrice', 2)" />
118 118 </template>
119 119 </uni-list-item>
120   - <uni-list-item title="不含税金额">
  120 + <uni-list-item title="外贸加工费">
121 121 <template v-slot:footer>
122   - <uni-easyinput v-model="item.amountExcludingTax" type="number" :inputBorder="false" disabled placeholder="自动计算" />
  122 + <uni-easyinput v-model="item.processingFee" type="number" :inputBorder="false" placeholder="请输入外贸加工费" />
123 123 </template>
124 124 </uni-list-item>
  125 + <!-- <uni-list-item title="不含税金额">
  126 + <template v-slot:footer>
  127 + <uni-easyinput v-model="item.amountExcludingTax" type="number" :inputBorder="false" disabled placeholder="自动计算" />
  128 + </template>
  129 + </uni-list-item> -->
125 130 <uni-list-item title="总金额">
126 131 <template v-slot:footer>
127 132 <uni-easyinput v-model="item.totalAmount" type="number" :inputBorder="false" disabled placeholder="自动计算" />
... ... @@ -129,7 +134,7 @@
129 134 </uni-list-item>
130 135 <uni-list-item title="发货日期">
131 136 <template v-slot:footer>
132   - <uni-datetime-picker type="date" v-model="item.orderDate" @change="onDateChange(idx, $event)" />
  137 + <uni-datetime-picker :start="minDeliveryDate" type="date" v-model="item.deliveryDate" @change="onDateChange(idx, $event)" />
133 138 </template>
134 139 </uni-list-item>
135 140 </uni-list>
... ... @@ -151,18 +156,41 @@
151 156 <view class="row"><text class="label">行业</text><text class="value">{{ item.industry }}</text></view>
152 157 <view class="row"><text class="label">牌号</text><text class="value">{{ item.brand }}</text></view>
153 158 <view class="row"><text class="label">品质</text><text class="value">{{ item.quality }}</text></view>
154   - <view class="row"><text class="label">规格</text><text class="value">{{ item.specDisplay }}</text></view>
  159 + <!-- 厚(公差) * 宽(公差) * 长(公差) -->
  160 + <view class="row row-spec"><text class="label">规格(mm)</text>
  161 + <view class="value value-spec">
  162 + <view v-if="item.thickness" class="value-spec_val">{{ item.thickness }}</view>
  163 + <view v-if="item.thickness" class="value-spec_box">
  164 + <view v-if="item.thicknessTolPos" class="value-spec_box_1">+{{ item.thicknessTolPos }}
  165 + </view>
  166 + <view v-if="item.thicknessTolNeg" class="value-spec_box_2">-{{ item.thicknessTolNeg }}
  167 + </view>
  168 + </view>
  169 + <view v-if="item.width" class="value-spec_val p12">*</view>
  170 + <view v-if="item.width" class="value-spec_val">{{ item.width }}</view>
  171 + <view v-if="item.width" class="value-spec_box">
  172 + <view v-if="item.widthTolPos" class="value-spec_box_1">+{{ item.widthTolPos }}</view>
  173 + <view v-if="item.widthTolNeg" class="value-spec_box_2">-{{ item.widthTolNeg }}</view>
  174 + </view>
  175 + <view v-if="item.length" class="value-spec_val p12">*</view>
  176 + <view v-if="item.length" class="value-spec_val">{{ item.length }}</view>
  177 + <view v-if="item.length" class="value-spec_box">
  178 + <view v-if="item.lengthTolPos" class="value-spec_box_1">+{{ item.lengthTolPos }}</view>
  179 + <view v-if="item.lengthTolNeg" class="value-spec_box_2">-{{ item.lengthTolNeg }}</view>
  180 + </view>
  181 + </view>
  182 + </view>
155 183 <view class="row"><text class="label">状态</text><text class="value">{{ item.status }}</text></view>
156 184 <view class="row"><text class="label">数量</text><text class="value">{{ item.quantity }}</text></view>
157 185 <view class="row"><text class="label">单价</text><text class="value">{{ formatCurrency(item.unitPrice)
158 186 }}</text>
159 187 </view>
160   - <view class="row"><text class="label">不含税金额</text><text class="value">{{
  188 + <!-- <view class="row"><text class="label">不含税金额</text><text class="value">{{
161 189 formatCurrency(item.amountExcludingTax)
162   - }}</text></view>
  190 + }}</text></view> -->
163 191 <view class="row"><text class="label">总金额</text><text class="value">{{ formatCurrency(item.totalAmount)
164 192 }}</text></view>
165   - <view class="row"><text class="label">发货日期</text><text class="value">{{ item.orderDate }}</text></view>
  193 + <view class="row"><text class="label">发货日期</text><text class="value">{{ item.deliveryDate }}</text></view>
166 194 </view>
167 195 </view>
168 196 <SingleSelectSheet :visible.sync="sheet.visible" :title="sheet.title" :options="sheet.options" v-model="sheet.value" @confirm="onProductConfirm" />
... ... @@ -176,7 +204,8 @@ export default {
176 204 mode: { type: String, default: 'add' },
177 205 list: { type: Array, default: () => [] },
178 206 max: { type: Number, default: 8 },
179   - orderDateBase: { type: String, default: '' },
  207 + deliveryDateBase: { type: String, default: '' },
  208 + deliveryDate: { type: String, default: '' },
180 209 options: { type: Array, default: () => [] }
181 210 },
182 211 components: { SingleSelectSheet },
... ... @@ -194,6 +223,21 @@ export default {
194 223 label: o.label != null ? o.label : (o.text != null ? o.text : (o.name != null ? o.name : '')),
195 224 value: o.value != null ? o.value : (o.id != null ? o.id : o.productId)
196 225 }))
  226 + },
  227 + minDeliveryDate() {
  228 + const s = this.deliveryDate
  229 + if (!s) return ''
  230 + const parts = String(s).split('-')
  231 + const y = Number(parts[0])
  232 + const m = Number(parts[1])
  233 + const d = Number(parts[2])
  234 + if (!y || !m || !d) return ''
  235 + const dt = new Date(y, m - 1, d)
  236 + dt.setDate(dt.getDate() + 1)
  237 + const yy = dt.getFullYear()
  238 + const mm = String(dt.getMonth() + 1).padStart(2, '0')
  239 + const dd = String(dt.getDate() - 1).padStart(2, '0')
  240 + return `${yy}/${mm}/${dd}`
197 241 }
198 242 },
199 243 watch: {
... ... @@ -218,10 +262,18 @@ export default {
218 262 },
219 263 methods: {
220 264 defaultItem() {
221   - return { productId: '', productName: '', industry: '', brand: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', status: '', quantity: '', unitPrice: '', amountExcludingTax: 0, totalAmount: 0, orderDate: '' }
  265 + return { productId: '', productName: '', industry: '', brand: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', status: '', quantity: '', unitPrice: '', totalAmount: 0, deliveryDate: '' }
222 266 },
223   - onImmediateChange(idx) {
224   - this.$nextTick(() => this.recalculate(idx))
  267 + onNonNegativeInput(idx, field) {
  268 + const it = this.items[idx]
  269 + if (!it) return
  270 + let v = String(it[field] != null ? it[field] : '')
  271 + v = v.replace(/[^0-9.]/g, '')
  272 + v = v.replace(/(\..*)\./g, '$1')
  273 + if (v.startsWith('.')) v = '0' + v
  274 + it[field] = v
  275 + this.$set(this.items, idx, it)
  276 + if (field === 'quantity' || field === 'unitPrice') this.$nextTick(() => this.recalculate(idx))
225 277 },
226 278 toNumber(val) {
227 279 if (typeof val === 'number') return isNaN(val) ? 0 : val
... ... @@ -234,21 +286,21 @@ export default {
234 286 const m = Math.pow(10, digits)
235 287 return Math.round(n * m) / m
236 288 },
237   - onNumberBlur(idx, field, digits) {
  289 + onNonNegativeBlur(idx, field, digits) {
238 290 const it = this.items[idx]
239 291 if (!it) return
240 292 const raw = it[field]
241   - // 如果为空则保持为空,不自动置为0,仅重新计算依赖字段
242 293 if (raw === '' || raw === null || raw === undefined) {
243 294 this.$set(this.items, idx, it)
244   - this.recalculate(idx)
  295 + if (field === 'quantity' || field === 'unitPrice') this.recalculate(idx)
245 296 return
246 297 }
247   - const num = this.toNumber(raw)
  298 + let num = this.toNumber(raw)
  299 + if (isNaN(num) || num < 0) num = 0
248 300 const rounded = this.round(num, digits)
249 301 it[field] = rounded
250 302 this.$set(this.items, idx, it)
251   - this.recalculate(idx)
  303 + if (field === 'quantity' || field === 'unitPrice') this.recalculate(idx)
252 304 },
253 305 formatCurrency(val) {
254 306 if (val == null || val === '') return ''
... ... @@ -286,8 +338,8 @@ export default {
286 338 const qty = this.toNumber(it.quantity)
287 339 const price = this.toNumber(it.unitPrice)
288 340 const total = this.round(qty * price, 2)
289   - const excl = this.round(total / (1 + TAX_RATE), 2)
290   - const next = { ...it, totalAmount: total, amountExcludingTax: excl }
  341 + // const excl = this.round(total / (1 + TAX_RATE), 2)
  342 + const next = { ...it, totalAmount: total }
291 343 this.$set(this.items, idx, next)
292 344 },
293 345 recalculateAll() {
... ... @@ -319,15 +371,15 @@ export default {
319 371 onDateChange(idx, e) {
320 372 const it = this.items[idx]
321 373 if (!it) return
322   - const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.orderDate
  374 + const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.deliveryDate
323 375 const dateStr = String(val).slice(0, 10)
324   - const base = this.orderDateBase ? new Date(this.orderDateBase) : null
  376 + const base = this.deliveryDateBase ? new Date(this.deliveryDateBase) : null
325 377 const d = new Date(dateStr)
326 378 if (base && !isNaN(d.getTime()) && d.getTime() < base.getTime()) {
327 379 uni.showToast({ title: '发货日期不得早于订货日期', icon: 'none' })
328   - it.orderDate = this.orderDateBase
  380 + it.deliveryDate = this.deliveryDateBase
329 381 } else {
330   - it.orderDate = dateStr
  382 + it.deliveryDate = dateStr
331 383 }
332 384 this.$set(this.items, idx, it)
333 385 },
... ... @@ -500,8 +552,46 @@ export default {
500 552
501 553 .value {
502 554 flex: 1;
503   - text-align: right;
  555 + // text-align: right;
504 556 color: rgba(0, 0, 0, 0.9);
505 557 font-size: 28rpx;
506 558 }
  559 + .value-spec {
  560 + height: 48rpx;
  561 + display: flex;
  562 + align-items: center;
  563 + color: #000000;
  564 + // justify-content: end;
  565 + &_box {
  566 + position: relative;
  567 + width: 60rpx;
  568 + height: 48rpx;
  569 +
  570 + &_1 {
  571 + font-size: 16rpx;
  572 + position: absolute;
  573 + top: -10rpx;
  574 + left: 0;
  575 + }
  576 +
  577 + &_2 {
  578 + font-size: 16rpx;
  579 + position: absolute;
  580 + bottom: -10rpx;
  581 + left: 0;
  582 + }
  583 + }
  584 +
  585 + &_val {
  586 + font-size: 28rpx;
  587 +
  588 + &.p12 {
  589 + padding-right: 12rpx;
  590 + }
  591 + }
  592 + }
  593 + .row-spec {
  594 + height: 60rpx;
  595 + align-items: center;
  596 + }
507 597 </style>
... ...
... ... @@ -34,8 +34,7 @@ export default {
34 34 computed: {
35 35 displayButtons() {
36 36 return [
37   - // { text: '删除', variant: 'danger' },
38   - { text: '编辑', variant: 'outline' }
  37 + { text: '编辑', variant: 'outline', visible: this.$auth.hasPermi('contract-manage:contract-framework:modify') }
39 38 ]
40 39 }
41 40 },
... ...
... ... @@ -5,7 +5,7 @@
5 5 <uni-search-bar v-model="searchKeyword" radius="6" placeholder="请输入客户名称或编号" clearButton="auto"
6 6 cancelButton="none" bgColor="#F3F3F3" textColor="rgba(0,0,0,0.4)" @confirm="search" @input="onSearchInput" />
7 7 <view class="tool-icons">
8   - <image class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
  8 + <image v-if="$auth.hasPermi('contract-manage:contract-framework:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
9 9 <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
10 10 </view>
11 11 </view>
... ... @@ -24,7 +24,7 @@
24 24 <text>框架合同编号</text><text>{{ item.code }}</text>
25 25 </view>
26 26 <view class="info-row">
27   - <text>是否签订</text><text>{{ item.hasFrameworkAgreement }}</text>
  27 + <text>是否签订</text><text>{{ item.hasFrameworkAgreement ? '是' : '否' }}</text>
28 28 </view>
29 29 <view class="info-row">
30 30 <text>品种</text><text>{{ item.materialTypeName }}</text>
... ...
... ... @@ -39,7 +39,7 @@
39 39 <view class="item-title"><text class="required">*</text><text>生产厂</text></view>
40 40 </template>
41 41 </uni-list-item>
42   - <!-- <ProductRel mode="add" :orderDateBase="form.orderDate" @change="onProductsChange" :options="productList" :rawToProdRatioList="rawToProdRatioList" /> -->
  42 + <ProductRel mode="add" :deliveryDateBase="form.deliveryDate" :deliveryDate="form.orderDate" @change="onProductsChange" :options="productList" :rawToProdRatioList="rawToProdRatioList" />
43 43 <uni-list-item title="合计人民币金额(大写)">
44 44 <template v-slot:footer>
45 45 <uni-easyinput v-model="form.totalAmountCapital" placeholder="自动计算" :inputBorder="false" disabled />
... ... @@ -92,33 +92,25 @@
92 92 :inputBorder="false" />
93 93 </template>
94 94 </uni-list-item>
95   - <view class="group">
96   - <view class="group-title">特别条款要求</view>
97   - <view class="radio-list">
98   - <view v-for="(opt, i) in specialTermsList" :key="'cr-' + i" class="radio-item"
99   - @click="onRadioSelect('specialTerms', 'specialTermsName', opt)">
100   - <view :class="['radio', { checked: form.specialTerms === opt.value }]" />
101   - <text class="label">{{ opt.label }}</text>
102   - </view>
103   - </view>
104   - </view>
105   - <view class="group">
106   - <view class="group-title">执行标准</view>
107   - <view class="radio-list">
108   - <view v-for="(opt, i) in executionStandardList" :key="'es-' + i" class="radio-item"
109   - @click="onRadioSelect('executionStandard', 'executionStandardName', opt)">
110   - <view :class="['radio', { checked: form.executionStandard === opt.value }]" />
111   - <text class="label">{{ opt.label }}</text>
112   - </view>
113   - </view>
114   - </view>
  95 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  96 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  97 + <template v-slot:body>
  98 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  99 + </template>
  100 + </uni-list-item>
  101 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  102 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  103 + <template v-slot:body>
  104 + <view class="item-title"><text>执行标准</text></view>
  105 + </template>
  106 + </uni-list-item>
115 107 <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
116 108 <template v-slot:footer>
117 109 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注"
118 110 :inputBorder="false" />
119 111 </template>
120 112 </uni-list-item>
121   - <uni-list-item title="特别说明">
  113 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
122 114 <template v-slot:footer>
123 115 <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
124 116 </template>
... ... @@ -181,7 +173,7 @@
181 173 数量
182 174 </div>
183 175 <div class="total-item-price">
184   - {{ (sumQuantity || 0).toFixed(2) }}t
  176 + {{ (totalQuantity || 0).toFixed(2) }}kg
185 177 </div>
186 178 </div>
187 179 <div class="total-item">
... ... @@ -189,7 +181,7 @@
189 181 不含税金额
190 182 </div>
191 183 <div class="total-item-price text-red">
192   - ¥{{ (sumAmountExcl || 0).toFixed(2) }}
  184 + ¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}
193 185 </div>
194 186 </div>
195 187 <div class="total-item">
... ... @@ -197,7 +189,7 @@
197 189 总金额
198 190 </div>
199 191 <div class="total-item-price text-red">
200   - ¥{{ (sumTotal || 0).toFixed(2) }}
  192 + ¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}
201 193 </div>
202 194 </div>
203 195 </div>
... ... @@ -214,7 +206,7 @@
214 206 <script>
215 207 import SingleSelectSheet from '@/components/single-select/index.vue'
216 208 import RelateSelectSheet from '@/components/relate-select/index.vue'
217   -//import ProductRel from './productRel.vue'
  209 +import ProductRel from './productRel.vue'
218 210 import CitySelector from '@/components/city-selector/index.vue'
219 211 import { getRetailCodeApi, createContractApi, getCustomerRemarks,getCustomerSpecificQualityRequirements } from '@/api/contract'
220 212 import { getDicByCodes } from '@/utils/dic'
... ... @@ -223,7 +215,7 @@ import { workshopQueryApi } from '@/api/devManage'
223 215
224 216 export default {
225 217 name: 'AddContractProcess',
226   - components: { SingleSelectSheet, RelateSelectSheet, /* ProductRel, */ CitySelector },
  218 + components: { SingleSelectSheet, RelateSelectSheet, ProductRel, CitySelector },
227 219 data() {
228 220 return {
229 221 form: {
... ... @@ -233,6 +225,7 @@ export default {
233 225 buyer: '',
234 226 buyerName: '',
235 227 orderDate: '',
  228 + deliveryDate: '',
236 229 designatedConsignee: '',
237 230 specialTerms: '',
238 231 specialTermsName: '',
... ... @@ -263,9 +256,9 @@ export default {
263 256 yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
264 257 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
265 258 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
266   - sumQuantity: 0,
267   - sumAmountExcl: 0,
268   - sumTotal: 0,
  259 + totalQuantity: 0,
  260 + totalAmountExcludingTax: 0,
  261 + totalAmountIncludingTax: 0,
269 262 productLineList: [],
270 263 productList: [],
271 264 rawToProdRatioList: [],
... ... @@ -313,8 +306,8 @@ export default {
313 306 const o = Array.isArray(oldVal) ? oldVal : []
314 307 const changed = []
315 308 for (let i = 0; i < n.length; i++) {
316   - const ni = n[i] && n[i].productId
317   - const oi = o[i] && o[i].productId
  309 + const ni = n[i] && n[i].rawProductId
  310 + const oi = o[i] && o[i].rawProductId
318 311 if (ni !== oi && ni !== undefined) changed.push(ni)
319 312 }
320 313 if (changed.length && this.form.buyer) {
... ... @@ -326,11 +319,11 @@ export default {
326 319 },
327 320 methods: {
328 321 getHistory() {
329   - console.log('this.productLineList', this.productLineList[0].productId)
330   - if (!this.productLineList.length || !this.productLineList[0].productId) {
  322 + console.log('this.productLineList', this.productLineList[0].rawProductId)
  323 + if (!this.productLineList.length || !this.productLineList[0].rawProductId) {
331 324 return;
332 325 }
333   - const id = this.productLineList.map(it => it.productId).join('')
  326 + const id = this.productLineList.map(it => it.rawProductId).join('')
334 327 this.fetchCustomerQualityRequirements(id)
335 328 },
336 329 async fetchCustomerQualityRequirements(id) {
... ... @@ -366,12 +359,12 @@ export default {
366 359 },
367 360 onProductsChange(products) {
368 361 const list = Array.isArray(products) ? products : []
369   - const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
  362 + const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.productQuantity) || 0), 0)
370 363 const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
371 364 const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
372   - this.sumQuantity = sumQ
373   - this.sumAmountExcl = sumE
374   - this.sumTotal = sumT
  365 + this.totalQuantity = sumQ
  366 + this.totalAmountExcludingTax = sumE
  367 + this.totalAmountIncludingTax = sumT
375 368 this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
376 369 this.productLineList = list
377 370 },
... ... @@ -450,6 +443,10 @@ export default {
450 443 setSheet('生产厂', opts)
451 444 } else if (field === 'supplier') {
452 445 setSheet('承揽方', this.supplierList)
  446 + } else if (field === 'specialTerms') {
  447 + setSheet('特别条款要求', this.specialTermsList)
  448 + } else if (field === 'executionStandard') {
  449 + setSheet('执行标准', this.executionStandardList)
453 450 } else if (field === 'includesPackagingFee') {
454 451 setSheet('单价中是否已包含包装费', this.yesNoList)
455 452 } else if (field === 'includesTransportFee') {
... ... @@ -520,10 +517,15 @@ export default {
520 517 ...formForSubmit,
521 518 destination,
522 519 type: 'PROCESS_STD_AGMT',
523   - sumQuantity: this.sumQuantity,
524   - sumAmountExcl: this.sumAmountExcl,
525   - sumTotal: this.sumTotal,
526   - contractDistributorLineList: lines
  520 + totalQuantity: this.totalQuantity,
  521 + totalAmountExcludingTax: this.totalAmountExcludingTax,
  522 + totalAmountIncludingTax: this.totalAmountIncludingTax,
  523 + contractStdProcessingLineList: lines.map(it => ({
  524 + ...it,
  525 + productId: it.rawProductId || '',
  526 + productName: it.rawProductName || '',
  527 + productGrade: it.rawProductGrade || '',
  528 + }))
527 529 })
528 530 console.log('onSubmit__payload', payload)
529 531
... ... @@ -542,17 +544,30 @@ export default {
542 544 { key: 'buyer', label: '定作方' },
543 545 { key: 'orderDate', label: '订货日期' },
544 546 { key: 'workshopId', label: '生产厂' },
  547 + { key: 'unit', label: '单位' },
  548 + { key: 'specialTerms', label: '特别条款要求' },
545 549 ]
546 550 for (const it of checks) {
547 551 const val = this.form[it.key]
548 552 const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
549 553 if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
550 554 }
551   - if (!Array.isArray(this.productLineList) || this.productLineList.length === 0) {
  555 + const list = Array.isArray(this.productLineList) ? this.productLineList : []
  556 + if (list.length === 0) {
552 557 uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
553 558 }
554   - for (const [idx, it] of this.productLineList.entries()) {
555   - if (!it.productName || !it.quantity || !it.unitPrice) {
  559 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  560 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  561 + for (const [idx, it] of list.entries()) {
  562 + if (
  563 + strEmpty(it.rawProductName) ||
  564 + strEmpty(it.industry) ||
  565 + strEmpty(it.quality) ||
  566 + strEmpty(it.rawProductGrade) ||
  567 + numEmpty(it.productQuantity) ||
  568 + numEmpty(it.unitPrice) ||
  569 + strEmpty(it.deliveryDate)
  570 + ) {
556 571 uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
557 572 }
558 573 }
... ... @@ -580,7 +595,7 @@ export default {
580 595 color: rgba(0, 0, 0, 0.6);
581 596 line-height: 32rpx;
582 597 width: 240rpx;
583   - padding: 24rpx 0;
  598 + padding: 12rpx 0;
584 599 }
585 600 .total-item-price {
586 601 font-weight: 600;
... ... @@ -602,7 +617,7 @@ export default {
602 617
603 618 .scroll {
604 619 flex: 1;
605   - padding: 12rpx 0 480rpx !important;
  620 + padding: 12rpx 0 392rpx !important;
606 621 }
607 622
608 623 .footer {
... ...
... ... @@ -204,11 +204,11 @@ export default {
204 204 const t = this.detail.standardApproved || false
205 205 const e = this.detail.standardShowExamine || false
206 206 return [
207   - { ...this.buttons[0], visible: (s === 'DRAFT') },
208   - { ...this.buttons[1], visible: (s === 'DRAFT') },
209   - { ...this.buttons[2], visible: (s !== 'DELETED' && t !== 'AUDIT' && t !== 'PASS') },
210   - { ...this.buttons[3], visible: (s === 'STANDARD' && e && t === 'AUDIT') },
211   - { ...this.buttons[4], visible: (s === 'STANDARD') }
  207 + { ...this.buttons[0], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:processed-standard-contract:modify')) },
  208 + { ...this.buttons[1], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:processed-standard-contract:delete')) },
  209 + { ...this.buttons[2], visible: (s !== 'DELETED' && t !== 'AUDIT' && t !== 'PASS' && this.$auth.hasPermi('contract-manage:processed-standard-contract:upload')) },
  210 + { ...this.buttons[3], visible: (s === 'STANDARD' && e && t === 'AUDIT' && this.$auth.hasPermi('contract-manage:processed-standard-contract:approve')) },
  211 + { ...this.buttons[4], visible: (s === 'STANDARD' && this.$auth.hasPermi('contract-manage:processed-standard-contract:review')) }
212 212 ]
213 213 }
214 214 },
... ...
... ... @@ -14,7 +14,7 @@
14 14 @input="onSearchInput"
15 15 />
16 16 <view class="tool-icons">
17   - <image class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
  17 + <image v-if="$auth.hasPermi('contract-manage:processed-standard-contract:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
18 18 <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
19 19 </view>
20 20 </view>
... ... @@ -206,7 +206,7 @@ export default {
206 206 if (!this.batchMode) this.selectedKeys = []
207 207 },
208 208 onAdd() {
209   - uni.showToast({ title: '点击新增', icon: 'none' })
  209 + uni.navigateTo({ url: '/pages/contract_process/add' })
210 210 },
211 211 fetchList({ pageIndex, pageSize, query, extra }) {
212 212 console.log('fetchList', pageIndex, pageSize, query, extra)
... ...
... ... @@ -41,7 +41,7 @@
41 41 </template>
42 42 </uni-list-item>
43 43
44   - <ProductRel mode="add" :orderDateBase="form.orderDate" :list="productLineList" @change="onProductsChange" :options="productList" />
  44 + <ProductRel mode="add" :deliveryDate="form.orderDate" :deliveryDateBase="form.deliveryDate" :list="productLineList" @change="onProductsChange" :options="productList" />
45 45
46 46 <uni-list-item title="合计人民币金额(大写)">
47 47 <template v-slot:footer>
... ... @@ -99,33 +99,25 @@
99 99 </template>
100 100 </uni-list-item>
101 101
102   - <view class="group">
103   - <view class="group-title">特别条款要求</view>
104   - <view class="radio-list">
105   - <view v-for="(opt, i) in specialTermsList" :key="'cr-' + i" class="radio-item"
106   - @click="onRadioSelect('specialTerms', 'specialTermsName', opt)">
107   - <view :class="['radio', { checked: form.specialTerms === opt.value }]" />
108   - <text class="label">{{ opt.label }}</text>
109   - </view>
110   - </view>
111   - </view>
112   - <view class="group">
113   - <view class="group-title">执行标准</view>
114   - <view class="radio-list">
115   - <view v-for="(opt, i) in executionStandardList" :key="'es-' + i" class="radio-item"
116   - @click="onRadioSelect('executionStandard', 'executionStandardName', opt)">
117   - <view :class="['radio', { checked: form.executionStandard === opt.value }]" />
118   - <text class="label">{{ opt.label }}</text>
119   - </view>
120   - </view>
121   - </view>
  102 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  103 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  104 + <template v-slot:body>
  105 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  106 + </template>
  107 + </uni-list-item>
  108 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  109 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  110 + <template v-slot:body>
  111 + <view class="item-title"><text>执行标准</text></view>
  112 + </template>
  113 + </uni-list-item>
122 114 <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
123 115 <template v-slot:footer>
124 116 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注"
125 117 :inputBorder="false" />
126 118 </template>
127 119 </uni-list-item>
128   - <uni-list-item title="特别说明">
  120 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
129 121 <template v-slot:footer>
130 122 <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
131 123 </template>
... ... @@ -177,15 +169,15 @@
177 169 <div class="total-text">合计</div>
178 170 <div class="total-item">
179 171 <div class="total-item-text">数量</div>
180   - <div class="total-item-price">{{ (sumQuantity || 0).toFixed(2) }}t</div>
  172 + <div class="total-item-price">{{ (totalQuantity || 0).toFixed(2) }}kg</div>
181 173 </div>
182 174 <div class="total-item">
183 175 <div class="total-item-text">不含税金额</div>
184   - <div class="total-item-price text-red">¥{{ (sumAmountExcl || 0).toFixed(2) }}</div>
  176 + <div class="total-item-price text-red">¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}</div>
185 177 </div>
186 178 <div class="total-item">
187 179 <div class="total-item-text">总金额</div>
188   - <div class="total-item-price text-red">¥{{ (sumTotal || 0).toFixed(2) }}</div>
  180 + <div class="total-item-price text-red">¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}</div>
189 181 </div>
190 182 </div>
191 183 <button class="btn submit" type="primary" @click="onSubmit">保存</button>
... ... @@ -223,6 +215,7 @@ export default {
223 215 workshopId: '',
224 216 workshopName: '',
225 217 orderDate: '',
  218 + deliveryDate: '',
226 219 designatedConsignee: '',
227 220 specialTerms: '',
228 221 specialTermsName: '',
... ... @@ -256,9 +249,9 @@ export default {
256 249 yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
257 250 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
258 251 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
259   - sumQuantity: 0,
260   - sumAmountExcl: 0,
261   - sumTotal: 0,
  252 + totalQuantity: 0,
  253 + totalAmountExcludingTax: 0,
  254 + totalAmountIncludingTax: 0,
262 255 productLineList: [],
263 256 newProductLineList: [],
264 257 productList: [],
... ... @@ -325,7 +318,7 @@ export default {
325 318 workshopId: m.workshopId || '',
326 319 workshopName: m.workshopName || '',
327 320 }
328   - const lines = Array.isArray(m.contractDistributorLineList) ? m.contractDistributorLineList : []
  321 + const lines = Array.isArray(m.contractStdProcessingLineList) ? m.contractStdProcessingLineList : []
329 322 this.productLineList = lines
330 323 this.onProductsChange(lines)
331 324 } catch (e) { }
... ... @@ -347,12 +340,12 @@ export default {
347 340 onProductsChange(products) {
348 341 const list = Array.isArray(products) ? products : []
349 342 this.newProductLineList = list
350   - const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
  343 + const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.productQuantity) || 0), 0)
351 344 const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
352 345 const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
353   - this.sumQuantity = sumQ
354   - this.sumAmountExcl = sumE
355   - this.sumTotal = sumT
  346 + this.totalQuantity = sumQ
  347 + this.totalAmountExcludingTax = sumE
  348 + this.totalAmountIncludingTax = sumT
356 349 this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
357 350 },
358 351 async loadSuppliers() {
... ... @@ -403,6 +396,10 @@ export default {
403 396 setSheet('生产厂', opts)
404 397 } else if (field === 'supplier') {
405 398 setSheet('承揽方', this.supplierList)
  399 + } else if (field === 'specialTerms') {
  400 + setSheet('特别条款要求', this.specialTermsList)
  401 + } else if (field === 'executionStandard') {
  402 + setSheet('执行标准', this.executionStandardList)
406 403 } else if (field === 'includesPackagingFee') {
407 404 setSheet('单价中是否已包含包装费', this.yesNoList)
408 405 } else if (field === 'includesTransportFee') {
... ... @@ -448,17 +445,30 @@ export default {
448 445 { key: 'buyer', label: '定作方' },
449 446 { key: 'orderDate', label: '订货日期' },
450 447 { key: 'workshopId', label: '生产厂' },
  448 + { key: 'unit', label: '单位' },
  449 + { key: 'specialTerms', label: '特别条款要求' },
451 450 ]
452 451 for (const it of checks) {
453 452 const val = this.form[it.key]
454 453 const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
455 454 if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
456 455 }
457   - if (!Array.isArray(this.productLineList) || this.productLineList.length === 0) {
  456 + const list = Array.isArray(this.newProductLineList) ? this.newProductLineList : []
  457 + if (list.length === 0) {
458 458 uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
459 459 }
460   - for (const [idx, it] of this.productLineList.entries()) {
461   - if (!it.productName || !it.quantity || !it.unitPrice) {
  460 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  461 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  462 + for (const [idx, it] of list.entries()) {
  463 + if (
  464 + strEmpty(it.productName) ||
  465 + strEmpty(it.industry) ||
  466 + strEmpty(it.quality) ||
  467 + strEmpty(it.brand) ||
  468 + numEmpty(it.productQuantity) ||
  469 + strEmpty(it.unitPrice) ||
  470 + strEmpty(it.deliveryDate)
  471 + ) {
462 472 uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
463 473 }
464 474 }
... ... @@ -493,7 +503,7 @@ export default {
493 503 sumQuantity: this.sumQuantity,
494 504 sumAmountExcl: this.sumAmountExcl,
495 505 sumTotal: this.sumTotal,
496   - contractDistributorLineList: lines
  506 + contractStdProcessingLineList: lines
497 507 })
498 508 try {
499 509 await updateContractApi(payload)
... ... @@ -528,7 +538,7 @@ export default {
528 538 color: rgba(0, 0, 0, 0.6);
529 539 line-height: 32rpx;
530 540 width: 240rpx;
531   - padding: 24rpx 0;
  541 + padding: 12rpx 0;
532 542 }
533 543
534 544 .total-item-price {
... ... @@ -551,7 +561,7 @@ export default {
551 561
552 562 .scroll {
553 563 flex: 1;
554   - padding: 12rpx 0 480rpx !important;
  564 + padding: 12rpx 0 392rpx !important;
555 565 }
556 566
557 567 .footer {
... ...
... ... @@ -38,7 +38,7 @@
38 38 <view class="item-title"><text>原材料名称</text></view>
39 39 </template>
40 40 </uni-list-item>
41   - <uni-list-item title="原材料牌号">
  41 + <uni-list-item title="原材料牌号">
42 42 <template v-slot:footer>
43 43 <uni-easyinput v-model="item.rawProductGrade" :inputBorder="false" placeholder="请输入原材料牌号" />
44 44 </template>
... ... @@ -58,74 +58,90 @@
58 58 <uni-easyinput v-model="item.supplyTime" :inputBorder="false" placeholder="请输入原材料提供时间" />
59 59 </template>
60 60 </uni-list-item>
61   - <uni-list-item class="select-item" :class="item.rawToProdRatioName ? 'is-filled' : 'is-empty'" clickable @click="openRawToProdRatioSheet(idx)" :rightText="item.rawToProdRatioName || '请选择原材料到产品的转换比例'" showArrow>
  61 + <uni-list-item class="select-item" :class="item.rawToProdRatioName ? 'is-filled' : 'is-empty'" clickable @click="openRawToProdRatioSheet(idx)" :rightText="item.rawToProdRatioName || '请选择原材料与产品数量比'" showArrow>
  62 + <template v-slot:body>
  63 + <view class="item-title"><text>原材料与产品数量比</text></view>
  64 + </template>
  65 + </uni-list-item>
  66 + <uni-list-item title="原材料与产品数量比备注">
  67 + <template v-slot:footer>
  68 + <uni-easyinput v-model="item.materialProductRatioRemarks" :disabled="item.materialProductRatio !== '10'" :inputBorder="false" placeholder="请输入原材料与产品数量比备注" />
  69 + </template>
  70 + </uni-list-item>
  71 +
  72 + <uni-list-item class="select-item" :class="item.productName ? 'is-filled' : 'is-empty'" clickable @click="openProductTargetSheet(idx)" :rightText="item.productName || '请选择定作物名称'" showArrow>
62 73 <template v-slot:body>
63   - <view class="item-title"><text>原材料到产品的转换比例</text></view>
  74 + <view class="item-title"><text>定作物名称</text></view>
  75 + </template>
  76 + </uni-list-item>
  77 + <uni-list-item title="定作物牌号">
  78 + <template v-slot:footer>
  79 + <uni-easyinput v-model="item.productGrade" :inputBorder="false" placeholder="请输入定作物牌号" />
64 80 </template>
65 81 </uni-list-item>
66   - <uni-list-item title="原材料到产品的转换比例备注">
  82 + <uni-list-item title="状态">
67 83 <template v-slot:footer>
68   - <uni-easyinput v-model="item.materialProductRatioRemarks" :disabled="item.materialProductRatio !== '10'" :inputBorder="false" placeholder="请输入原材料到产品的转换比例备注" />
  84 + <uni-easyinput v-model="item.productStatus" :inputBorder="false" placeholder="请输入状态" />
69 85 </template>
70 86 </uni-list-item>
71 87
72   - <uni-list-item title="厚度">
  88 + <uni-list-item title="厚度(mm)">
73 89 <template v-slot:footer>
74   - <uni-easyinput v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" />
  90 + <uni-easyinput type="digit" v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" @input="onNonNegativeInput(idx, 'thickness')" @blur="onNonNegativeBlur(idx, 'thickness', 2)" />
75 91 </template>
76 92 </uni-list-item>
77   - <uni-list-item title="厚度公差(单项+)">
  93 + <uni-list-item title="厚度公差上限(mm)">
78 94 <template v-slot:footer>
79   - <uni-easyinput v-model="item.thicknessTolPos" :inputBorder="false"
80   - placeholder="请输入厚度公差(单项+)" />
  95 + <uni-easyinput type="digit" v-model="item.thicknessTolPos" :inputBorder="false"
  96 + placeholder="请输入厚度公差上限" @input="onNonNegativeInput(idx, 'thicknessTolPos')" @blur="onNonNegativeBlur(idx, 'thicknessTolPos', 2)" />
81 97 </template>
82 98 </uni-list-item>
83   - <uni-list-item title="厚度公差(单项-)">
  99 + <uni-list-item title="厚度公差下限(mm)">
84 100 <template v-slot:footer>
85   - <uni-easyinput v-model="item.thicknessTolNeg" :inputBorder="false"
86   - placeholder="请输入厚度公差(单项-)" />
  101 + <uni-easyinput type="digit" v-model="item.thicknessTolNeg" :inputBorder="false"
  102 + placeholder="请输入厚度公差下限" @input="onNonNegativeInput(idx, 'thicknessTolNeg')" @blur="onNonNegativeBlur(idx, 'thicknessTolNeg', 2)" />
87 103 </template>
88 104 </uni-list-item>
89   - <uni-list-item title="宽度">
  105 + <uni-list-item title="宽度(mm)">
90 106 <template v-slot:footer>
91   - <uni-easyinput v-model="item.width" :inputBorder="false" placeholder="请输入宽度" />
  107 + <uni-easyinput type="digit" v-model="item.width" :inputBorder="false" placeholder="请输入宽度" @input="onNonNegativeInput(idx, 'width')" @blur="onNonNegativeBlur(idx, 'width', 2)" />
92 108 </template>
93 109 </uni-list-item>
94   - <uni-list-item title="宽度公差(单项+)">
  110 + <uni-list-item title="宽度公差上限(mm)">
95 111 <template v-slot:footer>
96   - <uni-easyinput v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差(单项+)" />
  112 + <uni-easyinput type="digit" v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差上限" @input="onNonNegativeInput(idx, 'widthTolPos')" @blur="onNonNegativeBlur(idx, 'widthTolPos', 2)" />
97 113 </template>
98 114 </uni-list-item>
99   - <uni-list-item title="宽度公差(单项-)">
  115 + <uni-list-item title="宽度公差下限(mm)">
100 116 <template v-slot:footer>
101   - <uni-easyinput v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差(单项-)" />
  117 + <uni-easyinput type="digit" v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差下限" @input="onNonNegativeInput(idx, 'widthTolNeg')" @blur="onNonNegativeBlur(idx, 'widthTolNeg', 2)" />
102 118 </template>
103 119 </uni-list-item>
104   - <uni-list-item title="长度">
  120 + <uni-list-item title="长度(mm)">
105 121 <template v-slot:footer>
106   - <uni-easyinput v-model="item.length" :inputBorder="false" placeholder="请输入长度" />
  122 + <uni-easyinput type="digit" v-model="item.length" :inputBorder="false" placeholder="请输入长度" @input="onNonNegativeInput(idx, 'length')" @blur="onNonNegativeBlur(idx, 'length', 2)" />
107 123 </template>
108 124 </uni-list-item>
109   - <uni-list-item title="长度公差(单项+)">
  125 + <uni-list-item title="长度公差上限(mm)">
110 126 <template v-slot:footer>
111   - <uni-easyinput v-model="item.lengthTolPos" :inputBorder="false"
112   - placeholder="请输入长度公差(单项+)" />
  127 + <uni-easyinput type="digit" v-model="item.lengthTolPos" :inputBorder="false"
  128 + placeholder="请输入长度公差上限" @input="onNonNegativeInput(idx, 'lengthTolPos')" @blur="onNonNegativeBlur(idx, 'lengthTolPos', 2)" />
113 129 </template>
114 130 </uni-list-item>
115   - <uni-list-item title="长度公差(单项-)">
  131 + <uni-list-item title="长度公差下限(mm)">
116 132 <template v-slot:footer>
117   - <uni-easyinput v-model="item.lengthTolNeg" :inputBorder="false"
118   - placeholder="请输入长度公差(单项-)" />
  133 + <uni-easyinput type="digit" v-model="item.lengthTolNeg" :inputBorder="false"
  134 + placeholder="请输入长度公差下限" @input="onNonNegativeInput(idx, 'lengthTolNeg')" @blur="onNonNegativeBlur(idx, 'lengthTolNeg', 2)" />
119 135 </template>
120 136 </uni-list-item>
121   - <uni-list-item title="定物数量">
  137 + <uni-list-item title="定物数量">
122 138 <template v-slot:footer>
123   - <uni-easyinput v-model="item.productQuantity" type="number" :inputBorder="false" placeholder="请输入数量" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'productQuantity', 0)" />
  139 + <uni-easyinput v-model="item.productQuantity" type="digit" :inputBorder="false" placeholder="请输入数量kg" @input="onNonNegativeInput(idx, 'productQuantity')" @blur="onNonNegativeBlur(idx, 'productQuantity', 2)" />
124 140 </template>
125 141 </uni-list-item>
126 142 <uni-list-item title="加工费单价">
127 143 <template v-slot:footer>
128   - <uni-easyinput v-model="item.unitPrice" type="number" :inputBorder="false" placeholder="请输入单价" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'unitPrice', 0)" />
  144 + <uni-easyinput v-model="item.unitPrice" type="digit" :inputBorder="false" placeholder="请输入销售价格" @input="onNonNegativeInput(idx, 'unitPrice')" @blur="onNonNegativeBlur(idx, 'unitPrice', 2)" />
129 145 </template>
130 146 </uni-list-item>
131 147 <uni-list-item title="不含税金额">
... ... @@ -140,7 +156,7 @@
140 156 </uni-list-item>
141 157 <uni-list-item title="发货日期">
142 158 <template v-slot:footer>
143   - <uni-datetime-picker type="date" v-model="item.orderDate" @change="onDateChange(idx, $event)" />
  159 + <uni-datetime-picker :start="minDeliveryDate" type="date" v-model="item.deliveryDate" @change="onDateChange(idx, $event)" />
144 160 </template>
145 161 </uni-list-item>
146 162 </uni-list>
... ... @@ -161,10 +177,33 @@
161 177 <view class="row"><text class="label">原材料名称</text><text class="value">{{ item.rawProductName }}</text></view>
162 178 <view class="row"><text class="label">原材料牌号</text><text class="value">{{ item.rawProductGrade }}</text></view>
163 179 <view class="row"><text class="label">原材料提供时间</text><text class="value">{{ item.rawProductProvideDate }}</text></view>
164   - <view class="row"><text class="label">原材料到产品的转换比例</text><text class="value">{{ item.rawToProdRatioName }}</text></view>
  180 + <view class="row"><text class="label">原材料产品数量比</text><text class="value">{{ item.rawToProdRatioName }}</text></view>
165 181 <view class="row"><text class="label">行业</text><text class="value">{{ item.industry }}</text></view>
166 182 <view class="row"><text class="label">品质</text><text class="value">{{ item.quality }}</text></view>
167   - <view class="row"><text class="label">规格</text><text class="value">{{ item.specDisplay }}</text></view>
  183 + <!-- 厚(公差) * 宽(公差) * 长(公差) -->
  184 + <view class="row row-spec"><text class="label">规格(mm)</text>
  185 + <view class="value value-spec">
  186 + <view v-if="item.thickness" class="value-spec_val">{{ item.thickness }}</view>
  187 + <view v-if="item.thickness" class="value-spec_box">
  188 + <view v-if="item.thicknessTolPos" class="value-spec_box_1">+{{ item.thicknessTolPos }}
  189 + </view>
  190 + <view v-if="item.thicknessTolNeg" class="value-spec_box_2">-{{ item.thicknessTolNeg }}
  191 + </view>
  192 + </view>
  193 + <view v-if="item.width" class="value-spec_val p12">*</view>
  194 + <view v-if="item.width" class="value-spec_val">{{ item.width }}</view>
  195 + <view v-if="item.width" class="value-spec_box">
  196 + <view v-if="item.widthTolPos" class="value-spec_box_1">+{{ item.widthTolPos }}</view>
  197 + <view v-if="item.widthTolNeg" class="value-spec_box_2">-{{ item.widthTolNeg }}</view>
  198 + </view>
  199 + <view v-if="item.length" class="value-spec_val p12">*</view>
  200 + <view v-if="item.length" class="value-spec_val">{{ item.length }}</view>
  201 + <view v-if="item.length" class="value-spec_box">
  202 + <view v-if="item.lengthTolPos" class="value-spec_box_1">+{{ item.lengthTolPos }}</view>
  203 + <view v-if="item.lengthTolNeg" class="value-spec_box_2">-{{ item.lengthTolNeg }}</view>
  204 + </view>
  205 + </view>
  206 + </view>
168 207 <view class="row"><text class="label">定做物数量</text><text class="value">{{ item.productQuantity }}</text></view>
169 208 <view class="row"><text class="label">加工费单价</text><text class="value">{{ formatCurrency(item.unitPrice)
170 209 }}</text>
... ... @@ -174,7 +213,7 @@
174 213 }}</text></view>
175 214 <view class="row"><text class="label">总金额</text><text class="value">{{ formatCurrency(item.totalAmount)
176 215 }}</text></view>
177   - <view class="row"><text class="label">发货日期</text><text class="value">{{ item.orderDate }}</text></view>
  216 + <view class="row"><text class="label">发货日期</text><text class="value">{{ item.deliveryDate }}</text></view>
178 217 </view>
179 218 </view>
180 219 <SingleSelectSheet :visible.sync="sheet.visible" :title="sheet.title" :options="sheet.options" v-model="sheet.value" @confirm="onProductConfirm" />
... ... @@ -188,8 +227,9 @@ export default {
188 227 mode: { type: String, default: 'add' },
189 228 list: { type: Array, default: () => [] },
190 229 max: { type: Number, default: 8 },
191   - orderDateBase: { type: String, default: '' },
  230 + deliveryDateBase: { type: String, default: '' },
192 231 options: { type: Array, default: () => [] },
  232 + deliveryDate: { type: String, default: '' },
193 233 rawToProdRatioList: { type: Array, default: () => [] }
194 234 },
195 235 components: { SingleSelectSheet },
... ... @@ -207,14 +247,28 @@ export default {
207 247 label: o.label != null ? o.label : (o.text != null ? o.text : (o.name != null ? o.name : '')),
208 248 value: o.value != null ? o.value : (o.id != null ? o.id : o.rawProductId)
209 249 }))
210   - }
211   - ,
  250 + },
212 251 ratioOptions() {
213 252 const list = Array.isArray(this.rawToProdRatioList) ? this.rawToProdRatioList : []
214 253 return list.map(o => ({
215 254 label: o.label != null ? o.label : (o.text != null ? o.text : (o.name != null ? o.name : '')),
216 255 value: o.value != null ? o.value : (o.id != null ? o.id : o.code)
217 256 }))
  257 + },
  258 + minDeliveryDate() {
  259 + const s = this.deliveryDate
  260 + if (!s) return ''
  261 + const parts = String(s).split('-')
  262 + const y = Number(parts[0])
  263 + const m = Number(parts[1])
  264 + const d = Number(parts[2])
  265 + if (!y || !m || !d) return ''
  266 + const dt = new Date(y, m - 1, d)
  267 + dt.setDate(dt.getDate() + 1)
  268 + const yy = dt.getFullYear()
  269 + const mm = String(dt.getMonth() + 1).padStart(2, '0')
  270 + const dd = String(dt.getDate() - 1).padStart(2, '0')
  271 + return `${yy}/${mm}/${dd}`
218 272 }
219 273 },
220 274 watch: {
... ... @@ -239,7 +293,34 @@ export default {
239 293 },
240 294 methods: {
241 295 defaultItem() {
242   - return { rawProductId: '', rawProductName: '', rawProductGrade: '', industry: '',materialProductRatioRemarks:'', supplyTime: '存料加工', materialProductRatio: '', rawToProdRatioName: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', productQuantity: '', unitPrice: '', amountExcludingTax: 0, totalAmount: 0, orderDate: '' }
  296 + return { productId:'', productName:'', productGrade:'', productStatus:'', rawProductId: '', rawProductName: '', rawProductGrade: '', industry: '',materialProductRatioRemarks:'', supplyTime: '存料加工', materialProductRatio: '', rawToProdRatioName: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', productQuantity: '', unitPrice: '', amountExcludingTax: 0, totalAmount: 0, deliveryDate: '' }
  297 + },
  298 + onNonNegativeInput(idx, field) {
  299 + const it = this.items[idx]
  300 + if (!it) return
  301 + let v = String(it[field] != null ? it[field] : '')
  302 + v = v.replace(/[^0-9.]/g, '')
  303 + v = v.replace(/(\..*)\./g, '$1')
  304 + if (v.startsWith('.')) v = '0' + v
  305 + it[field] = v
  306 + this.$set(this.items, idx, it)
  307 + if (field === 'productQuantity' || field === 'unitPrice') this.$nextTick(() => this.recalculate(idx))
  308 + },
  309 + onNonNegativeBlur(idx, field, digits) {
  310 + const it = this.items[idx]
  311 + if (!it) return
  312 + const raw = it[field]
  313 + if (raw === '' || raw === null || raw === undefined) {
  314 + this.$set(this.items, idx, it)
  315 + if (field === 'productQuantity' || field === 'unitPrice') this.recalculate(idx)
  316 + return
  317 + }
  318 + let num = this.toNumber(raw)
  319 + if (isNaN(num) || num < 0) num = 0
  320 + const rounded = this.round(num, digits)
  321 + it[field] = rounded
  322 + this.$set(this.items, idx, it)
  323 + if (field === 'productQuantity' || field === 'unitPrice') this.recalculate(idx)
243 324 },
244 325 onImmediateChange(idx) {
245 326 this.$nextTick(() => this.recalculate(idx))
... ... @@ -290,6 +371,12 @@ export default {
290 371 const match = opts.find(o => String(o.value) === String(current))
291 372 this.sheet = { ...this.sheet, visible: true, title: '请选择原材料名称', options: opts, idx, value: match ? match.value : '', mode: 'product' }
292 373 },
  374 + openProductTargetSheet(idx) {
  375 + const opts = this.selectOptions
  376 + const current = this.items[idx] && this.items[idx].productId
  377 + const match = opts.find(o => String(o.value) === String(current))
  378 + this.sheet = { ...this.sheet, visible: true, title: '请选择定作物名称', options: opts, idx, value: match ? match.value : '', mode: 'target' }
  379 + },
293 380 openRawToProdRatioSheet(idx) {
294 381 const opts = this.ratioOptions
295 382 const current = this.items[idx] && this.items[idx].materialProductRatio
... ... @@ -303,9 +390,12 @@ export default {
303 390 if (this.sheet.mode === 'ratio') {
304 391 it.materialProductRatio = value
305 392 it.rawToProdRatioName = label || ''
306   - } else {
  393 + } else if (this.sheet.mode === 'product') {
307 394 it.rawProductId = value
308 395 it.rawProductName = label || ''
  396 + } else if (this.sheet.mode === 'target') {
  397 + it.productId = value
  398 + it.productName = label || ''
309 399 }
310 400 this.$set(this.items, idx, it)
311 401 this.sheet.visible = false
... ... @@ -351,15 +441,15 @@ export default {
351 441 onDateChange(idx, e) {
352 442 const it = this.items[idx]
353 443 if (!it) return
354   - const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.orderDate
  444 + const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.deliveryDate
355 445 const dateStr = String(val).slice(0, 10)
356   - const base = this.orderDateBase ? new Date(this.orderDateBase) : null
  446 + const base = this.deliveryDateBase ? new Date(this.deliveryDateBase) : null
357 447 const d = new Date(dateStr)
358 448 if (base && !isNaN(d.getTime()) && d.getTime() < base.getTime()) {
359 449 uni.showToast({ title: '发货日期不得早于订货日期', icon: 'none' })
360   - it.orderDate = this.orderDateBase
  450 + it.deliveryDate = this.deliveryDateBase
361 451 } else {
362   - it.orderDate = dateStr
  452 + it.deliveryDate = dateStr
363 453 }
364 454 this.$set(this.items, idx, it)
365 455 },
... ... @@ -532,8 +622,45 @@ export default {
532 622
533 623 .value {
534 624 flex: 1;
535   - text-align: right;
536 625 color: rgba(0, 0, 0, 0.9);
537 626 font-size: 28rpx;
538 627 }
  628 + .value-spec {
  629 + height: 48rpx;
  630 + display: flex;
  631 + align-items: center;
  632 + color: #000000;
  633 + // justify-content: end;
  634 + &_box {
  635 + position: relative;
  636 + width: 60rpx;
  637 + height: 48rpx;
  638 +
  639 + &_1 {
  640 + font-size: 16rpx;
  641 + position: absolute;
  642 + top: -10rpx;
  643 + left: 0;
  644 + }
  645 +
  646 + &_2 {
  647 + font-size: 16rpx;
  648 + position: absolute;
  649 + bottom: -10rpx;
  650 + left: 0;
  651 + }
  652 + }
  653 +
  654 + &_val {
  655 + font-size: 28rpx;
  656 +
  657 + &.p12 {
  658 + padding-right: 12rpx;
  659 + }
  660 + }
  661 + }
  662 + .row-spec {
  663 + height: 60rpx;
  664 + align-items: center;
  665 + }
539 666 </style>
... ...
... ... @@ -39,7 +39,7 @@
39 39 <view class="item-title"><text class="required">*</text><text>生产厂</text></view>
40 40 </template>
41 41 </uni-list-item>
42   - <ProductRel mode="add" :orderDateBase="form.orderDate" @change="onProductsChange" :options="productList" />
  42 + <ProductRel mode="add" :deliveryDateBase="form.deliveryDate" :deliveryDate="form.orderDate" @change="onProductsChange" :options="productList" />
43 43 <uni-list-item title="合计人民币金额(大写)">
44 44 <template v-slot:footer>
45 45 <uni-easyinput v-model="form.totalAmountCapital" placeholder="自动计算" :inputBorder="false" disabled />
... ... @@ -92,33 +92,25 @@
92 92 :inputBorder="false" />
93 93 </template>
94 94 </uni-list-item>
95   - <view class="group">
96   - <view class="group-title">特别条款要求</view>
97   - <view class="radio-list">
98   - <view v-for="(opt, i) in specialTermsList" :key="'cr-' + i" class="radio-item"
99   - @click="onRadioSelect('specialTerms', 'specialTermsName', opt)">
100   - <view :class="['radio', { checked: form.specialTerms === opt.value }]" />
101   - <text class="label">{{ opt.label }}</text>
102   - </view>
103   - </view>
104   - </view>
105   - <view class="group">
106   - <view class="group-title">执行标准</view>
107   - <view class="radio-list">
108   - <view v-for="(opt, i) in executionStandardList" :key="'es-' + i" class="radio-item"
109   - @click="onRadioSelect('executionStandard', 'executionStandardName', opt)">
110   - <view :class="['radio', { checked: form.executionStandard === opt.value }]" />
111   - <text class="label">{{ opt.label }}</text>
112   - </view>
113   - </view>
114   - </view>
  95 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  96 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  97 + <template v-slot:body>
  98 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  99 + </template>
  100 + </uni-list-item>
  101 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  102 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  103 + <template v-slot:body>
  104 + <view class="item-title"><text>执行标准</text></view>
  105 + </template>
  106 + </uni-list-item>
115 107 <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
116 108 <template v-slot:footer>
117 109 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注"
118 110 :inputBorder="false" />
119 111 </template>
120 112 </uni-list-item>
121   - <uni-list-item title="特别说明">
  113 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
122 114 <template v-slot:footer>
123 115 <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
124 116 </template>
... ... @@ -181,7 +173,7 @@
181 173 数量
182 174 </div>
183 175 <div class="total-item-price">
184   - {{ (sumQuantity || 0).toFixed(2) }}t
  176 + {{ (totalQuantity || 0).toFixed(2) }}kg
185 177 </div>
186 178 </div>
187 179 <div class="total-item">
... ... @@ -189,7 +181,7 @@
189 181 不含税金额
190 182 </div>
191 183 <div class="total-item-price text-red">
192   - ¥{{ (sumAmountExcl || 0).toFixed(2) }}
  184 + ¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}
193 185 </div>
194 186 </div>
195 187 <div class="total-item">
... ... @@ -197,7 +189,7 @@
197 189 总金额
198 190 </div>
199 191 <div class="total-item-price text-red">
200   - ¥{{ (sumTotal || 0).toFixed(2) }}
  192 + ¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}
201 193 </div>
202 194 </div>
203 195 </div>
... ... @@ -233,6 +225,7 @@ export default {
233 225 buyer: '',
234 226 buyerName: '',
235 227 orderDate: '',
  228 + deliveryDate: '',
236 229 designatedConsignee: '',
237 230 specialTerms: '',
238 231 specialTermsName: '',
... ... @@ -263,9 +256,9 @@ export default {
263 256 yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
264 257 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
265 258 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
266   - sumQuantity: 0,
267   - sumAmountExcl: 0,
268   - sumTotal: 0,
  259 + totalQuantity: 0,
  260 + totalAmountExcludingTax: 0,
  261 + totalAmountIncludingTax: 0,
269 262 productLineList: [],
270 263 productList: [],
271 264 customerRemarks: [],
... ... @@ -369,9 +362,9 @@ export default {
369 362 const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
370 363 const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
371 364 const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
372   - this.sumQuantity = sumQ
373   - this.sumAmountExcl = sumE
374   - this.sumTotal = sumT
  365 + this.totalQuantity = sumQ
  366 + this.totalAmountExcludingTax = sumE
  367 + this.totalAmountIncludingTax = sumT
375 368 this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
376 369 this.productLineList = list
377 370 },
... ... @@ -447,6 +440,10 @@ export default {
447 440 setSheet('生产厂', opts)
448 441 } else if (field === 'supplier') {
449 442 setSheet('供方', this.supplierList)
  443 + } else if (field === 'specialTerms') {
  444 + setSheet('特别条款要求', this.specialTermsList)
  445 + } else if (field === 'executionStandard') {
  446 + setSheet('执行标准', this.executionStandardList)
450 447 } else if (field === 'includesPackagingFee') {
451 448 setSheet('单价中是否已包含包装费', this.yesNoList)
452 449 } else if (field === 'includesTransportFee') {
... ... @@ -517,9 +514,9 @@ export default {
517 514 ...formForSubmit,
518 515 destination,
519 516 type: 'DISTRIB_STD',
520   - sumQuantity: this.sumQuantity,
521   - sumAmountExcl: this.sumAmountExcl,
522   - sumTotal: this.sumTotal,
  517 + totalQuantity: this.totalQuantity,
  518 + totalAmountExcludingTax: this.totalAmountExcludingTax,
  519 + totalAmountIncludingTax: this.totalAmountIncludingTax,
523 520 contractDistributorLineList: lines
524 521 })
525 522 console.log('onSubmit__payload', payload)
... ... @@ -538,18 +535,31 @@ export default {
538 535 { key: 'supplier', label: '供方' },
539 536 { key: 'buyer', label: '需方' },
540 537 { key: 'orderDate', label: '订货日期' },
  538 + { key: 'unit', label: '单位' },
541 539 { key: 'workshopId', label: '生产厂' },
  540 + { key: 'specialTerms', label: '特别条款要求' },
542 541 ]
543 542 for (const it of checks) {
544 543 const val = this.form[it.key]
545 544 const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
546 545 if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
547 546 }
548   - if (!Array.isArray(this.productLineList) || this.productLineList.length === 0) {
  547 + const list = Array.isArray(this.productLineList) ? this.productLineList : []
  548 + if (list.length === 0) {
549 549 uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
550 550 }
551   - for (const [idx, it] of this.productLineList.entries()) {
552   - if (!it.productName || !it.quantity || !it.unitPrice) {
  551 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  552 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  553 + for (const [idx, it] of list.entries()) {
  554 + if (
  555 + strEmpty(it.productName) ||
  556 + strEmpty(it.industry) ||
  557 + strEmpty(it.quality) ||
  558 + strEmpty(it.brand) ||
  559 + numEmpty(it.quantity) ||
  560 + numEmpty(it.unitPrice) ||
  561 + strEmpty(it.deliveryDate)
  562 + ) {
553 563 uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
554 564 }
555 565 }
... ... @@ -577,7 +587,7 @@ export default {
577 587 color: rgba(0, 0, 0, 0.6);
578 588 line-height: 32rpx;
579 589 width: 240rpx;
580   - padding: 24rpx 0;
  590 + padding: 12rpx 0;
581 591 }
582 592 .total-item-price {
583 593 font-weight: 600;
... ... @@ -599,7 +609,7 @@ export default {
599 609
600 610 .scroll {
601 611 flex: 1;
602   - padding: 12rpx 0 480rpx !important;
  612 + padding: 12rpx 0 392rpx !important;
603 613 }
604 614
605 615 .footer {
... ...
... ... @@ -206,11 +206,11 @@ export default {
206 206 const t = this.detail.standardApproved || ''
207 207 const e = this.detail.standardShowExamine || false
208 208 return [
209   - { ...this.buttons[0], visible: (s === 'DRAFT') },
210   - { ...this.buttons[1], visible: (s === 'DRAFT') },
211   - { ...this.buttons[2], visible: (s !== 'DELETED' && t !== 'AUDIT' && t !== 'PASS') },
212   - { ...this.buttons[3], visible: (s === 'STANDARD' && e && t === 'AUDIT') },
213   - { ...this.buttons[4], visible: (s === 'STANDARD') }
  209 + { ...this.buttons[0], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:distribution-standard-contract:modify')) },
  210 + { ...this.buttons[1], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:distribution-standard-contract:delete')) },
  211 + { ...this.buttons[2], visible: (s !== 'DELETED' && t !== 'AUDIT' && t !== 'PASS' && this.$auth.hasPermi('contract-manage:distribution-standard-contract:upload')) },
  212 + { ...this.buttons[3], visible: (s === 'STANDARD' && e && t === 'AUDIT' && this.$auth.hasPermi('contract-manage:distribution-standard-contract:approve')) },
  213 + { ...this.buttons[4], visible: (s === 'STANDARD' && this.$auth.hasPermi('contract-manage:distribution-standard-contract:review')) }
214 214 ]
215 215 }
216 216 },
... ...
... ... @@ -14,7 +14,7 @@
14 14 @input="onSearchInput"
15 15 />
16 16 <view class="tool-icons">
17   - <image class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
  17 + <image v-if="$auth.hasPermi('contract-manage:distribution-standard-contract:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
18 18 <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
19 19 </view>
20 20 </view>
... ...
... ... @@ -41,7 +41,7 @@
41 41 </template>
42 42 </uni-list-item>
43 43
44   - <ProductRel mode="add" :orderDateBase="form.orderDate" :list="productLineList" @change="onProductsChange" :options="productList" />
  44 + <ProductRel mode="add" :deliveryDateBase="form.deliveryDate" :deliveryDate="form.orderDate" :list="productLineList" @change="onProductsChange" :options="productList" />
45 45
46 46 <uni-list-item title="合计人民币金额(大写)">
47 47 <template v-slot:footer>
... ... @@ -99,33 +99,25 @@
99 99 </template>
100 100 </uni-list-item>
101 101
102   - <view class="group">
103   - <view class="group-title">特别条款要求</view>
104   - <view class="radio-list">
105   - <view v-for="(opt, i) in specialTermsList" :key="'cr-' + i" class="radio-item"
106   - @click="onRadioSelect('specialTerms', 'specialTermsName', opt)">
107   - <view :class="['radio', { checked: form.specialTerms === opt.value }]" />
108   - <text class="label">{{ opt.label }}</text>
109   - </view>
110   - </view>
111   - </view>
112   - <view class="group">
113   - <view class="group-title">执行标准</view>
114   - <view class="radio-list">
115   - <view v-for="(opt, i) in executionStandardList" :key="'es-' + i" class="radio-item"
116   - @click="onRadioSelect('executionStandard', 'executionStandardName', opt)">
117   - <view :class="['radio', { checked: form.executionStandard === opt.value }]" />
118   - <text class="label">{{ opt.label }}</text>
119   - </view>
120   - </view>
121   - </view>
  102 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  103 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  104 + <template v-slot:body>
  105 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  106 + </template>
  107 + </uni-list-item>
  108 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  109 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  110 + <template v-slot:body>
  111 + <view class="item-title"><text>执行标准</text></view>
  112 + </template>
  113 + </uni-list-item>
122 114 <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
123 115 <template v-slot:footer>
124 116 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注"
125 117 :inputBorder="false" />
126 118 </template>
127 119 </uni-list-item>
128   - <uni-list-item title="特别说明">
  120 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
129 121 <template v-slot:footer>
130 122 <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
131 123 </template>
... ... @@ -177,15 +169,15 @@
177 169 <div class="total-text">合计</div>
178 170 <div class="total-item">
179 171 <div class="total-item-text">数量</div>
180   - <div class="total-item-price">{{ (sumQuantity || 0).toFixed(2) }}t</div>
  172 + <div class="total-item-price">{{ (totalQuantity || 0).toFixed(2) }}kg</div>
181 173 </div>
182 174 <div class="total-item">
183 175 <div class="total-item-text">不含税金额</div>
184   - <div class="total-item-price text-red">¥{{ (sumAmountExcl || 0).toFixed(2) }}</div>
  176 + <div class="total-item-price text-red">¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}</div>
185 177 </div>
186 178 <div class="total-item">
187 179 <div class="total-item-text">总金额</div>
188   - <div class="total-item-price text-red">¥{{ (sumTotal || 0).toFixed(2) }}</div>
  180 + <div class="total-item-price text-red">¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}</div>
189 181 </div>
190 182 </div>
191 183 <button class="btn submit" type="primary" @click="onSubmit">保存</button>
... ... @@ -223,6 +215,7 @@ export default {
223 215 workshopId: '',
224 216 workshopName: '',
225 217 orderDate: '',
  218 + deliveryDate: '',
226 219 designatedConsignee: '',
227 220 specialTerms: '',
228 221 specialTermsName: '',
... ... @@ -256,9 +249,9 @@ export default {
256 249 yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
257 250 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
258 251 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
259   - sumQuantity: 0,
260   - sumAmountExcl: 0,
261   - sumTotal: 0,
  252 + totalQuantity: 0,
  253 + totalAmountExcludingTax: 0,
  254 + totalAmountIncludingTax: 0,
262 255 productLineList: [],
263 256 newProductLineList: [],
264 257 productList: []
... ... @@ -349,9 +342,9 @@ export default {
349 342 const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
350 343 const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
351 344 const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
352   - this.sumQuantity = sumQ
353   - this.sumAmountExcl = sumE
354   - this.sumTotal = sumT
  345 + this.totalQuantity = sumQ
  346 + this.totalAmountExcludingTax = sumE
  347 + this.totalAmountIncludingTax = sumT
355 348 this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
356 349 },
357 350 async loadSuppliers() {
... ... @@ -399,6 +392,10 @@ export default {
399 392 setSheet('生产厂', opts)
400 393 } else if (field === 'supplier') {
401 394 setSheet('供方', this.supplierList)
  395 + } else if (field === 'specialTerms') {
  396 + setSheet('特别条款要求', this.specialTermsList)
  397 + } else if (field === 'executionStandard') {
  398 + setSheet('执行标准', this.executionStandardList)
402 399 } else if (field === 'includesPackagingFee') {
403 400 setSheet('单价中是否已包含包装费', this.yesNoList)
404 401 } else if (field === 'includesTransportFee') {
... ... @@ -443,18 +440,32 @@ export default {
443 440 { key: 'supplier', label: '供方' },
444 441 { key: 'buyer', label: '需方' },
445 442 { key: 'orderDate', label: '订货日期' },
  443 + { key: 'unit', label: '单位' },
446 444 { key: 'workshopId', label: '生产厂' },
  445 + { key: 'specialTerms', label: '特别条款要求' },
447 446 ]
448 447 for (const it of checks) {
449 448 const val = this.form[it.key]
450 449 const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
451 450 if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
452 451 }
453   - if (!Array.isArray(this.productLineList) || this.productLineList.length === 0) {
  452 + const list = Array.isArray(this.newProductLineList) ? this.newProductLineList : []
  453 + if (list.length === 0) {
454 454 uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
455 455 }
456   - for (const [idx, it] of this.productLineList.entries()) {
457   - if (!it.productName || !it.quantity || !it.unitPrice) {
  456 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  457 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  458 + for (const [idx, it] of list.entries()) {
  459 + console.log('it111', it)
  460 + if (
  461 + strEmpty(it.productName) ||
  462 + strEmpty(it.industry) ||
  463 + strEmpty(it.quality) ||
  464 + strEmpty(it.brand) ||
  465 + numEmpty(it.quantity) ||
  466 + numEmpty(it.unitPrice) ||
  467 + strEmpty(it.deliveryDate)
  468 + ) {
458 469 uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
459 470 }
460 471 }
... ... @@ -486,9 +497,9 @@ export default {
486 497 id: this.form.id,
487 498 destination,
488 499 type: 'DISTRIB_STD',
489   - sumQuantity: this.sumQuantity,
490   - sumAmountExcl: this.sumAmountExcl,
491   - sumTotal: this.sumTotal,
  500 + totalQuantity: this.totalQuantity,
  501 + totalAmountExcludingTax: this.totalAmountExcludingTax,
  502 + totalAmountIncludingTax: this.totalAmountIncludingTax,
492 503 contractDistributorLineList: lines
493 504 })
494 505 try {
... ... @@ -524,7 +535,7 @@ export default {
524 535 color: rgba(0, 0, 0, 0.6);
525 536 line-height: 32rpx;
526 537 width: 240rpx;
527   - padding: 24rpx 0;
  538 + padding: 12rpx 0;
528 539 }
529 540
530 541 .total-item-price {
... ... @@ -547,7 +558,7 @@ export default {
547 558
548 559 .scroll {
549 560 flex: 1;
550   - padding: 12rpx 0 480rpx !important;
  561 + padding: 12rpx 0 392rpx !important;
551 562 }
552 563
553 564 .footer {
... ... @@ -742,4 +753,4 @@ export default {
742 753 }
743 754 }
744 755
745   -</style>
\ No newline at end of file
  756 +</style>
... ...
... ... @@ -53,53 +53,53 @@
53 53 <uni-easyinput v-model="item.quality" :inputBorder="false" placeholder="请输入品质" />
54 54 </template>
55 55 </uni-list-item>
56   - <uni-list-item title="厚度">
  56 + <uni-list-item title="厚度(mm)">
57 57 <template v-slot:footer>
58   - <uni-easyinput v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" />
  58 + <uni-easyinput type="digit" v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" @input="onNonNegativeInput(idx, 'thickness')" @blur="onNonNegativeBlur(idx, 'thickness', 2)" />
59 59 </template>
60 60 </uni-list-item>
61   - <uni-list-item title="厚度公差(单项+)">
  61 + <uni-list-item title="厚度公差上限(mm)">
62 62 <template v-slot:footer>
63   - <uni-easyinput v-model="item.thicknessTolPos" :inputBorder="false"
64   - placeholder="请输入厚度公差(单项+)" />
  63 + <uni-easyinput type="digit" v-model="item.thicknessTolPos" :inputBorder="false"
  64 + placeholder="请输入厚度公差上限" @input="onNonNegativeInput(idx, 'thicknessTolPos')" @blur="onNonNegativeBlur(idx, 'thicknessTolPos', 2)" />
65 65 </template>
66 66 </uni-list-item>
67   - <uni-list-item title="厚度公差(单项-)">
  67 + <uni-list-item title="厚度公差下限(mm)">
68 68 <template v-slot:footer>
69   - <uni-easyinput v-model="item.thicknessTolNeg" :inputBorder="false"
70   - placeholder="请输入厚度公差(单项-)" />
  69 + <uni-easyinput type="digit" v-model="item.thicknessTolNeg" :inputBorder="false"
  70 + placeholder="请输入厚度公差下限" @input="onNonNegativeInput(idx, 'thicknessTolNeg')" @blur="onNonNegativeBlur(idx, 'thicknessTolNeg', 2)" />
71 71 </template>
72 72 </uni-list-item>
73   - <uni-list-item title="宽度">
  73 + <uni-list-item title="宽度(mm)">
74 74 <template v-slot:footer>
75   - <uni-easyinput v-model="item.width" :inputBorder="false" placeholder="请输入宽度" />
  75 + <uni-easyinput type="digit" v-model="item.width" :inputBorder="false" placeholder="请输入宽度" @input="onNonNegativeInput(idx, 'width')" @blur="onNonNegativeBlur(idx, 'width', 2)" />
76 76 </template>
77 77 </uni-list-item>
78   - <uni-list-item title="宽度公差(单项+)">
  78 + <uni-list-item title="宽度公差上限(mm)">
79 79 <template v-slot:footer>
80   - <uni-easyinput v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差(单项+)" />
  80 + <uni-easyinput type="digit" v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差上限" @input="onNonNegativeInput(idx, 'widthTolPos')" @blur="onNonNegativeBlur(idx, 'widthTolPos', 2)" />
81 81 </template>
82 82 </uni-list-item>
83   - <uni-list-item title="宽度公差(单项-)">
  83 + <uni-list-item title="宽度公差下限(mm)">
84 84 <template v-slot:footer>
85   - <uni-easyinput v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差(单项-)" />
  85 + <uni-easyinput type="digit" v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差下限" @input="onNonNegativeInput(idx, 'widthTolNeg')" @blur="onNonNegativeBlur(idx, 'widthTolNeg', 2)" />
86 86 </template>
87 87 </uni-list-item>
88   - <uni-list-item title="长度">
  88 + <uni-list-item title="长度(mm)">
89 89 <template v-slot:footer>
90   - <uni-easyinput v-model="item.length" :inputBorder="false" placeholder="请输入长度" />
  90 + <uni-easyinput type="digit" v-model="item.length" :inputBorder="false" placeholder="请输入长度" @input="onNonNegativeInput(idx, 'length')" @blur="onNonNegativeBlur(idx, 'length', 2)" />
91 91 </template>
92 92 </uni-list-item>
93   - <uni-list-item title="长度公差(单项+)">
  93 + <uni-list-item title="长度公差上限(mm)">
94 94 <template v-slot:footer>
95   - <uni-easyinput v-model="item.lengthTolPos" :inputBorder="false"
96   - placeholder="请输入长度公差(单项+)" />
  95 + <uni-easyinput type="digit" v-model="item.lengthTolPos" :inputBorder="false"
  96 + placeholder="请输入长度公差上限" @input="onNonNegativeInput(idx, 'lengthTolPos')" @blur="onNonNegativeBlur(idx, 'lengthTolPos', 2)" />
97 97 </template>
98 98 </uni-list-item>
99   - <uni-list-item title="长度公差(单项-)">
  99 + <uni-list-item title="长度公差下限(mm)">
100 100 <template v-slot:footer>
101   - <uni-easyinput v-model="item.lengthTolNeg" :inputBorder="false"
102   - placeholder="请输入长度公差(单项-)" />
  101 + <uni-easyinput type="digit" v-model="item.lengthTolNeg" :inputBorder="false"
  102 + placeholder="请输入长度公差下限" @input="onNonNegativeInput(idx, 'lengthTolNeg')" @blur="onNonNegativeBlur(idx, 'lengthTolNeg', 2)" />
103 103 </template>
104 104 </uni-list-item>
105 105 <uni-list-item title="状态">
... ... @@ -107,14 +107,14 @@
107 107 <uni-easyinput v-model="item.status" :inputBorder="false" placeholder="请输入状态" />
108 108 </template>
109 109 </uni-list-item>
110   - <uni-list-item title="数量">
  110 + <uni-list-item title="数量kg">
111 111 <template v-slot:footer>
112   - <uni-easyinput v-model="item.quantity" type="number" :inputBorder="false" placeholder="请输入数量" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'quantity', 0)" />
  112 + <uni-easyinput v-model="item.quantity" type="digit" :inputBorder="false" placeholder="请输入数量kg" @input="onNonNegativeInput(idx, 'quantity')" @blur="onNonNegativeBlur(idx, 'quantity', 2)" />
113 113 </template>
114 114 </uni-list-item>
115   - <uni-list-item title="单价">
  115 + <uni-list-item title="销售价格">
116 116 <template v-slot:footer>
117   - <uni-easyinput v-model="item.unitPrice" type="number" :inputBorder="false" placeholder="请输入单价" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'unitPrice', 0)" />
  117 + <uni-easyinput v-model="item.unitPrice" type="digit" :inputBorder="false" placeholder="请输入销售价格" @input="onNonNegativeInput(idx, 'unitPrice')" @blur="onNonNegativeBlur(idx, 'unitPrice', 2)" />
118 118 </template>
119 119 </uni-list-item>
120 120 <uni-list-item title="不含税金额">
... ... @@ -129,7 +129,7 @@
129 129 </uni-list-item>
130 130 <uni-list-item title="发货日期">
131 131 <template v-slot:footer>
132   - <uni-datetime-picker type="date" v-model="item.orderDate" @change="onDateChange(idx, $event)" />
  132 + <uni-datetime-picker :start="minDeliveryDate" type="date" v-model="item.deliveryDate" @change="onDateChange(idx, $event)" />
133 133 </template>
134 134 </uni-list-item>
135 135 </uni-list>
... ... @@ -151,7 +151,30 @@
151 151 <view class="row"><text class="label">行业</text><text class="value">{{ item.industry }}</text></view>
152 152 <view class="row"><text class="label">牌号</text><text class="value">{{ item.brand }}</text></view>
153 153 <view class="row"><text class="label">品质</text><text class="value">{{ item.quality }}</text></view>
154   - <view class="row"><text class="label">规格</text><text class="value">{{ item.specDisplay }}</text></view>
  154 + <!-- 厚(公差) * 宽(公差) * 长(公差) -->
  155 + <view class="row row-spec"><text class="label">规格(mm)</text>
  156 + <view class="value value-spec">
  157 + <view v-if="item.thickness" class="value-spec_val">{{ item.thickness }}</view>
  158 + <view v-if="item.thickness" class="value-spec_box">
  159 + <view v-if="item.thicknessTolPos" class="value-spec_box_1">+{{ item.thicknessTolPos }}
  160 + </view>
  161 + <view v-if="item.thicknessTolNeg" class="value-spec_box_2">-{{ item.thicknessTolNeg }}
  162 + </view>
  163 + </view>
  164 + <view v-if="item.width" class="value-spec_val p12">*</view>
  165 + <view v-if="item.width" class="value-spec_val">{{ item.width }}</view>
  166 + <view v-if="item.width" class="value-spec_box">
  167 + <view v-if="item.widthTolPos" class="value-spec_box_1">+{{ item.widthTolPos }}</view>
  168 + <view v-if="item.widthTolNeg" class="value-spec_box_2">-{{ item.widthTolNeg }}</view>
  169 + </view>
  170 + <view v-if="item.length" class="value-spec_val p12">*</view>
  171 + <view v-if="item.length" class="value-spec_val">{{ item.length }}</view>
  172 + <view v-if="item.length" class="value-spec_box">
  173 + <view v-if="item.lengthTolPos" class="value-spec_box_1">+{{ item.lengthTolPos }}</view>
  174 + <view v-if="item.lengthTolNeg" class="value-spec_box_2">-{{ item.lengthTolNeg }}</view>
  175 + </view>
  176 + </view>
  177 + </view>
155 178 <view class="row"><text class="label">状态</text><text class="value">{{ item.status }}</text></view>
156 179 <view class="row"><text class="label">数量</text><text class="value">{{ item.quantity }}</text></view>
157 180 <view class="row"><text class="label">单价</text><text class="value">{{ formatCurrency(item.unitPrice)
... ... @@ -162,7 +185,7 @@
162 185 }}</text></view>
163 186 <view class="row"><text class="label">总金额</text><text class="value">{{ formatCurrency(item.totalAmount)
164 187 }}</text></view>
165   - <view class="row"><text class="label">发货日期</text><text class="value">{{ item.orderDate }}</text></view>
  188 + <view class="row"><text class="label">发货日期</text><text class="value">{{ item.deliveryDate }}</text></view>
166 189 </view>
167 190 </view>
168 191 <SingleSelectSheet :visible.sync="sheet.visible" :title="sheet.title" :options="sheet.options" v-model="sheet.value" @confirm="onProductConfirm" />
... ... @@ -176,7 +199,8 @@ export default {
176 199 mode: { type: String, default: 'add' },
177 200 list: { type: Array, default: () => [] },
178 201 max: { type: Number, default: 8 },
179   - orderDateBase: { type: String, default: '' },
  202 + deliveryDateBase: { type: String, default: '' },
  203 + deliveryDate: { type: String, default: '' },
180 204 options: { type: Array, default: () => [] }
181 205 },
182 206 components: { SingleSelectSheet },
... ... @@ -194,6 +218,21 @@ export default {
194 218 label: o.label != null ? o.label : (o.text != null ? o.text : (o.name != null ? o.name : '')),
195 219 value: o.value != null ? o.value : (o.id != null ? o.id : o.productId)
196 220 }))
  221 + },
  222 + minDeliveryDate() {
  223 + const s = this.deliveryDate
  224 + if (!s) return ''
  225 + const parts = String(s).split('-')
  226 + const y = Number(parts[0])
  227 + const m = Number(parts[1])
  228 + const d = Number(parts[2])
  229 + if (!y || !m || !d) return ''
  230 + const dt = new Date(y, m - 1, d)
  231 + dt.setDate(dt.getDate() + 1)
  232 + const yy = dt.getFullYear()
  233 + const mm = String(dt.getMonth() + 1).padStart(2, '0')
  234 + const dd = String(dt.getDate() - 1).padStart(2, '0')
  235 + return `${yy}/${mm}/${dd}`
197 236 }
198 237 },
199 238 watch: {
... ... @@ -218,10 +257,18 @@ export default {
218 257 },
219 258 methods: {
220 259 defaultItem() {
221   - return { productId: '', productName: '', industry: '', brand: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', status: '', quantity: '', unitPrice: '', amountExcludingTax: 0, totalAmount: 0, orderDate: '' }
  260 + return { productId: '', productName: '', industry: '', brand: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', status: '', quantity: '', unitPrice: '', amountExcludingTax: 0, totalAmount: 0, deliveryDate: '' }
222 261 },
223   - onImmediateChange(idx) {
224   - this.$nextTick(() => this.recalculate(idx))
  262 + onNonNegativeInput(idx, field) {
  263 + const it = this.items[idx]
  264 + if (!it) return
  265 + let v = String(it[field] != null ? it[field] : '')
  266 + v = v.replace(/[^0-9.]/g, '')
  267 + v = v.replace(/(\..*)\./g, '$1')
  268 + if (v.startsWith('.')) v = '0' + v
  269 + it[field] = v
  270 + this.$set(this.items, idx, it)
  271 + if (field === 'quantity' || field === 'unitPrice') this.$nextTick(() => this.recalculate(idx))
225 272 },
226 273 toNumber(val) {
227 274 if (typeof val === 'number') return isNaN(val) ? 0 : val
... ... @@ -234,21 +281,21 @@ export default {
234 281 const m = Math.pow(10, digits)
235 282 return Math.round(n * m) / m
236 283 },
237   - onNumberBlur(idx, field, digits) {
  284 + onNonNegativeBlur(idx, field, digits) {
238 285 const it = this.items[idx]
239 286 if (!it) return
240 287 const raw = it[field]
241   - // 如果为空则保持为空,不自动置为0,仅重新计算依赖字段
242 288 if (raw === '' || raw === null || raw === undefined) {
243 289 this.$set(this.items, idx, it)
244   - this.recalculate(idx)
  290 + if (field === 'quantity' || field === 'unitPrice') this.recalculate(idx)
245 291 return
246 292 }
247   - const num = this.toNumber(raw)
  293 + let num = this.toNumber(raw)
  294 + if (isNaN(num) || num < 0) num = 0
248 295 const rounded = this.round(num, digits)
249 296 it[field] = rounded
250 297 this.$set(this.items, idx, it)
251   - this.recalculate(idx)
  298 + if (field === 'quantity' || field === 'unitPrice') this.recalculate(idx)
252 299 },
253 300 formatCurrency(val) {
254 301 if (val == null || val === '') return ''
... ... @@ -319,15 +366,15 @@ export default {
319 366 onDateChange(idx, e) {
320 367 const it = this.items[idx]
321 368 if (!it) return
322   - const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.orderDate
  369 + const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.deliveryDate
323 370 const dateStr = String(val).slice(0, 10)
324   - const base = this.orderDateBase ? new Date(this.orderDateBase) : null
  371 + const base = this.deliveryDateBase ? new Date(this.deliveryDateBase) : null
325 372 const d = new Date(dateStr)
326 373 if (base && !isNaN(d.getTime()) && d.getTime() < base.getTime()) {
327 374 uni.showToast({ title: '发货日期不得早于订货日期', icon: 'none' })
328   - it.orderDate = this.orderDateBase
  375 + it.deliveryDate = this.deliveryDateBase
329 376 } else {
330   - it.orderDate = dateStr
  377 + it.deliveryDate = dateStr
331 378 }
332 379 this.$set(this.items, idx, it)
333 380 },
... ... @@ -500,8 +547,46 @@ export default {
500 547
501 548 .value {
502 549 flex: 1;
503   - text-align: right;
  550 + // text-align: right;
504 551 color: rgba(0, 0, 0, 0.9);
505 552 font-size: 28rpx;
506 553 }
  554 + .value-spec {
  555 + height: 48rpx;
  556 + display: flex;
  557 + align-items: center;
  558 + color: #000000;
  559 + // justify-content: end;
  560 + &_box {
  561 + position: relative;
  562 + width: 60rpx;
  563 + height: 48rpx;
  564 +
  565 + &_1 {
  566 + font-size: 16rpx;
  567 + position: absolute;
  568 + top: -10rpx;
  569 + left: 0;
  570 + }
  571 +
  572 + &_2 {
  573 + font-size: 16rpx;
  574 + position: absolute;
  575 + bottom: -10rpx;
  576 + left: 0;
  577 + }
  578 + }
  579 +
  580 + &_val {
  581 + font-size: 28rpx;
  582 +
  583 + &.p12 {
  584 + padding-right: 12rpx;
  585 + }
  586 + }
  587 + }
  588 + .row-spec {
  589 + height: 60rpx;
  590 + align-items: center;
  591 + }
507 592 </style>
... ...
... ... @@ -39,7 +39,7 @@
39 39 <view class="item-title"><text class="required">*</text><text>生产厂</text></view>
40 40 </template>
41 41 </uni-list-item>
42   - <ProductRel mode="add" :orderDateBase="form.orderDate" @change="onProductsChange" :options="productList" />
  42 + <ProductRel mode="add" :deliveryDate="form.orderDate" :deliveryDateBase="form.deliveryDate" @change="onProductsChange" :options="productList" />
43 43 <uni-list-item title="合计人民币金额(大写)">
44 44 <template v-slot:footer>
45 45 <uni-easyinput v-model="form.totalAmountCapital" placeholder="自动计算" :inputBorder="false" disabled />
... ... @@ -92,33 +92,25 @@
92 92 :inputBorder="false" />
93 93 </template>
94 94 </uni-list-item>
95   - <view class="group">
96   - <view class="group-title">特别条款要求</view>
97   - <view class="radio-list">
98   - <view v-for="(opt, i) in specialTermsList" :key="'cr-' + i" class="radio-item"
99   - @click="onRadioSelect('specialTerms', 'specialTermsName', opt)">
100   - <view :class="['radio', { checked: form.specialTerms === opt.value }]" />
101   - <text class="label">{{ opt.label }}</text>
102   - </view>
103   - </view>
104   - </view>
105   - <view class="group">
106   - <view class="group-title">执行标准</view>
107   - <view class="radio-list">
108   - <view v-for="(opt, i) in executionStandardList" :key="'es-' + i" class="radio-item"
109   - @click="onRadioSelect('executionStandard', 'executionStandardName', opt)">
110   - <view :class="['radio', { checked: form.executionStandard === opt.value }]" />
111   - <text class="label">{{ opt.label }}</text>
112   - </view>
113   - </view>
114   - </view>
  95 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  96 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  97 + <template v-slot:body>
  98 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  99 + </template>
  100 + </uni-list-item>
  101 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  102 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  103 + <template v-slot:body>
  104 + <view class="item-title"><text>执行标准</text></view>
  105 + </template>
  106 + </uni-list-item>
115 107 <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
116 108 <template v-slot:footer>
117 109 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注"
118 110 :inputBorder="false" />
119 111 </template>
120 112 </uni-list-item>
121   - <uni-list-item title="特别说明">
  113 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
122 114 <template v-slot:footer>
123 115 <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
124 116 </template>
... ... @@ -181,7 +173,7 @@
181 173 数量
182 174 </div>
183 175 <div class="total-item-price">
184   - {{ (sumQuantity || 0).toFixed(2) }}t
  176 + {{ (totalQuantity || 0).toFixed(2) }}kg
185 177 </div>
186 178 </div>
187 179 <div class="total-item">
... ... @@ -189,7 +181,7 @@
189 181 不含税金额
190 182 </div>
191 183 <div class="total-item-price text-red">
192   - ¥{{ (sumAmountExcl || 0).toFixed(2) }}
  184 + ¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}
193 185 </div>
194 186 </div>
195 187 <div class="total-item">
... ... @@ -197,7 +189,7 @@
197 189 总金额
198 190 </div>
199 191 <div class="total-item-price text-red">
200   - ¥{{ (sumTotal || 0).toFixed(2) }}
  192 + ¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}
201 193 </div>
202 194 </div>
203 195 </div>
... ... @@ -233,6 +225,7 @@ export default {
233 225 buyer: '',
234 226 buyerName: '',
235 227 orderDate: '',
  228 + deliveryDate: '',
236 229 designatedConsignee: '',
237 230 specialTerms: '',
238 231 specialTermsName: '',
... ... @@ -263,9 +256,9 @@ export default {
263 256 yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
264 257 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
265 258 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
266   - sumQuantity: 0,
267   - sumAmountExcl: 0,
268   - sumTotal: 0,
  259 + totalQuantity: 0,
  260 + totalAmountExcludingTax: 0,
  261 + totalAmountIncludingTax: 0,
269 262 productLineList: [],
270 263 productList: [],
271 264 customerRemarks: [],
... ... @@ -368,9 +361,9 @@ export default {
368 361 const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
369 362 const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
370 363 const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
371   - this.sumQuantity = sumQ
372   - this.sumAmountExcl = sumE
373   - this.sumTotal = sumT
  364 + this.totalQuantity = sumQ
  365 + this.totalAmountExcludingTax = sumE
  366 + this.totalAmountIncludingTax = sumT
374 367 this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
375 368 this.productLineList = list
376 369 },
... ... @@ -446,6 +439,10 @@ export default {
446 439 setSheet('生产厂', opts)
447 440 } else if (field === 'supplier') {
448 441 setSheet('供方', this.supplierList)
  442 + } else if (field === 'specialTerms') {
  443 + setSheet('特别条款要求', this.specialTermsList)
  444 + } else if (field === 'executionStandard') {
  445 + setSheet('执行标准', this.executionStandardList)
449 446 } else if (field === 'includesPackagingFee') {
450 447 setSheet('单价中是否已包含包装费', this.yesNoList)
451 448 } else if (field === 'includesTransportFee') {
... ... @@ -516,9 +513,9 @@ export default {
516 513 ...formForSubmit,
517 514 destination,
518 515 type: 'DIST_STOCK_CONTRACT',
519   - sumQuantity: this.sumQuantity,
520   - sumAmountExcl: this.sumAmountExcl,
521   - sumTotal: this.sumTotal,
  516 + totalQuantity: this.totalQuantity,
  517 + totalAmountExcludingTax: this.totalAmountExcludingTax,
  518 + totalAmountIncludingTax: this.totalAmountIncludingTax,
522 519 contractDistributorLineList: lines
523 520 })
524 521 console.log('onSubmit__payload', payload)
... ... @@ -537,18 +534,30 @@ export default {
537 534 { key: 'supplier', label: '供方' },
538 535 { key: 'buyer', label: '需方' },
539 536 { key: 'orderDate', label: '订货日期' },
  537 + { key: 'unit', label: '单位' },
540 538 { key: 'workshopId', label: '生产厂' },
  539 + { key: 'specialTerms', label: '特别条款要求' },
541 540 ]
542 541 for (const it of checks) {
543 542 const val = this.form[it.key]
544 543 const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
545 544 if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
546 545 }
547   - if (!Array.isArray(this.productLineList) || this.productLineList.length === 0) {
  546 + const list = Array.isArray(this.productLineList) ? this.productLineList : []
  547 + if (list.length === 0) {
548 548 uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
549 549 }
550   - for (const [idx, it] of this.productLineList.entries()) {
551   - if (!it.productName || !it.quantity || !it.unitPrice) {
  550 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  551 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  552 + for (const [idx, it] of list.entries()) {
  553 + if (
  554 + strEmpty(it.productName) ||
  555 + strEmpty(it.industry) ||
  556 + strEmpty(it.quality) ||
  557 + strEmpty(it.brand) ||
  558 + numEmpty(it.quantity) ||
  559 + strEmpty(it.deliveryDate)
  560 + ) {
552 561 uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
553 562 }
554 563 }
... ... @@ -576,7 +585,7 @@ export default {
576 585 color: rgba(0, 0, 0, 0.6);
577 586 line-height: 32rpx;
578 587 width: 240rpx;
579   - padding: 24rpx 0;
  588 + padding: 12rpx 0;
580 589 }
581 590 .total-item-price {
582 591 font-weight: 600;
... ... @@ -598,7 +607,7 @@ export default {
598 607
599 608 .scroll {
600 609 flex: 1;
601   - padding: 12rpx 0 480rpx !important;
  610 + padding: 12rpx 0 392rpx !important;
602 611 }
603 612
604 613 .footer {
... ...
... ... @@ -52,13 +52,13 @@
52 52 }}</text></view>
53 53 </view>
54 54
55   - <view class="section">
  55 + <view class="section" v-if="detail.status === 'STANDARD'">
56 56 <view class="row"><text class="label">规范性合同</text><text class="value" style="color: #3D48A3;">{{ detail.standardFileName || '-'
57 57 }}</text></view>
58 58 <view class="row"><text class="label">合同是否规范</text><text class="value">{{ detail.standardStandardized ? '是' : '否'
59 59 }}</text></view>
60 60 </view>
61   - <view class="section" v-if="status === 'FORMAL'">
  61 + <view class="section" v-if="detail.status === 'FORMAL'">
62 62 <view class="row"><text class="label">规范性合同</text><text class="value" style="color: #3D48A3;">{{ detail.formalFileName || '-' }}</text></view>
63 63 <view class="row"><text class="label">合同是否规范</text><text class="value">{{ detail.formalStandardized ? '是' : '否' }}</text></view>
64 64 </view>
... ... @@ -252,18 +252,18 @@ export default {
252 252 const e = this.detail.showExamine || false
253 253 const f = this.detail.standardShowExamine || false
254 254 return [
255   - { ...this.buttons[0], visible: (s === 'DRAFT') },
256   - { ...this.buttons[1], visible: (s === 'DRAFT') },
257   - { ...this.buttons[2], visible: (s === 'FORMAL' && !l) },
258   - { ...this.buttons[3], visible: ((s === 'DRAFT' || s === 'FORMAL') && t !== 'AUDIT' && t !== 'PASS') },
259   - { ...this.buttons[4], visible: (s === 'STANDARD' && t !== 'AUDIT' && t !== 'PASS') },
260   - { ...this.buttons[5], visible: (s === 'STANDARD' && a !== 'AUDIT' && a !== 'PASS') },
261   - { ...this.buttons[6], visible: (s === 'FORMAL' && e && t === 'AUDIT') },
262   - { ...this.buttons[7], visible: (s === 'STANDARD' && e && t === 'AUDIT') },
263   - { ...this.buttons[8], visible: (s === 'STANDARD' && f && a === 'AUDIT') },
264   - { ...this.buttons[9], visible: (s === 'FORMAL' && t) },
265   - { ...this.buttons[10], visible: (s === 'STANDARD' && t ) },
266   - { ...this.buttons[11], visible: (s === 'STANDARD' && a ) },
  255 + { ...this.buttons[0], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:modify')) },
  256 + { ...this.buttons[1], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:delete')) },
  257 + { ...this.buttons[2], visible: (s === 'FORMAL' && !l && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:lock')) },
  258 + { ...this.buttons[3], visible: ((s === 'DRAFT' || s === 'FORMAL') && t !== 'AUDIT' && t !== 'PASS' && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:upload')) },
  259 + { ...this.buttons[4], visible: (s === 'STANDARD' && t !== 'AUDIT' && t !== 'PASS' && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:upload')) },
  260 + { ...this.buttons[5], visible: (s === 'STANDARD' && a !== 'AUDIT' && a !== 'PASS' && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:standard-upload')) },
  261 + { ...this.buttons[6], visible: (s === 'FORMAL' && e && t === 'AUDIT' && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:approve')) },
  262 + { ...this.buttons[7], visible: (s === 'STANDARD' && e && t === 'AUDIT' && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:approve')) },
  263 + { ...this.buttons[8], visible: (s === 'STANDARD' && f && a === 'AUDIT' && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:restandard-approveview')) },
  264 + { ...this.buttons[9], visible: (s === 'FORMAL' && t && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:review')) },
  265 + { ...this.buttons[10], visible: (s === 'STANDARD' && t && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:review')) },
  266 + { ...this.buttons[11], visible: (s === 'STANDARD' && a && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:standard-review')) },
267 267 ]
268 268 }
269 269 },
... ...
... ... @@ -14,7 +14,7 @@
14 14 @input="onSearchInput"
15 15 />
16 16 <view class="tool-icons">
17   - <image class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
  17 + <image v-if="$auth.hasPermi('contract-manage:distribution-inventory-contract:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
18 18 <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
19 19 </view>
20 20 </view>
... ... @@ -61,7 +61,9 @@
61 61 <text>订单总额</text><text class="amount" :style="{ color: '#b67a76' }">¥{{ formatAmount(item.totalAmountIncludingTax) }}</text>
62 62 </view>
63 63 <view class="info-row" v-if="item.status === 'STANDARD' || item.status === 'FORMAL'">
64   - <text>{{ item.status === 'STANDARD' ? '标准合同' : '正式合同' }}规范性审核状态</text><span class="info-status" :style="getStatusCss(item.standardApprovedName)">{{ item.standardApprovedName }}</span>
  64 + <text>{{ item.status === 'STANDARD' ? '标准合同' : '正式合同' }}规范性审核状态</text>
  65 + <span v-if="item.status === 'STANDARD' ? item.standardApprovedName : item.formalApprovedName" class="info-status" :style="getStatusCss(item.status === 'STANDARD' ? item.standardApprovedName : item.formalApprovedName)">{{ item.status === 'STANDARD' ? item.standardApprovedName : item.formalApprovedName }}</span>
  66 + <span v-else>-</span>
65 67 </view>
66 68 <view class="info-row">
67 69 <text>订货日期</text><text>{{ item.orderDate }}</text>
... ... @@ -244,7 +246,7 @@ export default {
244 246 const list = Array.isArray(this.statusStyle) ? this.statusStyle : []
245 247 const found = list.find(it => it && it.text === name) || {}
246 248 return {
247   - color: found.color || '#000',
  249 + color: found.color || '#fff',
248 250 backgroundColor: found.bgColor || '#000'
249 251 }
250 252 }
... ...
... ... @@ -108,7 +108,7 @@
108 108 数量
109 109 </div>
110 110 <div class="total-item-price">
111   - {{ (sumQuantity || 0).toFixed(2) }}t
  111 + {{ (totalQuantity || 0).toFixed(2) }}t
112 112 </div>
113 113 </div>
114 114 <div class="total-item">
... ... @@ -116,7 +116,7 @@
116 116 不含税金额
117 117 </div>
118 118 <div class="total-item-price text-red">
119   - ¥{{ (sumAmountExcl || 0).toFixed(2) }}
  119 + ¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}
120 120 </div>
121 121 </div>
122 122 <div class="total-item">
... ... @@ -124,7 +124,7 @@
124 124 总金额
125 125 </div>
126 126 <div class="total-item-price text-red">
127   - ¥{{ (sumTotal || 0).toFixed(2) }}
  127 + ¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}
128 128 </div>
129 129 </div>
130 130 </div>
... ... @@ -147,15 +147,15 @@ export default {
147 147 }
148 148 },
149 149 computed: {
150   - sumQuantity() {
  150 + totalQuantity() {
151 151 const qty = this.items.filter(it => it.locked).reduce((p, c) => p + this.toNumber(c.quantity), 0)
152 152 return this.round(qty, 2)
153 153 },
154   - sumAmountExcl() {
  154 + totalAmountExcludingTax() {
155 155 const sum = this.items.filter(it => it.locked).reduce((p, c) => p + this.toNumber(c.amountExcludingTax), 0)
156 156 return this.round(sum, 2)
157 157 },
158   - sumTotal() { return this.totalAmount },
  158 + totalAmountIncludingTax() { return this.totalAmount },
159 159 totalAmount() {
160 160 let sum = 0
161 161 for (const it of this.items) {
... ... @@ -325,9 +325,9 @@ export default {
325 325 const payload = {
326 326 id: this.id,
327 327 totalAmountCapital: formatCurrencyToChinese(this.sumTotal),
328   - totalAmountExcludingTax: this.sumAmountExcl,
329   - totalAmountIncludingTax: this.sumTotal,
330   - totalQuantity: this.sumQuantity,
  328 + totalAmountExcludingTax: this.totalAmountExcludingTax,
  329 + totalAmountIncludingTax: this.totalAmountIncludingTax,
  330 + totalQuantity: this.totalQuantity,
331 331 type:'DIST_STOCK_CONTRACT',
332 332 contractDistributorLineList: selected
333 333 }
... ... @@ -362,7 +362,7 @@ export default {
362 362
363 363 .scroll {
364 364 flex: 1;
365   - padding: 12rpx 0 480rpx !important;
  365 + padding: 12rpx 0 392rpx !important;
366 366 }
367 367
368 368 .header {
... ... @@ -646,7 +646,7 @@ export default {
646 646 color: rgba(0, 0, 0, 0.6);
647 647 line-height: 32rpx;
648 648 width: 240rpx;
649   - padding: 24rpx 0;
  649 + padding: 12rpx 0;
650 650 }
651 651
652 652 .total-item-price {
... ...
... ... @@ -41,7 +41,7 @@
41 41 </template>
42 42 </uni-list-item>
43 43
44   - <ProductRel mode="add" :orderDateBase="form.orderDate" :list="productLineList" @change="onProductsChange" :options="productList" />
  44 + <ProductRel mode="add" :deliveryDate="form.orderDate" :deliveryDateBase="form.deliveryDate" :list="productLineList" @change="onProductsChange" :options="productList" />
45 45
46 46 <uni-list-item title="合计人民币金额(大写)">
47 47 <template v-slot:footer>
... ... @@ -99,33 +99,25 @@
99 99 </template>
100 100 </uni-list-item>
101 101
102   - <view class="group">
103   - <view class="group-title">特别条款要求</view>
104   - <view class="radio-list">
105   - <view v-for="(opt, i) in specialTermsList" :key="'cr-' + i" class="radio-item"
106   - @click="onRadioSelect('specialTerms', 'specialTermsName', opt)">
107   - <view :class="['radio', { checked: form.specialTerms === opt.value }]" />
108   - <text class="label">{{ opt.label }}</text>
109   - </view>
110   - </view>
111   - </view>
112   - <view class="group">
113   - <view class="group-title">执行标准</view>
114   - <view class="radio-list">
115   - <view v-for="(opt, i) in executionStandardList" :key="'es-' + i" class="radio-item"
116   - @click="onRadioSelect('executionStandard', 'executionStandardName', opt)">
117   - <view :class="['radio', { checked: form.executionStandard === opt.value }]" />
118   - <text class="label">{{ opt.label }}</text>
119   - </view>
120   - </view>
121   - </view>
  102 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  103 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  104 + <template v-slot:body>
  105 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  106 + </template>
  107 + </uni-list-item>
  108 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  109 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  110 + <template v-slot:body>
  111 + <view class="item-title"><text>执行标准</text></view>
  112 + </template>
  113 + </uni-list-item>
122 114 <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
123 115 <template v-slot:footer>
124 116 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注"
125 117 :inputBorder="false" />
126 118 </template>
127 119 </uni-list-item>
128   - <uni-list-item title="特别说明">
  120 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
129 121 <template v-slot:footer>
130 122 <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
131 123 </template>
... ... @@ -177,15 +169,15 @@
177 169 <div class="total-text">合计</div>
178 170 <div class="total-item">
179 171 <div class="total-item-text">数量</div>
180   - <div class="total-item-price">{{ (sumQuantity || 0).toFixed(2) }}t</div>
  172 + <div class="total-item-price">{{ (totalQuantity || 0).toFixed(2) }}kg</div>
181 173 </div>
182 174 <div class="total-item">
183 175 <div class="total-item-text">不含税金额</div>
184   - <div class="total-item-price text-red">¥{{ (sumAmountExcl || 0).toFixed(2) }}</div>
  176 + <div class="total-item-price text-red">¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}</div>
185 177 </div>
186 178 <div class="total-item">
187 179 <div class="total-item-text">总金额</div>
188   - <div class="total-item-price text-red">¥{{ (sumTotal || 0).toFixed(2) }}</div>
  180 + <div class="total-item-price text-red">¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}</div>
189 181 </div>
190 182 </div>
191 183 <button class="btn submit" type="primary" @click="onSubmit">保存</button>
... ... @@ -223,6 +215,7 @@ export default {
223 215 workshopId: '',
224 216 workshopName: '',
225 217 orderDate: '',
  218 + deliveryDate: '',
226 219 designatedConsignee: '',
227 220 specialTerms: '',
228 221 specialTermsName: '',
... ... @@ -256,9 +249,9 @@ export default {
256 249 yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
257 250 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
258 251 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
259   - sumQuantity: 0,
260   - sumAmountExcl: 0,
261   - sumTotal: 0,
  252 + totalQuantity: 0,
  253 + totalAmountExcludingTax: 0,
  254 + totalAmountIncludingTax: 0,
262 255 productLineList: [],
263 256 newProductLineList: [],
264 257 productList: []
... ... @@ -349,9 +342,9 @@ export default {
349 342 const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
350 343 const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
351 344 const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
352   - this.sumQuantity = sumQ
353   - this.sumAmountExcl = sumE
354   - this.sumTotal = sumT
  345 + this.totalQuantity = sumQ
  346 + this.totalAmountExcludingTax = sumE
  347 + this.totalAmountIncludingTax = sumT
355 348 this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
356 349 },
357 350 async loadSuppliers() {
... ... @@ -399,6 +392,10 @@ export default {
399 392 setSheet('生产厂', opts)
400 393 } else if (field === 'supplier') {
401 394 setSheet('供方', this.supplierList)
  395 + } else if (field === 'specialTerms') {
  396 + setSheet('特别条款要求', this.specialTermsList)
  397 + } else if (field === 'executionStandard') {
  398 + setSheet('执行标准', this.executionStandardList)
402 399 } else if (field === 'includesPackagingFee') {
403 400 setSheet('单价中是否已包含包装费', this.yesNoList)
404 401 } else if (field === 'includesTransportFee') {
... ... @@ -443,18 +440,30 @@ export default {
443 440 { key: 'supplier', label: '供方' },
444 441 { key: 'buyer', label: '需方' },
445 442 { key: 'orderDate', label: '订货日期' },
  443 + { key: 'unit', label: '单位' },
446 444 { key: 'workshopId', label: '生产厂' },
  445 + { key: 'specialTerms', label: '特别条款要求' },
447 446 ]
448 447 for (const it of checks) {
449 448 const val = this.form[it.key]
450 449 const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
451 450 if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
452 451 }
453   - if (!Array.isArray(this.productLineList) || this.productLineList.length === 0) {
  452 + const list = Array.isArray(this.newProductLineList) ? this.newProductLineList : []
  453 + if (list.length === 0) {
454 454 uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
455 455 }
456   - for (const [idx, it] of this.productLineList.entries()) {
457   - if (!it.productName || !it.quantity) {
  456 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  457 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  458 + for (const [idx, it] of list.entries()) {
  459 + if (
  460 + strEmpty(it.productName) ||
  461 + strEmpty(it.industry) ||
  462 + strEmpty(it.quality) ||
  463 + strEmpty(it.brand) ||
  464 + numEmpty(it.quantity) ||
  465 + strEmpty(it.deliveryDate)
  466 + ) {
458 467 uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
459 468 }
460 469 }
... ... @@ -486,9 +495,9 @@ export default {
486 495 id: this.form.id,
487 496 destination,
488 497 type: 'DIST_STOCK_CONTRACT',
489   - sumQuantity: this.sumQuantity,
490   - sumAmountExcl: this.sumAmountExcl,
491   - sumTotal: this.sumTotal,
  498 + totalQuantity: this.totalQuantity,
  499 + totalAmountExcludingTax: this.totalAmountExcludingTax,
  500 + totalAmountIncludingTax: this.totalAmountIncludingTax,
492 501 contractDistributorLineList: lines
493 502 })
494 503 try {
... ... @@ -524,7 +533,7 @@ export default {
524 533 color: rgba(0, 0, 0, 0.6);
525 534 line-height: 32rpx;
526 535 width: 240rpx;
527   - padding: 24rpx 0;
  536 + padding: 12rpx 0;
528 537 }
529 538
530 539 .total-item-price {
... ... @@ -547,7 +556,7 @@ export default {
547 556
548 557 .scroll {
549 558 flex: 1;
550   - padding: 12rpx 0 480rpx !important;
  559 + padding: 12rpx 0 392rpx !important;
551 560 }
552 561
553 562 .footer {
... ... @@ -742,4 +751,4 @@ export default {
742 751 }
743 752 }
744 753
745   -</style>
\ No newline at end of file
  754 +</style>
... ...
... ... @@ -53,53 +53,53 @@
53 53 <uni-easyinput v-model="item.quality" :inputBorder="false" placeholder="请输入品质" />
54 54 </template>
55 55 </uni-list-item>
56   - <uni-list-item title="厚度">
  56 + <uni-list-item title="厚度(mm)">
57 57 <template v-slot:footer>
58   - <uni-easyinput v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" />
  58 + <uni-easyinput type="digit" v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" @input="onNonNegativeInput(idx, 'thickness')" @blur="onNonNegativeBlur(idx, 'thickness', 2)" />
59 59 </template>
60 60 </uni-list-item>
61   - <uni-list-item title="厚度公差(单项+)">
  61 + <uni-list-item title="厚度公差上限(mm)">
62 62 <template v-slot:footer>
63   - <uni-easyinput v-model="item.thicknessTolPos" :inputBorder="false"
64   - placeholder="请输入厚度公差(单项+)" />
  63 + <uni-easyinput type="digit" v-model="item.thicknessTolPos" :inputBorder="false"
  64 + placeholder="请输入厚度公差上限" @input="onNonNegativeInput(idx, 'thicknessTolPos')" @blur="onNonNegativeBlur(idx, 'thicknessTolPos', 2)" />
65 65 </template>
66 66 </uni-list-item>
67   - <uni-list-item title="厚度公差(单项-)">
  67 + <uni-list-item title="厚度公差下限(mm)">
68 68 <template v-slot:footer>
69   - <uni-easyinput v-model="item.thicknessTolNeg" :inputBorder="false"
70   - placeholder="请输入厚度公差(单项-)" />
  69 + <uni-easyinput type="digit" v-model="item.thicknessTolNeg" :inputBorder="false"
  70 + placeholder="请输入厚度公差下限" @input="onNonNegativeInput(idx, 'thicknessTolNeg')" @blur="onNonNegativeBlur(idx, 'thicknessTolNeg', 2)" />
71 71 </template>
72 72 </uni-list-item>
73   - <uni-list-item title="宽度">
  73 + <uni-list-item title="宽度(mm)">
74 74 <template v-slot:footer>
75   - <uni-easyinput v-model="item.width" :inputBorder="false" placeholder="请输入宽度" />
  75 + <uni-easyinput type="digit" v-model="item.width" :inputBorder="false" placeholder="请输入宽度" @input="onNonNegativeInput(idx, 'width')" @blur="onNonNegativeBlur(idx, 'width', 2)" />
76 76 </template>
77 77 </uni-list-item>
78   - <uni-list-item title="宽度公差(单项+)">
  78 + <uni-list-item title="宽度公差上限(mm)">
79 79 <template v-slot:footer>
80   - <uni-easyinput v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差(单项+)" />
  80 + <uni-easyinput type="digit" v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差上限" @input="onNonNegativeInput(idx, 'widthTolPos')" @blur="onNonNegativeBlur(idx, 'widthTolPos', 2)" />
81 81 </template>
82 82 </uni-list-item>
83   - <uni-list-item title="宽度公差(单项-)">
  83 + <uni-list-item title="宽度公差下限(mm)">
84 84 <template v-slot:footer>
85   - <uni-easyinput v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差(单项-)" />
  85 + <uni-easyinput type="digit" v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差下限" @input="onNonNegativeInput(idx, 'widthTolNeg')" @blur="onNonNegativeBlur(idx, 'widthTolNeg', 2)" />
86 86 </template>
87 87 </uni-list-item>
88   - <uni-list-item title="长度">
  88 + <uni-list-item title="长度(mm)">
89 89 <template v-slot:footer>
90   - <uni-easyinput v-model="item.length" :inputBorder="false" placeholder="请输入长度" />
  90 + <uni-easyinput type="digit" v-model="item.length" :inputBorder="false" placeholder="请输入长度" @input="onNonNegativeInput(idx, 'length')" @blur="onNonNegativeBlur(idx, 'length', 2)" />
91 91 </template>
92 92 </uni-list-item>
93   - <uni-list-item title="长度公差(单项+)">
  93 + <uni-list-item title="长度公差上限(mm)">
94 94 <template v-slot:footer>
95   - <uni-easyinput v-model="item.lengthTolPos" :inputBorder="false"
96   - placeholder="请输入长度公差(单项+)" />
  95 + <uni-easyinput type="digit" v-model="item.lengthTolPos" :inputBorder="false"
  96 + placeholder="请输入长度公差上限" @input="onNonNegativeInput(idx, 'lengthTolPos')" @blur="onNonNegativeBlur(idx, 'lengthTolPos', 2)" />
97 97 </template>
98 98 </uni-list-item>
99   - <uni-list-item title="长度公差(单项-)">
  99 + <uni-list-item title="长度公差下限(mm)">
100 100 <template v-slot:footer>
101   - <uni-easyinput v-model="item.lengthTolNeg" :inputBorder="false"
102   - placeholder="请输入长度公差(单项-)" />
  101 + <uni-easyinput type="digit" v-model="item.lengthTolNeg" :inputBorder="false"
  102 + placeholder="请输入长度公差下限" @input="onNonNegativeInput(idx, 'lengthTolNeg')" @blur="onNonNegativeBlur(idx, 'lengthTolNeg', 2)" />
103 103 </template>
104 104 </uni-list-item>
105 105 <uni-list-item title="状态">
... ... @@ -109,12 +109,12 @@
109 109 </uni-list-item>
110 110 <uni-list-item title="数量">
111 111 <template v-slot:footer>
112   - <uni-easyinput v-model="item.quantity" type="number" :inputBorder="false" placeholder="请输入数量" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'quantity', 0)" />
  112 + <uni-easyinput v-model="item.quantity" type="digit" :inputBorder="false" placeholder="请输入数量kg" @input="onNonNegativeInput(idx, 'quantity')" @blur="onNonNegativeBlur(idx, 'quantity', 2)" />
113 113 </template>
114 114 </uni-list-item>
115 115 <uni-list-item title="单价">
116 116 <template v-slot:footer>
117   - <uni-easyinput v-model="item.unitPrice" type="number" :inputBorder="false" placeholder="-" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'unitPrice', 0)" disabled />
  117 + <uni-easyinput v-model="item.unitPrice" type="digit" :inputBorder="false" disabled placeholder="请输入销售价格" @input="onNonNegativeInput(idx, 'unitPrice')" @blur="onNonNegativeBlur(idx, 'unitPrice', 2)" />
118 118 </template>
119 119 </uni-list-item>
120 120 <uni-list-item title="不含税金额">
... ... @@ -129,7 +129,7 @@
129 129 </uni-list-item>
130 130 <uni-list-item title="发货日期">
131 131 <template v-slot:footer>
132   - <uni-datetime-picker type="date" v-model="item.orderDate" @change="onDateChange(idx, $event)" />
  132 + <uni-datetime-picker :start="minDeliveryDate" type="date" v-model="item.deliveryDate" @change="onDateChange(idx, $event)" />
133 133 </template>
134 134 </uni-list-item>
135 135 </uni-list>
... ... @@ -151,7 +151,30 @@
151 151 <view class="row"><text class="label">行业</text><text class="value">{{ item.industry }}</text></view>
152 152 <view class="row"><text class="label">牌号</text><text class="value">{{ item.brand }}</text></view>
153 153 <view class="row"><text class="label">品质</text><text class="value">{{ item.quality }}</text></view>
154   - <view class="row"><text class="label">规格</text><text class="value">{{ item.specDisplay }}</text></view>
  154 + <!-- 厚(公差) * 宽(公差) * 长(公差) -->
  155 + <view class="row row-spec"><text class="label">规格(mm)</text>
  156 + <view class="value value-spec">
  157 + <view v-if="item.thickness" class="value-spec_val">{{ item.thickness }}</view>
  158 + <view v-if="item.thickness" class="value-spec_box">
  159 + <view v-if="item.thicknessTolPos" class="value-spec_box_1">+{{ item.thicknessTolPos }}
  160 + </view>
  161 + <view v-if="item.thicknessTolNeg" class="value-spec_box_2">-{{ item.thicknessTolNeg }}
  162 + </view>
  163 + </view>
  164 + <view v-if="item.width" class="value-spec_val p12">*</view>
  165 + <view v-if="item.width" class="value-spec_val">{{ item.width }}</view>
  166 + <view v-if="item.width" class="value-spec_box">
  167 + <view v-if="item.widthTolPos" class="value-spec_box_1">+{{ item.widthTolPos }}</view>
  168 + <view v-if="item.widthTolNeg" class="value-spec_box_2">-{{ item.widthTolNeg }}</view>
  169 + </view>
  170 + <view v-if="item.length" class="value-spec_val p12">*</view>
  171 + <view v-if="item.length" class="value-spec_val">{{ item.length }}</view>
  172 + <view v-if="item.length" class="value-spec_box">
  173 + <view v-if="item.lengthTolPos" class="value-spec_box_1">+{{ item.lengthTolPos }}</view>
  174 + <view v-if="item.lengthTolNeg" class="value-spec_box_2">-{{ item.lengthTolNeg }}</view>
  175 + </view>
  176 + </view>
  177 + </view>
155 178 <view class="row"><text class="label">状态</text><text class="value">{{ item.status }}</text></view>
156 179 <view class="row"><text class="label">数量</text><text class="value">{{ item.quantity }}</text></view>
157 180 <view class="row"><text class="label">单价</text><text class="value">{{ formatCurrency(item.unitPrice)
... ... @@ -162,7 +185,7 @@
162 185 }}</text></view>
163 186 <view class="row"><text class="label">总金额</text><text class="value">{{ formatCurrency(item.totalAmount)
164 187 }}</text></view>
165   - <view class="row"><text class="label">发货日期</text><text class="value">{{ item.orderDate }}</text></view>
  188 + <view class="row"><text class="label">发货日期</text><text class="value">{{ item.deliveryDate }}</text></view>
166 189 </view>
167 190 </view>
168 191 <SingleSelectSheet :visible.sync="sheet.visible" :title="sheet.title" :options="sheet.options" v-model="sheet.value" @confirm="onProductConfirm" />
... ... @@ -176,7 +199,8 @@ export default {
176 199 mode: { type: String, default: 'add' },
177 200 list: { type: Array, default: () => [] },
178 201 max: { type: Number, default: 8 },
179   - orderDateBase: { type: String, default: '' },
  202 + deliveryDateBase: { type: String, default: '' },
  203 + deliveryDate: { type: String, default: '' },
180 204 options: { type: Array, default: () => [] }
181 205 },
182 206 components: { SingleSelectSheet },
... ... @@ -194,6 +218,22 @@ export default {
194 218 label: o.label != null ? o.label : (o.text != null ? o.text : (o.name != null ? o.name : '')),
195 219 value: o.value != null ? o.value : (o.id != null ? o.id : o.productId)
196 220 }))
  221 + },
  222 +
  223 + minDeliveryDate() {
  224 + const s = this.deliveryDate
  225 + if (!s) return ''
  226 + const parts = String(s).split('-')
  227 + const y = Number(parts[0])
  228 + const m = Number(parts[1])
  229 + const d = Number(parts[2])
  230 + if (!y || !m || !d) return ''
  231 + const dt = new Date(y, m - 1, d)
  232 + dt.setDate(dt.getDate() + 1)
  233 + const yy = dt.getFullYear()
  234 + const mm = String(dt.getMonth() + 1).padStart(2, '0')
  235 + const dd = String(dt.getDate() - 1).padStart(2, '0')
  236 + return `${yy}/${mm}/${dd}`
197 237 }
198 238 },
199 239 watch: {
... ... @@ -218,10 +258,18 @@ export default {
218 258 },
219 259 methods: {
220 260 defaultItem() {
221   - return { productId: '', productName: '', industry: '', brand: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', status: '', quantity: '', unitPrice: '', amountExcludingTax: 0, totalAmount: 0, orderDate: '' }
  261 + return { productId: '', productName: '', industry: '', brand: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', status: '', quantity: '', unitPrice: '', amountExcludingTax: 0, totalAmount: 0, deliveryDate: '' }
222 262 },
223   - onImmediateChange(idx) {
224   - this.$nextTick(() => this.recalculate(idx))
  263 + onNonNegativeInput(idx, field) {
  264 + const it = this.items[idx]
  265 + if (!it) return
  266 + let v = String(it[field] != null ? it[field] : '')
  267 + v = v.replace(/[^0-9.]/g, '')
  268 + v = v.replace(/(\..*)\./g, '$1')
  269 + if (v.startsWith('.')) v = '0' + v
  270 + it[field] = v
  271 + this.$set(this.items, idx, it)
  272 + if (field === 'quantity' || field === 'unitPrice') this.$nextTick(() => this.recalculate(idx))
225 273 },
226 274 toNumber(val) {
227 275 if (typeof val === 'number') return isNaN(val) ? 0 : val
... ... @@ -234,21 +282,21 @@ export default {
234 282 const m = Math.pow(10, digits)
235 283 return Math.round(n * m) / m
236 284 },
237   - onNumberBlur(idx, field, digits) {
  285 + onNonNegativeBlur(idx, field, digits) {
238 286 const it = this.items[idx]
239 287 if (!it) return
240 288 const raw = it[field]
241   - // 如果为空则保持为空,不自动置为0,仅重新计算依赖字段
242 289 if (raw === '' || raw === null || raw === undefined) {
243 290 this.$set(this.items, idx, it)
244   - this.recalculate(idx)
  291 + if (field === 'quantity' || field === 'unitPrice') this.recalculate(idx)
245 292 return
246 293 }
247   - const num = this.toNumber(raw)
  294 + let num = this.toNumber(raw)
  295 + if (isNaN(num) || num < 0) num = 0
248 296 const rounded = this.round(num, digits)
249 297 it[field] = rounded
250 298 this.$set(this.items, idx, it)
251   - this.recalculate(idx)
  299 + if (field === 'quantity' || field === 'unitPrice') this.recalculate(idx)
252 300 },
253 301 formatCurrency(val) {
254 302 if (val == null || val === '') return ''
... ... @@ -319,15 +367,15 @@ export default {
319 367 onDateChange(idx, e) {
320 368 const it = this.items[idx]
321 369 if (!it) return
322   - const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.orderDate
  370 + const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.deliveryDate
323 371 const dateStr = String(val).slice(0, 10)
324   - const base = this.orderDateBase ? new Date(this.orderDateBase) : null
  372 + const base = this.deliveryDateBase ? new Date(this.deliveryDateBase) : null
325 373 const d = new Date(dateStr)
326 374 if (base && !isNaN(d.getTime()) && d.getTime() < base.getTime()) {
327 375 uni.showToast({ title: '发货日期不得早于订货日期', icon: 'none' })
328   - it.orderDate = this.orderDateBase
  376 + it.deliveryDate = this.deliveryDateBase
329 377 } else {
330   - it.orderDate = dateStr
  378 + it.deliveryDate = dateStr
331 379 }
332 380 this.$set(this.items, idx, it)
333 381 },
... ... @@ -500,8 +548,46 @@ export default {
500 548
501 549 .value {
502 550 flex: 1;
503   - text-align: right;
  551 + // text-align: right;
504 552 color: rgba(0, 0, 0, 0.9);
505 553 font-size: 28rpx;
506 554 }
  555 + .value-spec {
  556 + height: 48rpx;
  557 + display: flex;
  558 + align-items: center;
  559 + color: #000000;
  560 + // justify-content: end;
  561 + &_box {
  562 + position: relative;
  563 + width: 60rpx;
  564 + height: 48rpx;
  565 +
  566 + &_1 {
  567 + font-size: 16rpx;
  568 + position: absolute;
  569 + top: -10rpx;
  570 + left: 0;
  571 + }
  572 +
  573 + &_2 {
  574 + font-size: 16rpx;
  575 + position: absolute;
  576 + bottom: -10rpx;
  577 + left: 0;
  578 + }
  579 + }
  580 +
  581 + &_val {
  582 + font-size: 28rpx;
  583 +
  584 + &.p12 {
  585 + padding-right: 12rpx;
  586 + }
  587 + }
  588 + }
  589 + .row-spec {
  590 + height: 60rpx;
  591 + align-items: center;
  592 + }
507 593 </style>
... ...
... ... @@ -25,7 +25,7 @@
25 25
26 26 <script>
27 27 import DetailButtons from '@/components/detail-buttons/index.vue'
28   -import { getSpecDetailApi } from '@/api/contract.js'
  28 +import { getSpecDetailApi, cancelApi } from '@/api/contract.js'
29 29
30 30 export default {
31 31 components: { DetailButtons },
... ... @@ -35,14 +35,24 @@ export default {
35 35 form: {
36 36 id: '', contractCode: '', customerName: '', deptName: '', workshopName: '', contractType: '', contractDocumentDate: '', applicationCount: '', totalQuantity: '', specLockDate: '', delayReason: '', orderDate: ''
37 37
38   - }
  38 + },
  39 + buttons: [
  40 + { text: '编辑', variant: 'outline', visible: true, event: 'edit' },
  41 + { text: '审核', variant: 'outline', visible: true, event: 'audit' },
  42 + { text: '审核详情', variant: 'outline', visible: true, event: 'auditDetail' },
  43 + { text: '取消', variant: 'danger', visible: true, event: 'cancel' },
  44 + ]
39 45 }
40 46 },
41 47 computed: {
42 48 displayButtons() {
  49 + const s = this.form.approvalStatus || false
  50 + const e = this.form.showExamine || false
43 51 return [
44   - // { text: '删除', variant: 'danger' },
45   - { text: '编辑', variant: 'outline' }
  52 + { ...this.buttons[0], visible: (s === 'REFUSE' && this.$auth.hasPermi('contract-manage:unlocked-operation-application:modify')) },
  53 + { ...this.buttons[1], visible: (s === 'AUDIT' && e && this.$auth.hasPermi('contract-manage:unlocked-operation-application:approve')) },
  54 + { ...this.buttons[2], visible: (s !== 'REFUSE' && this.$auth.hasPermi('contract-manage:unlocked-operation-application:review')) },
  55 + { ...this.buttons[3], visible: (s === 'REFUSE' && this.$auth.hasPermi('contract-manage:unlocked-operation-application:cancel')) },
46 56 ]
47 57 }
48 58 },
... ... @@ -60,6 +70,7 @@ export default {
60 70 const m = d || {}
61 71 const yesNo = m.hasFrameworkAgreement === 'Y' || m.hasFrameworkAgreement === true
62 72 this.form = {
  73 + ...res.data || {},
63 74 id: m.id || '',
64 75 contractCode: m.contractCode || '',
65 76 customerName: m.customerName || (m.customer && m.customer.name) || '',
... ... @@ -75,13 +86,52 @@ export default {
75 86 }
76 87 })
77 88 },
  89 + onEdit() {
  90 + if (!this.form.id) return
  91 + uni.navigateTo({ url: `/pages/contract_unlocked_operation/modify?id=${this.form.id}` })
  92 + },
  93 + onAudit(id, type) {
  94 + const CACHE_KEY = 'sourceBusinessId'
  95 + // const TYPE = 'contractType'
  96 + // uni.setStorageSync(TYPE, type)
  97 + uni.setStorageSync(CACHE_KEY, id)
  98 + uni.navigateTo({ url: '/pages/flow/audit' })
  99 + },
  100 + onAuditDetail(id, type) {
  101 + console.log(id,'id')
  102 + const CACHE_KEY = 'sourceBusinessId'
  103 + // const TYPE = 'contractType'
  104 + // uni.setStorageSync(TYPE, type)
  105 + uni.setStorageSync(CACHE_KEY, id)
  106 + uni.navigateTo({ url: '/pages/flow/audit_detail' })
  107 + },
  108 + onCancel(id) {
  109 + uni.showModal({
  110 + title: '确认取消吗?',
  111 + success: (res) => {
  112 + if (res.confirm) {
  113 + uni.showLoading({ title: '取消中...' })
  114 + cancelApi(id).then(res => {
  115 + uni.hideLoading()
  116 + if (res.code === 200) {
  117 + uni.showToast({ title: '取消成功' })
  118 + this.loadDetail()
  119 + } else {
  120 + uni.showToast({ title: res.msg || '取消失败' })
  121 + }
  122 + })
  123 + }
  124 + }
  125 + })
  126 + },
78 127 handleButtonClick(btn) {
79   - if (btn && btn.text === '编辑') {
80   - return uni.navigateTo({ url: `/pages/contract_unlocked_operation/modify?id=${this.id}` })
81   - }
82   - // if (btn && btn.text === '删除') {
83   - // uni.showToast({ title: '暂未接入删除接口', icon: 'none' })
84   - // }
  128 + if (!btn || btn.disabled) return
  129 + if (typeof btn.onClick === 'function') return btn.onClick(this.form, btn.params)
  130 + const e = btn.event || ''
  131 + if (e === 'edit') return this.onEdit(btn && btn.params)
  132 + if (e === 'audit') return this.onAudit(this.form.id || '')
  133 + if (e === 'auditDetail') return this.onAuditDetail(this.form.id || '')
  134 + if (e === 'cancel') return this.onCancel(this.form.id || '')
85 135 }
86 136 }
87 137 }
... ...
... ... @@ -6,7 +6,7 @@
6 6 cancelButton="none" bgColor="#F3F3F3" textColor="rgba(0,0,0,0.4)" @confirm="search" @input="onSearchInput" />
7 7 <view class="tool-icons">
8 8 <!-- <image class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" /> -->
9   - <!-- <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" /> -->
  9 + <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
10 10 </view>
11 11 </view>
12 12
... ... @@ -39,22 +39,19 @@
39 39 </card-list>
40 40 </view>
41 41 <!-- 筛选弹框 -->
42   - <!-- <filter-modal :visible.sync="filterVisible" :value.sync="filterForm" title="筛选" @reset="onFilterReset"
  42 + <filter-modal :visible.sync="filterVisible" :value.sync="filterForm" title="筛选" @reset="onFilterReset"
43 43 @confirm="onFilterConfirm">
44 44 <template v-slot="{ model }">
45 45 <view class="filter-form">
46 46 <view class="form-item">
47   - <view class="label">品种</view>
  47 + <view class="label">审核状态</view>
48 48 <uni-data-checkbox mode="tag" :multiple="false" :value-field="'value'" :text-field="'text'"
49   - v-model="model.materialTypeId" @change="onMaterialTypeChange" :localdata="materialTypeOptions" />
50   - </view>
51   - <view class="form-item">
52   - <view class="label">授权截止时间</view>
53   - <uni-datetime-picker type="daterange" v-model="model.dateRange" start="2023-01-01" />
  49 + v-model="model.approvalStatus" @change="onApprovalStatusChange" :localdata="auditStatusOptions" />
54 50 </view>
  51 +
55 52 </view>
56 53 </template>
57   - </filter-modal> -->
  54 + </filter-modal>
58 55 </view>
59 56 </template>
60 57
... ... @@ -74,13 +71,14 @@ export default {
74 71 // 批量选择
75 72 batchMode: false,
76 73 // 给到 card 的筛选值
77   - query: { materialTypeId: '', dateRange: [] },
  74 + query: { materialTypeId: '', dateRange: [], approvalStatus: '' },
78 75 extraParams: {},
79 76
80 77 // 筛选弹框
81 78 filterVisible: false,
82   - filterForm: { materialTypeId: '', dateRange: [] },
  79 + filterForm: { materialTypeId: '', dateRange: [], approvalStatus: '' },
83 80 materialTypeOptions: [],
  81 + auditStatusOptions: [],
84 82 statusMap
85 83 }
86 84
... ... @@ -93,6 +91,7 @@ export default {
93 91 },
94 92 created() {
95 93 this.getProductVariety();
  94 + this.loadAuditStatusOptions();
96 95 },
97 96 // 页面触底兜底:当页面自身滚动到底部时,转调卡片组件加载更多
98 97 onReachBottom() {
... ... @@ -162,6 +161,9 @@ export default {
162 161 },
163 162 onFilterConfirm(payload) {
164 163 // 合并筛选值
  164 + if ((payload.approvalStatus === '' || payload.approvalStatus == null) && this.filterForm.approvalStatus !== '') {
  165 + payload.approvalStatus = this.filterForm.approvalStatus
  166 + }
165 167 this.query = { ...this.query, ...payload }
166 168 },
167 169 onMaterialTypeChange(e) {
... ... @@ -198,6 +200,22 @@ export default {
198 200 }))
199 201 })
200 202 },
  203 + async loadAuditStatusOptions() {
  204 + try {
  205 + const dicCodes = ['AUDIT_STATUS']
  206 + const results = await getDicByCodes(dicCodes)
  207 + const option = (results.AUDIT_STATUS && results.AUDIT_STATUS.data) || []
  208 + this.auditStatusOptions = option.map(it => ({ value: it.code, text: it.name }))
  209 + } catch (e) {
  210 + this.auditStatusOptions = []
  211 + }
  212 + },
  213 + onApprovalStatusChange(e) {
  214 + const raw = e && e.detail && e.detail.value !== undefined
  215 + ? e.detail.value
  216 + : (e && e.value !== undefined ? e.value : '')
  217 + this.filterForm.approvalStatus = raw
  218 + },
201 219 }
202 220 }
203 221 </script>
... ...
... ... @@ -39,7 +39,7 @@
39 39 <view class="item-title"><text class="required">*</text><text>生产厂</text></view>
40 40 </template>
41 41 </uni-list-item>
42   - <ProductRel mode="add" :orderDateBase="form.orderDate" @change="onProductsChange" :options="productList" />
  42 + <ProductRel mode="add" :deliveryDate="form.orderDate" :deliveryDateBase="form.deliveryDate" @change="onProductsChange" :options="productList" />
43 43 <uni-list-item title="合计人民币金额(大写)">
44 44 <template v-slot:footer>
45 45 <uni-easyinput v-model="form.totalAmountCapital" placeholder="自动计算" :inputBorder="false" disabled />
... ... @@ -92,33 +92,25 @@
92 92 :inputBorder="false" />
93 93 </template>
94 94 </uni-list-item>
95   - <view class="group">
96   - <view class="group-title">特别条款要求</view>
97   - <view class="radio-list">
98   - <view v-for="(opt, i) in specialTermsList" :key="'cr-' + i" class="radio-item"
99   - @click="onRadioSelect('specialTerms', 'specialTermsName', opt)">
100   - <view :class="['radio', { checked: form.specialTerms === opt.value }]" />
101   - <text class="label">{{ opt.label }}</text>
102   - </view>
103   - </view>
104   - </view>
105   - <view class="group">
106   - <view class="group-title">执行标准</view>
107   - <view class="radio-list">
108   - <view v-for="(opt, i) in executionStandardList" :key="'es-' + i" class="radio-item"
109   - @click="onRadioSelect('executionStandard', 'executionStandardName', opt)">
110   - <view :class="['radio', { checked: form.executionStandard === opt.value }]" />
111   - <text class="label">{{ opt.label }}</text>
112   - </view>
113   - </view>
114   - </view>
  95 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  96 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  97 + <template v-slot:body>
  98 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  99 + </template>
  100 + </uni-list-item>
  101 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  102 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  103 + <template v-slot:body>
  104 + <view class="item-title"><text>执行标准</text></view>
  105 + </template>
  106 + </uni-list-item>
115 107 <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
116 108 <template v-slot:footer>
117 109 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注"
118 110 :inputBorder="false" />
119 111 </template>
120 112 </uni-list-item>
121   - <uni-list-item title="特别说明">
  113 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
122 114 <template v-slot:footer>
123 115 <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
124 116 </template>
... ... @@ -180,8 +172,8 @@
180 172 <div class="total-item-text">
181 173 数量
182 174 </div>
183   - <div class="total-item-price">
184   - {{ (sumQuantity || 0).toFixed(2) }}t
  175 + <div class="total-item-price">
  176 + {{ (totalQuantity || 0).toFixed(2) }}kg
185 177 </div>
186 178 </div>
187 179 <div class="total-item">
... ... @@ -189,7 +181,7 @@
189 181 不含税金额
190 182 </div>
191 183 <div class="total-item-price text-red">
192   - ¥{{ (sumAmountExcl || 0).toFixed(2) }}
  184 + ¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}
193 185 </div>
194 186 </div>
195 187 <div class="total-item">
... ... @@ -197,7 +189,7 @@
197 189 总金额
198 190 </div>
199 191 <div class="total-item-price text-red">
200   - ¥{{ (sumTotal || 0).toFixed(2) }}
  192 + ¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}
201 193 </div>
202 194 </div>
203 195 </div>
... ... @@ -233,6 +225,7 @@ export default {
233 225 buyer: '',
234 226 buyerName: '',
235 227 orderDate: '',
  228 + deliveryDate: '',
236 229 designatedConsignee: '',
237 230 specialTerms: '',
238 231 specialTermsName: '',
... ... @@ -263,9 +256,9 @@ export default {
263 256 yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
264 257 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
265 258 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
266   - sumQuantity: 0,
267   - sumAmountExcl: 0,
268   - sumTotal: 0,
  259 + totalQuantity: 0,
  260 + totalAmountExcludingTax: 0,
  261 + totalAmountIncludingTax: 0,
269 262 productLineList: [],
270 263 productList: [],
271 264 customerRemarks: [],
... ... @@ -308,6 +301,8 @@ export default {
308 301 productLineList: {
309 302 deep: true,
310 303 handler(newVal, oldVal) {
  304 + console.log('newVal', newVal)
  305 + console.log('oldVal', oldVal)
311 306 const n = Array.isArray(newVal) ? newVal : []
312 307 const o = Array.isArray(oldVal) ? oldVal : []
313 308 const changed = []
... ... @@ -364,13 +359,14 @@ export default {
364 359 });
365 360 },
366 361 onProductsChange(products) {
  362 + console.log('products', products)
367 363 const list = Array.isArray(products) ? products : []
368 364 const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
369 365 const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
370 366 const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
371   - this.sumQuantity = sumQ
372   - this.sumAmountExcl = sumE
373   - this.sumTotal = sumT
  367 + this.totalQuantity = sumQ
  368 + this.totalAmountExcludingTax = sumE
  369 + this.totalAmountIncludingTax = sumT
374 370 this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
375 371 this.productLineList = list
376 372 },
... ... @@ -446,6 +442,10 @@ export default {
446 442 setSheet('生产厂', opts)
447 443 } else if (field === 'supplier') {
448 444 setSheet('供方', this.supplierList)
  445 + } else if (field === 'specialTerms') {
  446 + setSheet('特别条款要求', this.specialTermsList)
  447 + } else if (field === 'executionStandard') {
  448 + setSheet('执行标准', this.executionStandardList)
449 449 } else if (field === 'includesPackagingFee') {
450 450 setSheet('单价中是否已包含包装费', this.yesNoList)
451 451 } else if (field === 'includesTransportFee') {
... ... @@ -516,9 +516,9 @@ export default {
516 516 ...formForSubmit,
517 517 destination,
518 518 type: 'DRAFT_DIST_AGMT',
519   - sumQuantity: this.sumQuantity,
520   - sumAmountExcl: this.sumAmountExcl,
521   - sumTotal: this.sumTotal,
  519 + totalQuantity: this.totalQuantity,
  520 + totalAmountExcludingTax: this.totalAmountExcludingTax,
  521 + totalAmountIncludingTax: this.totalAmountIncludingTax,
522 522 contractDistributorLineList: lines
523 523 })
524 524 console.log('onSubmit__payload', payload)
... ... @@ -537,18 +537,31 @@ export default {
537 537 { key: 'supplier', label: '供方' },
538 538 { key: 'buyer', label: '需方' },
539 539 { key: 'orderDate', label: '订货日期' },
  540 + { key: 'unit', label: '单位' },
540 541 { key: 'workshopId', label: '生产厂' },
  542 + { key: 'specialTerms', label: '特别条款要求' },
541 543 ]
542 544 for (const it of checks) {
543 545 const val = this.form[it.key]
544 546 const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
545 547 if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
546 548 }
547   - if (!Array.isArray(this.productLineList) || this.productLineList.length === 0) {
  549 + const list = Array.isArray(this.productLineList) ? this.productLineList : []
  550 + if (list.length === 0) {
548 551 uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
549 552 }
550   - for (const [idx, it] of this.productLineList.entries()) {
551   - if (!it.productName || !it.quantity || !it.unitPrice) {
  553 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  554 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  555 + for (const [idx, it] of list.entries()) {
  556 + if (
  557 + strEmpty(it.productName) ||
  558 + strEmpty(it.industry) ||
  559 + strEmpty(it.quality) ||
  560 + strEmpty(it.brand) ||
  561 + numEmpty(it.quantity) ||
  562 + numEmpty(it.unitPrice) ||
  563 + strEmpty(it.deliveryDate)
  564 + ) {
552 565 uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
553 566 }
554 567 }
... ... @@ -576,7 +589,7 @@ export default {
576 589 color: rgba(0, 0, 0, 0.6);
577 590 line-height: 32rpx;
578 591 width: 240rpx;
579   - padding: 24rpx 0;
  592 + padding: 12rpx 0;
580 593 }
581 594 .total-item-price {
582 595 font-weight: 600;
... ... @@ -598,7 +611,7 @@ export default {
598 611
599 612 .scroll {
600 613 flex: 1;
601   - padding: 12rpx 0 480rpx !important;
  614 + padding: 12rpx 0 392rpx !important;
602 615 }
603 616
604 617 .footer {
... ...
... ... @@ -53,7 +53,7 @@
53 53 }}</text></view>
54 54 </view>
55 55
56   - <view class="section">
  56 + <view class="section" v-if="detail.status === 'STANDARD'">
57 57 <view class="row"><text class="label">规范性合同</text><text class="value" style="color: #3D48A3;">{{
58 58 detail.standardFileName || '-'
59 59 }}</text></view>
... ... @@ -61,7 +61,7 @@
61 61 detail.standardStandardized ? '是' : '否'
62 62 }}</text></view>
63 63 </view>
64   - <view class="section" v-if="status === 'FORMAL'">
  64 + <view class="section" v-if="detail.status === 'FORMAL'">
65 65 <view class="row"><text class="label">规范性合同</text><text class="value" style="color: #3D48A3;">{{
66 66 detail.formalFileName || '-' }}</text></view>
67 67 <view class="row"><text class="label">合同是否规范</text><text class="value">{{ detail.formalStandardized
... ... @@ -114,7 +114,7 @@
114 114 </template>
115 115
116 116 <script>
117   -import { getContractApi, deleteContractApi, uploadFormalContract, statusStyle } from '@/api/contract'
  117 +import { getContractApi, deleteContractApi, uploadFormalContract, statusStyle, uploadStandardContract } from '@/api/contract'
118 118 import ProductRel from './productRel.vue'
119 119 import DetailButtons from '@/components/detail-buttons/index.vue'
120 120 import FileUpload from '@/components/file-upload/index.vue'
... ... @@ -265,19 +265,19 @@ export default {
265 265 const e = this.detail.showExamine || false
266 266 const f = this.detail.standardShowExamine || false
267 267 return [
268   - { ...this.buttons[0], visible: (s === 'DRAFT') },
269   - { ...this.buttons[1], visible: (s === 'DRAFT') },
270   - { ...this.buttons[2], visible: (s === 'FORMAL' && !l) },
271   - { ...this.buttons[3], visible: (s === 'FORMAL' && !l) },
272   - { ...this.buttons[4], visible: ((s === 'DRAFT' || s === 'FORMAL') && t !== 'AUDIT' && t !== 'PASS') },
273   - { ...this.buttons[5], visible: (s === 'STANDARD' && t !== 'AUDIT' && t !== 'PASS') },
274   - { ...this.buttons[6], visible: (s === 'STANDARD' && a !== 'AUDIT' && a !== 'PASS') },
275   - { ...this.buttons[7], visible: (s === 'FORMAL' && e && t === 'AUDIT') },
276   - { ...this.buttons[8], visible: (s === 'STANDARD' && e && t === 'AUDIT') },
277   - { ...this.buttons[9], visible: (s === 'STANDARD' && f && a === 'AUDIT') },
278   - { ...this.buttons[10], visible: (s === 'FORMAL' && t) },
279   - { ...this.buttons[11], visible: (s === 'STANDARD' && t) },
280   - { ...this.buttons[12], visible: (s === 'STANDARD' && a) },
  268 + { ...this.buttons[0], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:distribution-unlocked-contract:modify')) },
  269 + { ...this.buttons[1], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:distribution-unlocked-contract:delete')) },
  270 + { ...this.buttons[2], visible: (s === 'FORMAL' && !l && this.$auth.hasPermi('contract-manage:distribution-unlocked-contract:lock')) },
  271 + { ...this.buttons[3], visible: (s === 'FORMAL' && !l && this.$auth.hasPermi('contract-manage:distribution-unlocked-contract:lock-apply')) },
  272 + { ...this.buttons[4], visible: ((s === 'DRAFT' || s === 'FORMAL') && t !== 'AUDIT' && t !== 'PASS' && this.$auth.hasPermi('contract-manage:distribution-unlocked-contract:upload')) },
  273 + { ...this.buttons[5], visible: (s === 'STANDARD' && t !== 'AUDIT' && t !== 'PASS' && this.$auth.hasPermi('contract-manage:distribution-unlocked-contract:upload')) },
  274 + { ...this.buttons[6], visible: (s === 'STANDARD' && a !== 'AUDIT' && a !== 'PASS' && this.$auth.hasPermi('contract-manage:distribution-unlocked-contract:standard-upload')) },
  275 + { ...this.buttons[7], visible: (s === 'FORMAL' && e && t === 'AUDIT' && this.$auth.hasPermi('contract-manage:distribution-unlocked-contract:approve')) },
  276 + { ...this.buttons[8], visible: (s === 'STANDARD' && e && t === 'AUDIT' && this.$auth.hasPermi('contract-manage:distribution-unlocked-contract:approve')) },
  277 + { ...this.buttons[9], visible: (s === 'STANDARD' && f && a === 'AUDIT' && this.$auth.hasPermi('contract-manage:distribution-unlocked-contract:standard-approve')) },
  278 + { ...this.buttons[10], visible: (s === 'FORMAL' && t === 'AUDIT' && this.$auth.hasPermi('contract-manage:distribution-unlocked-contract:review')) },
  279 + { ...this.buttons[11], visible: (s === 'STANDARD' && t === 'AUDIT' && this.$auth.hasPermi('contract-manage:distribution-unlocked-contract:review')) },
  280 + { ...this.buttons[12], visible: (s === 'STANDARD' && a === 'AUDIT' && this.$auth.hasPermi('contract-manage:distribution-unlocked-contract:standard-review')) },
281 281 ]
282 282 }
283 283 },
... ...
... ... @@ -14,7 +14,7 @@
14 14 @input="onSearchInput"
15 15 />
16 16 <view class="tool-icons">
17   - <image class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
  17 + <image v-if="$auth.hasPermi('contract-manage:distribution-unlocked-contract:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
18 18 <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
19 19 </view>
20 20 </view>
... ... @@ -61,7 +61,9 @@
61 61 <text>订单总额</text><text class="amount" :style="{ color: '#b67a76' }">{{ item.totalAmountIncludingTax ? '¥' : '' }}{{ formatAmount(item.totalAmountIncludingTax) || '-' }}</text>
62 62 </view>
63 63 <view class="info-row" v-if="item.status === 'STANDARD' || item.status === 'FORMAL'">
64   - <text>{{ item.status === 'STANDARD' ? '标准合同' : '正式合同' }}规范性审核状态</text><span class="info-status" :style="item.standardApprovedName ? getStatusCss(item.standardApprovedName) : ''">{{ item.standardApprovedName || '-' }}</span>
  64 + <text>{{ item.status === 'STANDARD' ? '标准合同' : '正式合同' }}规范性审核状态</text>
  65 + <span v-if="item.status === 'STANDARD' ? item.standardApprovedName : item.formalApprovedName" class="info-status" :style="getStatusCss(item.status === 'STANDARD' ? item.standardApprovedName : item.formalApprovedName)">{{ item.status === 'STANDARD' ? item.standardApprovedName : item.formalApprovedName }}</span>
  66 + <span v-else>-</span>
65 67 </view>
66 68 <view class="info-row">
67 69 <text>订货日期</text><text>{{ item.orderDate }}</text>
... ...
... ... @@ -107,7 +107,7 @@
107 107 数量
108 108 </div>
109 109 <div class="total-item-price">
110   - {{ (sumQuantity || 0).toFixed(2) }}t
  110 + {{ (totalQuantity || 0).toFixed(2) }}kg
111 111 </div>
112 112 </div>
113 113 <div class="total-item">
... ... @@ -115,7 +115,7 @@
115 115 不含税金额
116 116 </div>
117 117 <div class="total-item-price text-red">
118   - ¥{{ (sumAmountExcl || 0).toFixed(2) }}
  118 + ¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}
119 119 </div>
120 120 </div>
121 121 <div class="total-item">
... ... @@ -123,7 +123,7 @@
123 123 总金额
124 124 </div>
125 125 <div class="total-item-price text-red">
126   - ¥{{ (sumTotal || 0).toFixed(2) }}
  126 + ¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}
127 127 </div>
128 128 </div>
129 129 </div>
... ... @@ -146,15 +146,15 @@ export default {
146 146 }
147 147 },
148 148 computed: {
149   - sumQuantity() {
  149 + totalQuantity() {
150 150 const qty = this.items.filter(it => it.locked).reduce((p, c) => p + this.toNumber(c.quantity), 0)
151 151 return this.round(qty, 2)
152 152 },
153   - sumAmountExcl() {
  153 + totalAmountExcludingTax() {
154 154 const sum = this.items.filter(it => it.locked).reduce((p, c) => p + this.toNumber(c.amountExcludingTax), 0)
155 155 return this.round(sum, 2)
156 156 },
157   - sumTotal() { return this.totalAmount },
  157 + totalAmountIncludingTax() { return this.totalAmount },
158 158 totalAmount() {
159 159 let sum = 0
160 160 for (const it of this.items) {
... ... @@ -325,9 +325,9 @@ export default {
325 325 const payload = {
326 326 id: this.id,
327 327 totalAmountCapital: formatCurrencyToChinese(this.sumTotal),
328   - totalAmountExcludingTax: this.sumAmountExcl,
329   - totalAmountIncludingTax: this.sumTotal,
330   - totalQuantity: this.sumQuantity,
  328 + totalAmountExcludingTax: this.totalAmountExcludingTax,
  329 + totalAmountIncludingTax: this.totalAmountIncludingTax,
  330 + totalQuantity: this.totalQuantity,
331 331 type:'DRAFT_DIST_AGMT',
332 332 contractDistributorLineList: selected
333 333 }
... ... @@ -362,7 +362,7 @@ export default {
362 362
363 363 .scroll {
364 364 flex: 1;
365   - padding: 12rpx 0 480rpx !important;
  365 + padding: 12rpx 0 392rpx !important;
366 366 }
367 367
368 368 .header {
... ... @@ -646,7 +646,7 @@ export default {
646 646 color: rgba(0, 0, 0, 0.6);
647 647 line-height: 32rpx;
648 648 width: 240rpx;
649   - padding: 24rpx 0;
  649 + padding: 12rpx 0;
650 650 }
651 651
652 652 .total-item-price {
... ...
... ... @@ -41,7 +41,7 @@
41 41 </template>
42 42 </uni-list-item>
43 43
44   - <ProductRel mode="add" :orderDateBase="form.orderDate" :list="productLineList" @change="onProductsChange" :options="productList" />
  44 + <ProductRel mode="add" :deliveryDateBase="form.deliveryDate" :deliveryDate="form.orderDate" :list="productLineList" @change="onProductsChange" :options="productList" />
45 45
46 46 <uni-list-item title="合计人民币金额(大写)">
47 47 <template v-slot:footer>
... ... @@ -99,33 +99,25 @@
99 99 </template>
100 100 </uni-list-item>
101 101
102   - <view class="group">
103   - <view class="group-title">特别条款要求</view>
104   - <view class="radio-list">
105   - <view v-for="(opt, i) in specialTermsList" :key="'cr-' + i" class="radio-item"
106   - @click="onRadioSelect('specialTerms', 'specialTermsName', opt)">
107   - <view :class="['radio', { checked: form.specialTerms === opt.value }]" />
108   - <text class="label">{{ opt.label }}</text>
109   - </view>
110   - </view>
111   - </view>
112   - <view class="group">
113   - <view class="group-title">执行标准</view>
114   - <view class="radio-list">
115   - <view v-for="(opt, i) in executionStandardList" :key="'es-' + i" class="radio-item"
116   - @click="onRadioSelect('executionStandard', 'executionStandardName', opt)">
117   - <view :class="['radio', { checked: form.executionStandard === opt.value }]" />
118   - <text class="label">{{ opt.label }}</text>
119   - </view>
120   - </view>
121   - </view>
  102 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  103 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  104 + <template v-slot:body>
  105 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  106 + </template>
  107 + </uni-list-item>
  108 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  109 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  110 + <template v-slot:body>
  111 + <view class="item-title"><text>执行标准</text></view>
  112 + </template>
  113 + </uni-list-item>
122 114 <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
123 115 <template v-slot:footer>
124 116 <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注"
125 117 :inputBorder="false" />
126 118 </template>
127 119 </uni-list-item>
128   - <uni-list-item title="特别说明">
  120 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
129 121 <template v-slot:footer>
130 122 <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
131 123 </template>
... ... @@ -177,15 +169,15 @@
177 169 <div class="total-text">合计</div>
178 170 <div class="total-item">
179 171 <div class="total-item-text">数量</div>
180   - <div class="total-item-price">{{ (sumQuantity || 0).toFixed(2) }}t</div>
  172 + <div class="total-item-price">{{ (totalQuantity || 0).toFixed(2) }}kg</div>
181 173 </div>
182 174 <div class="total-item">
183 175 <div class="total-item-text">不含税金额</div>
184   - <div class="total-item-price text-red">¥{{ (sumAmountExcl || 0).toFixed(2) }}</div>
  176 + <div class="total-item-price text-red">¥{{ (totalAmountExcludingTax || 0).toFixed(2) }}</div>
185 177 </div>
186 178 <div class="total-item">
187 179 <div class="total-item-text">总金额</div>
188   - <div class="total-item-price text-red">¥{{ (sumTotal || 0).toFixed(2) }}</div>
  180 + <div class="total-item-price text-red">¥{{ (totalAmountIncludingTax || 0).toFixed(2) }}</div>
189 181 </div>
190 182 </div>
191 183 <button class="btn submit" type="primary" @click="onSubmit">保存</button>
... ... @@ -223,6 +215,7 @@ export default {
223 215 workshopId: '',
224 216 workshopName: '',
225 217 orderDate: '',
  218 + deliveryDate: '',
226 219 designatedConsignee: '',
227 220 specialTerms: '',
228 221 specialTermsName: '',
... ... @@ -256,9 +249,9 @@ export default {
256 249 yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
257 250 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
258 251 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
259   - sumQuantity: 0,
260   - sumAmountExcl: 0,
261   - sumTotal: 0,
  252 + totalQuantity: 0,
  253 + totalAmountExcludingTax: 0,
  254 + totalAmountIncludingTax: 0,
262 255 productLineList: [],
263 256 newProductLineList: [],
264 257 productList: []
... ... @@ -349,9 +342,9 @@ export default {
349 342 const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
350 343 const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
351 344 const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
352   - this.sumQuantity = sumQ
353   - this.sumAmountExcl = sumE
354   - this.sumTotal = sumT
  345 + this.totalQuantity = sumQ
  346 + this.totalAmountExcludingTax = sumE
  347 + this.totalAmountIncludingTax = sumT
355 348 this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
356 349 },
357 350 async loadSuppliers() {
... ... @@ -399,6 +392,10 @@ export default {
399 392 setSheet('生产厂', opts)
400 393 } else if (field === 'supplier') {
401 394 setSheet('供方', this.supplierList)
  395 + } else if (field === 'specialTerms') {
  396 + setSheet('特别条款要求', this.specialTermsList)
  397 + } else if (field === 'executionStandard') {
  398 + setSheet('执行标准', this.executionStandardList)
402 399 } else if (field === 'includesPackagingFee') {
403 400 setSheet('单价中是否已包含包装费', this.yesNoList)
404 401 } else if (field === 'includesTransportFee') {
... ... @@ -439,22 +436,35 @@ export default {
439 436 },
440 437 validateRequired() {
441 438 const checks = [
442   - { key: 'code', label: '编号' },
  439 + { key: 'code', label: '编号' },
443 440 { key: 'supplier', label: '供方' },
444 441 { key: 'buyer', label: '需方' },
445 442 { key: 'orderDate', label: '订货日期' },
  443 + { key: 'unit', label: '单位' },
446 444 { key: 'workshopId', label: '生产厂' },
  445 + { key: 'specialTerms', label: '特别条款要求' },
447 446 ]
448 447 for (const it of checks) {
449 448 const val = this.form[it.key]
450 449 const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
451 450 if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
452 451 }
453   - if (!Array.isArray(this.productLineList) || this.productLineList.length === 0) {
  452 + const list = Array.isArray(this.newProductLineList) ? this.newProductLineList : []
  453 + if (list.length === 0) {
454 454 uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
455 455 }
456   - for (const [idx, it] of this.productLineList.entries()) {
457   - if (!it.productName || !it.quantity || !it.unitPrice) {
  456 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  457 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  458 + for (const [idx, it] of list.entries()) {
  459 + if (
  460 + strEmpty(it.productName) ||
  461 + strEmpty(it.industry) ||
  462 + strEmpty(it.quality) ||
  463 + strEmpty(it.brand) ||
  464 + numEmpty(it.quantity) ||
  465 + strEmpty(it.unitPrice) ||
  466 + strEmpty(it.deliveryDate)
  467 + ) {
458 468 uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
459 469 }
460 470 }
... ... @@ -486,9 +496,9 @@ export default {
486 496 id: this.form.id,
487 497 destination,
488 498 type: 'DRAFT_DIST_AGMT',
489   - sumQuantity: this.sumQuantity,
490   - sumAmountExcl: this.sumAmountExcl,
491   - sumTotal: this.sumTotal,
  499 + totalQuantity: this.totalQuantity,
  500 + totalAmountExcludingTax: this.totalAmountExcludingTax,
  501 + totalAmountIncludingTax: this.totalAmountIncludingTax,
492 502 contractDistributorLineList: lines
493 503 })
494 504 try {
... ... @@ -524,7 +534,7 @@ export default {
524 534 color: rgba(0, 0, 0, 0.6);
525 535 line-height: 32rpx;
526 536 width: 240rpx;
527   - padding: 24rpx 0;
  537 + padding: 12rpx 0;
528 538 }
529 539
530 540 .total-item-price {
... ... @@ -547,7 +557,7 @@ export default {
547 557
548 558 .scroll {
549 559 flex: 1;
550   - padding: 12rpx 0 480rpx !important;
  560 + padding: 12rpx 0 392rpx !important;
551 561 }
552 562
553 563 .footer {
... ...
... ... @@ -53,53 +53,53 @@
53 53 <uni-easyinput v-model="item.quality" :inputBorder="false" placeholder="请输入品质" />
54 54 </template>
55 55 </uni-list-item>
56   - <uni-list-item title="厚度">
  56 + <uni-list-item title="厚度(mm)">
57 57 <template v-slot:footer>
58   - <uni-easyinput v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" />
  58 + <uni-easyinput type="digit" v-model="item.thickness" :inputBorder="false" placeholder="请输入厚度" @input="onNonNegativeInput(idx, 'thickness')" @blur="onNonNegativeBlur(idx, 'thickness', 2)" />
59 59 </template>
60 60 </uni-list-item>
61   - <uni-list-item title="厚度公差(单项+)">
  61 + <uni-list-item title="厚度公差上限(mm)">
62 62 <template v-slot:footer>
63   - <uni-easyinput v-model="item.thicknessTolPos" :inputBorder="false"
64   - placeholder="请输入厚度公差(单项+)" />
  63 + <uni-easyinput type="digit" v-model="item.thicknessTolPos" :inputBorder="false"
  64 + placeholder="请输入厚度公差上限" @input="onNonNegativeInput(idx, 'thicknessTolPos')" @blur="onNonNegativeBlur(idx, 'thicknessTolPos', 2)" />
65 65 </template>
66 66 </uni-list-item>
67   - <uni-list-item title="厚度公差(单项-)">
  67 + <uni-list-item title="厚度公差下限(mm)">
68 68 <template v-slot:footer>
69   - <uni-easyinput v-model="item.thicknessTolNeg" :inputBorder="false"
70   - placeholder="请输入厚度公差(单项-)" />
  69 + <uni-easyinput type="digit" v-model="item.thicknessTolNeg" :inputBorder="false"
  70 + placeholder="请输入厚度公差下限" @input="onNonNegativeInput(idx, 'thicknessTolNeg')" @blur="onNonNegativeBlur(idx, 'thicknessTolNeg', 2)" />
71 71 </template>
72 72 </uni-list-item>
73   - <uni-list-item title="宽度">
  73 + <uni-list-item title="宽度(mm)">
74 74 <template v-slot:footer>
75   - <uni-easyinput v-model="item.width" :inputBorder="false" placeholder="请输入宽度" />
  75 + <uni-easyinput type="digit" v-model="item.width" :inputBorder="false" placeholder="请输入宽度" @input="onNonNegativeInput(idx, 'width')" @blur="onNonNegativeBlur(idx, 'width', 2)" />
76 76 </template>
77 77 </uni-list-item>
78   - <uni-list-item title="宽度公差(单项+)">
  78 + <uni-list-item title="宽度公差上限(mm)">
79 79 <template v-slot:footer>
80   - <uni-easyinput v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差(单项+)" />
  80 + <uni-easyinput type="digit" v-model="item.widthTolPos" :inputBorder="false" placeholder="请输入宽度公差上限" @input="onNonNegativeInput(idx, 'widthTolPos')" @blur="onNonNegativeBlur(idx, 'widthTolPos', 2)" />
81 81 </template>
82 82 </uni-list-item>
83   - <uni-list-item title="宽度公差(单项-)">
  83 + <uni-list-item title="宽度公差下限(mm)">
84 84 <template v-slot:footer>
85   - <uni-easyinput v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差(单项-)" />
  85 + <uni-easyinput type="digit" v-model="item.widthTolNeg" :inputBorder="false" placeholder="请输入宽度公差下限" @input="onNonNegativeInput(idx, 'widthTolNeg')" @blur="onNonNegativeBlur(idx, 'widthTolNeg', 2)" />
86 86 </template>
87 87 </uni-list-item>
88   - <uni-list-item title="长度">
  88 + <uni-list-item title="长度(mm)">
89 89 <template v-slot:footer>
90   - <uni-easyinput v-model="item.length" :inputBorder="false" placeholder="请输入长度" />
  90 + <uni-easyinput type="digit" v-model="item.length" :inputBorder="false" placeholder="请输入长度" @input="onNonNegativeInput(idx, 'length')" @blur="onNonNegativeBlur(idx, 'length', 2)" />
91 91 </template>
92 92 </uni-list-item>
93   - <uni-list-item title="长度公差(单项+)">
  93 + <uni-list-item title="长度公差上限(mm)">
94 94 <template v-slot:footer>
95   - <uni-easyinput v-model="item.lengthTolPos" :inputBorder="false"
96   - placeholder="请输入长度公差(单项+)" />
  95 + <uni-easyinput type="digit" v-model="item.lengthTolPos" :inputBorder="false"
  96 + placeholder="请输入长度公差上限" @input="onNonNegativeInput(idx, 'lengthTolPos')" @blur="onNonNegativeBlur(idx, 'lengthTolPos', 2)" />
97 97 </template>
98 98 </uni-list-item>
99   - <uni-list-item title="长度公差(单项-)">
  99 + <uni-list-item title="长度公差下限(mm)">
100 100 <template v-slot:footer>
101   - <uni-easyinput v-model="item.lengthTolNeg" :inputBorder="false"
102   - placeholder="请输入长度公差(单项-)" />
  101 + <uni-easyinput type="digit" v-model="item.lengthTolNeg" :inputBorder="false"
  102 + placeholder="请输入长度公差下限" @input="onNonNegativeInput(idx, 'lengthTolNeg')" @blur="onNonNegativeBlur(idx, 'lengthTolNeg', 2)" />
103 103 </template>
104 104 </uni-list-item>
105 105 <uni-list-item title="状态">
... ... @@ -109,12 +109,12 @@
109 109 </uni-list-item>
110 110 <uni-list-item title="数量">
111 111 <template v-slot:footer>
112   - <uni-easyinput v-model="item.quantity" type="number" :inputBorder="false" placeholder="请输入数量" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'quantity', 0)" />
  112 + <uni-easyinput v-model="item.quantity" type="digit" :inputBorder="false" placeholder="请输入数量kg" @input="onNonNegativeInput(idx, 'quantity')" @blur="onNonNegativeBlur(idx, 'quantity', 2)" />
113 113 </template>
114 114 </uni-list-item>
115 115 <uni-list-item title="单价">
116 116 <template v-slot:footer>
117   - <uni-easyinput v-model="item.unitPrice" type="number" :inputBorder="false" placeholder="请输入单价" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'unitPrice', 0)" />
  117 + <uni-easyinput v-model="item.unitPrice" type="digit" :inputBorder="false" placeholder="请输入销售价格" @input="onNonNegativeInput(idx, 'unitPrice')" @blur="onNonNegativeBlur(idx, 'unitPrice', 2)" />
118 118 </template>
119 119 </uni-list-item>
120 120 <uni-list-item title="不含税金额">
... ... @@ -129,7 +129,7 @@
129 129 </uni-list-item>
130 130 <uni-list-item title="发货日期">
131 131 <template v-slot:footer>
132   - <uni-datetime-picker type="date" v-model="item.orderDate" @change="onDateChange(idx, $event)" />
  132 + <uni-datetime-picker :start="minDeliveryDate" type="date" v-model="item.deliveryDate" @change="onDateChange(idx, $event)" />
133 133 </template>
134 134 </uni-list-item>
135 135 </uni-list>
... ... @@ -151,7 +151,30 @@
151 151 <view class="row"><text class="label">行业</text><text class="value">{{ item.industry }}</text></view>
152 152 <view class="row"><text class="label">牌号</text><text class="value">{{ item.brand }}</text></view>
153 153 <view class="row"><text class="label">品质</text><text class="value">{{ item.quality }}</text></view>
154   - <view class="row"><text class="label">规格</text><text class="value">{{ item.specDisplay }}</text></view>
  154 + <!-- 厚(公差) * 宽(公差) * 长(公差) -->
  155 + <view class="row row-spec"><text class="label">规格(mm)</text>
  156 + <view class="value value-spec">
  157 + <view v-if="item.thickness" class="value-spec_val">{{ item.thickness }}</view>
  158 + <view v-if="item.thickness" class="value-spec_box">
  159 + <view v-if="item.thicknessTolPos" class="value-spec_box_1">+{{ item.thicknessTolPos }}
  160 + </view>
  161 + <view v-if="item.thicknessTolNeg" class="value-spec_box_2">-{{ item.thicknessTolNeg }}
  162 + </view>
  163 + </view>
  164 + <view v-if="item.width" class="value-spec_val p12">*</view>
  165 + <view v-if="item.width" class="value-spec_val">{{ item.width }}</view>
  166 + <view v-if="item.width" class="value-spec_box">
  167 + <view v-if="item.widthTolPos" class="value-spec_box_1">+{{ item.widthTolPos }}</view>
  168 + <view v-if="item.widthTolNeg" class="value-spec_box_2">-{{ item.widthTolNeg }}</view>
  169 + </view>
  170 + <view v-if="item.length" class="value-spec_val p12">*</view>
  171 + <view v-if="item.length" class="value-spec_val">{{ item.length }}</view>
  172 + <view v-if="item.length" class="value-spec_box">
  173 + <view v-if="item.lengthTolPos" class="value-spec_box_1">+{{ item.lengthTolPos }}</view>
  174 + <view v-if="item.lengthTolNeg" class="value-spec_box_2">-{{ item.lengthTolNeg }}</view>
  175 + </view>
  176 + </view>
  177 + </view>
155 178 <view class="row"><text class="label">状态</text><text class="value">{{ item.status }}</text></view>
156 179 <view class="row"><text class="label">数量</text><text class="value">{{ item.quantity }}</text></view>
157 180 <view class="row"><text class="label">单价</text><text class="value">{{ formatCurrency(item.unitPrice)
... ... @@ -162,7 +185,7 @@
162 185 }}</text></view>
163 186 <view class="row"><text class="label">总金额</text><text class="value">{{ formatCurrency(item.totalAmount)
164 187 }}</text></view>
165   - <view class="row"><text class="label">发货日期</text><text class="value">{{ item.orderDate }}</text></view>
  188 + <view class="row"><text class="label">发货日期</text><text class="value">{{ item.deliveryDate }}</text></view>
166 189 </view>
167 190 </view>
168 191 <SingleSelectSheet :visible.sync="sheet.visible" :title="sheet.title" :options="sheet.options" v-model="sheet.value" @confirm="onProductConfirm" />
... ... @@ -176,7 +199,8 @@ export default {
176 199 mode: { type: String, default: 'add' },
177 200 list: { type: Array, default: () => [] },
178 201 max: { type: Number, default: 8 },
179   - orderDateBase: { type: String, default: '' },
  202 + deliveryDateBase: { type: String, default: '' },
  203 + deliveryDate: { type: String, default: '' },
180 204 options: { type: Array, default: () => [] }
181 205 },
182 206 components: { SingleSelectSheet },
... ... @@ -194,6 +218,21 @@ export default {
194 218 label: o.label != null ? o.label : (o.text != null ? o.text : (o.name != null ? o.name : '')),
195 219 value: o.value != null ? o.value : (o.id != null ? o.id : o.productId)
196 220 }))
  221 + },
  222 + minDeliveryDate() {
  223 + const s = this.deliveryDate
  224 + if (!s) return ''
  225 + const parts = String(s).split('-')
  226 + const y = Number(parts[0])
  227 + const m = Number(parts[1])
  228 + const d = Number(parts[2])
  229 + if (!y || !m || !d) return ''
  230 + const dt = new Date(y, m - 1, d)
  231 + dt.setDate(dt.getDate() + 1)
  232 + const yy = dt.getFullYear()
  233 + const mm = String(dt.getMonth() + 1).padStart(2, '0')
  234 + const dd = String(dt.getDate() - 1).padStart(2, '0')
  235 + return `${yy}/${mm}/${dd}`
197 236 }
198 237 },
199 238 watch: {
... ... @@ -218,10 +257,18 @@ export default {
218 257 },
219 258 methods: {
220 259 defaultItem() {
221   - return { productId: '', productName: '', industry: '', brand: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', status: '', quantity: '', unitPrice: '', amountExcludingTax: 0, totalAmount: 0, orderDate: '' }
  260 + return { productId: '', productName: '', industry: '', brand: '', quality: '', thickness: '', thicknessTolPos: '', thicknessTolNeg: '', width: '', widthTolPos: '', widthTolNeg: '', length: '', lengthTolPos: '', lengthTolNeg: '', status: '', quantity: '', unitPrice: '', amountExcludingTax: 0, totalAmount: 0, deliveryDate: '' }
222 261 },
223   - onImmediateChange(idx) {
224   - this.$nextTick(() => this.recalculate(idx))
  262 + onNonNegativeInput(idx, field) {
  263 + const it = this.items[idx]
  264 + if (!it) return
  265 + let v = String(it[field] != null ? it[field] : '')
  266 + v = v.replace(/[^0-9.]/g, '')
  267 + v = v.replace(/(\..*)\./g, '$1')
  268 + if (v.startsWith('.')) v = '0' + v
  269 + it[field] = v
  270 + this.$set(this.items, idx, it)
  271 + if (field === 'quantity' || field === 'unitPrice') this.$nextTick(() => this.recalculate(idx))
225 272 },
226 273 toNumber(val) {
227 274 if (typeof val === 'number') return isNaN(val) ? 0 : val
... ... @@ -234,21 +281,21 @@ export default {
234 281 const m = Math.pow(10, digits)
235 282 return Math.round(n * m) / m
236 283 },
237   - onNumberBlur(idx, field, digits) {
  284 + onNonNegativeBlur(idx, field, digits) {
238 285 const it = this.items[idx]
239 286 if (!it) return
240 287 const raw = it[field]
241   - // 如果为空则保持为空,不自动置为0,仅重新计算依赖字段
242 288 if (raw === '' || raw === null || raw === undefined) {
243 289 this.$set(this.items, idx, it)
244   - this.recalculate(idx)
  290 + if (field === 'quantity' || field === 'unitPrice') this.recalculate(idx)
245 291 return
246 292 }
247   - const num = this.toNumber(raw)
  293 + let num = this.toNumber(raw)
  294 + if (isNaN(num) || num < 0) num = 0
248 295 const rounded = this.round(num, digits)
249 296 it[field] = rounded
250 297 this.$set(this.items, idx, it)
251   - this.recalculate(idx)
  298 + if (field === 'quantity' || field === 'unitPrice') this.recalculate(idx)
252 299 },
253 300 formatCurrency(val) {
254 301 if (val == null || val === '') return ''
... ... @@ -319,15 +366,15 @@ export default {
319 366 onDateChange(idx, e) {
320 367 const it = this.items[idx]
321 368 if (!it) return
322   - const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.orderDate
  369 + const val = typeof e === 'string' ? e : (e && e.detail && e.detail.value) ? e.detail.value : it.deliveryDate
323 370 const dateStr = String(val).slice(0, 10)
324   - const base = this.orderDateBase ? new Date(this.orderDateBase) : null
  371 + const base = this.deliveryDateBase ? new Date(this.deliveryDateBase) : null
325 372 const d = new Date(dateStr)
326 373 if (base && !isNaN(d.getTime()) && d.getTime() < base.getTime()) {
327 374 uni.showToast({ title: '发货日期不得早于订货日期', icon: 'none' })
328   - it.orderDate = this.orderDateBase
  375 + it.deliveryDate = this.deliveryDateBase
329 376 } else {
330   - it.orderDate = dateStr
  377 + it.deliveryDate = dateStr
331 378 }
332 379 this.$set(this.items, idx, it)
333 380 },
... ... @@ -500,8 +547,46 @@ export default {
500 547
501 548 .value {
502 549 flex: 1;
503   - text-align: right;
  550 + // text-align: right;
504 551 color: rgba(0, 0, 0, 0.9);
505 552 font-size: 28rpx;
506 553 }
  554 + .value-spec {
  555 + height: 48rpx;
  556 + display: flex;
  557 + align-items: center;
  558 + color: #000000;
  559 + // justify-content: end;
  560 + &_box {
  561 + position: relative;
  562 + width: 60rpx;
  563 + height: 48rpx;
  564 +
  565 + &_1 {
  566 + font-size: 16rpx;
  567 + position: absolute;
  568 + top: -10rpx;
  569 + left: 0;
  570 + }
  571 +
  572 + &_2 {
  573 + font-size: 16rpx;
  574 + position: absolute;
  575 + bottom: -10rpx;
  576 + left: 0;
  577 + }
  578 + }
  579 +
  580 + &_val {
  581 + font-size: 28rpx;
  582 +
  583 + &.p12 {
  584 + padding-right: 12rpx;
  585 + }
  586 + }
  587 + }
  588 + .row-spec {
  589 + height: 60rpx;
  590 + align-items: center;
  591 + }
507 592 </style>
... ...
... ... @@ -14,9 +14,10 @@
14 14 </template>
15 15 </uni-list-item>
16 16
17   - <uni-list-item title="区域">
18   - <template v-slot:footer>
19   - <uni-easyinput v-model="form.region" placeholder="请输入区域" :inputBorder="false" />
  17 + <uni-list-item class="select-item" :class="form.region ? 'is-filled' : 'is-empty'" clickable
  18 + @click="openSheet('region')" :rightText="displayLabel('regionName')" showArrow>
  19 + <template v-slot:body>
  20 + <view class="item-title"><text>区域</text></view>
20 21 </template>
21 22 </uni-list-item>
22 23 <uni-list-item title="客户简称">
... ... @@ -176,9 +177,9 @@
176 177 <uni-easyinput v-model="form.majorCustomers" placeholder="请输入主要客户" :inputBorder="false" />
177 178 </template>
178 179 </uni-list-item>
179   - <uni-list-item title="主营项目">
  180 + <uni-list-item class="mgb10" title="主营项目">
180 181 <template v-slot:footer>
181   - <uni-easyinput v-model="form.mainProjects" placeholder="请输入主营项目" :inputBorder="false" />
  182 + <uni-easyinput type="textarea" v-model="form.mainProjects" placeholder="请输入主营项目" :inputBorder="false" />
182 183 </template>
183 184 </uni-list-item>
184 185 <uni-list-item title="从事行业">
... ... @@ -316,7 +317,7 @@
316 317 <script>
317 318 import SingleSelectSheet from '@/components/single-select/index.vue'
318 319 import RelateSelectSheet from '@/components/relate-select/index.vue'
319   -import { generateCreditCode, getAllUser, getDeptUser, createApi } from '@/api/credit_manage.js'
  320 +import { generateCreditCode, getAllUser, getDeptUser, createApi, getArea } from '@/api/credit_manage.js'
320 321 import { getDicByCodeApi } from '@/api/base.js'
321 322 import CorePersonnel from './corePersonnel.vue'
322 323
... ... @@ -328,6 +329,7 @@ export default {
328 329 form: {
329 330 serialNumber: '',
330 331 region: '',
  332 + regionName: '',
331 333 customerShortName: '',
332 334 enterpriseType: '',
333 335 enterpriseTypeName: '',
... ... @@ -381,6 +383,7 @@ export default {
381 383 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
382 384 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
383 385 enterpriseTypeOptions: [],
  386 + regionOptions: [],
384 387 categoryOptions: [],
385 388 companyCategoryOptions: [],
386 389 investigatorOptions: [],
... ... @@ -389,6 +392,7 @@ export default {
389 392 },
390 393 created() {
391 394 this.loadSerialNumber()
  395 + this.loadRegionOptions()
392 396 this.loadEnterpriseTypeOptions()
393 397 this.loadCategoryOptions()
394 398 this.loadCompanyCategoryOptions()
... ... @@ -408,6 +412,7 @@ export default {
408 412 displayLabel(field) {
409 413 const m = this.form
410 414 const map = {
  415 + regionName: '请选择区域',
411 416 enterpriseTypeName: '请选择企业类型',
412 417 suggestedCategoryName: '请选择建议客户分类',
413 418 }
... ... @@ -420,6 +425,9 @@ export default {
420 425 const match = (options || []).find(o => String(o.label) === String(current) || String(o.value) === String(current))
421 426 this.sheet = { ...this.sheet, visible: true, title, options, field, value: match ? match.value : '' }
422 427 }
  428 + if (field === 'region') {
  429 + setSheet('区域', this.regionOptions)
  430 + } else
423 431 if (field === 'enterpriseType') {
424 432 setSheet('企业类型', this.enterpriseTypeOptions)
425 433 } else if (field === 'suggestedCategory') {
... ... @@ -490,6 +498,15 @@ export default {
490 498 this.enterpriseTypeOptions = []
491 499 }
492 500 },
  501 + async loadRegionOptions() {
  502 + try {
  503 + const res = await getArea()
  504 + const list = res.data || []
  505 + this.regionOptions = (list || []).map(it => ({ label: it.name || '', value: it.id || '' }))
  506 + } catch (e) {
  507 + this.regionOptions = []
  508 + }
  509 + },
493 510 async loadCategoryOptions() {
494 511 try {
495 512 const res = await getDicByCodeApi('CUSTOMER_CATEGORY')
... ... @@ -552,13 +569,14 @@ export default {
552 569 })
553 570 console.log('onSubmit__payload_2', payload);
554 571 delete payload.enterpriseTypeName
  572 + delete payload.regionName
555 573 delete payload.suggestedCategoryName
556 574 delete payload.companyIdName
557 575 delete payload.investigatorName
558 576 try {
559 577 await createApi(payload)
560 578 uni.showToast({ title: '提交成功', icon: 'success' })
561   - setTimeout(() => uni.navigateBack(), 600)
  579 + setTimeout(() => { uni.redirectTo({ url: '/pages/credit_manage/index' }) }, 300)
562 580 } catch (e) {
563 581 uni.showToast({ title: (e && e.msg) || '提交失败', icon: 'none' })
564 582 }
... ... @@ -618,7 +636,6 @@ export default {
618 636
619 637 &__container {
620 638 padding: 32rpx;
621   - align-items: center;
622 639
623 640 .uni-easyinput {
624 641
... ... @@ -743,4 +760,4 @@ export default {
743 760 }
744 761 }
745 762 }
746   -</style>
\ No newline at end of file
  763 +</style>
... ...
... ... @@ -13,9 +13,10 @@
13 13 </template>
14 14 </uni-list-item>
15 15
16   - <uni-list-item title="区域">
17   - <template v-slot:footer>
18   - <uni-easyinput v-model="form.region" placeholder="请输入区域" :inputBorder="false" />
  16 + <uni-list-item class="select-item" :class="form.region ? 'is-filled' : 'is-empty'" clickable
  17 + @click="openSheet('region')" :rightText="displayLabel('regionName')" showArrow>
  18 + <template v-slot:body>
  19 + <view class="item-title"><text>区域</text></view>
19 20 </template>
20 21 </uni-list-item>
21 22 <uni-list-item title="客户简称">
... ... @@ -175,9 +176,9 @@
175 176 <uni-easyinput v-model="form.majorCustomers" placeholder="请输入主要客户" :inputBorder="false" />
176 177 </template>
177 178 </uni-list-item>
178   - <uni-list-item title="主营项目">
  179 + <uni-list-item class="mgb10" title="主营项目">
179 180 <template v-slot:footer>
180   - <uni-easyinput v-model="form.mainProjects" placeholder="请输入主营项目" :inputBorder="false" />
  181 + <uni-easyinput type="textarea" v-model="form.mainProjects" placeholder="请输入主营项目" :inputBorder="false" />
181 182 </template>
182 183 </uni-list-item>
183 184 <uni-list-item title="从事行业">
... ... @@ -314,7 +315,7 @@
314 315 <script>
315 316 import SingleSelectSheet from '@/components/single-select/index.vue'
316 317 import RelateSelectSheet from '@/components/relate-select/index.vue'
317   -import { getDetailApi, updateApi, getAllUser } from '@/api/credit_manage.js'
  318 +import { getDetailApi, updateApi, getAllUser, getArea } from '@/api/credit_manage.js'
318 319 import { getDicByCodeApi } from '@/api/base.js'
319 320 import CorePersonnel from './corePersonnel.vue'
320 321
... ... @@ -328,6 +329,7 @@ export default {
328 329 id: '',
329 330 serialNumber: '',
330 331 region: '',
  332 + regionName: '',
331 333 customerShortName: '',
332 334 enterpriseType: '',
333 335 enterpriseTypeName: '',
... ... @@ -383,6 +385,7 @@ export default {
383 385 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
384 386 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
385 387 enterpriseTypeOptions: [],
  388 + regionOptions: [],
386 389 categoryOptions: [],
387 390 investigatorOptions: [],
388 391 genderOptions: []
... ... @@ -393,6 +396,7 @@ export default {
393 396 if (this.id) this.loadDetail(this.id)
394 397 },
395 398 created() {
  399 + this.loadRegionOptions()
396 400 this.loadEnterpriseTypeOptions()
397 401 this.loadCategoryOptions()
398 402 this.loadInvestigatorOptions()
... ... @@ -400,6 +404,7 @@ export default {
400 404 },
401 405 watch: {
402 406 enterpriseTypeOptions() { this.refreshLabelFields() },
  407 + regionOptions() { this.refreshLabelFields() },
403 408 categoryOptions() { this.refreshLabelFields() },
404 409 investigatorOptions() { this.refreshLabelFields() }
405 410 },
... ... @@ -425,6 +430,7 @@ export default {
425 430 displayLabel(field) {
426 431 const m = this.form
427 432 const map = {
  433 + regionName: '请选择区域',
428 434 enterpriseTypeName: '请选择企业类型',
429 435 suggestedCategoryName: '请选择建议客户分类',
430 436 }
... ... @@ -433,9 +439,11 @@ export default {
433 439 },
434 440 refreshLabelFields() {
435 441 const et = this.enterpriseTypeOptions.find(o => String(o.value) === String(this.form.enterpriseType))
  442 + const rn = this.regionOptions.find(o => String(o.value) === String(this.form.region))
436 443 const ct = this.categoryOptions.find(o => String(o.value) === String(this.form.suggestedCategory))
437 444 const iu = this.investigatorOptions.find(o => String(o.value) === String(this.form.investigator))
438 445 this.form.enterpriseTypeName = et ? (et.label || '') : this.form.enterpriseTypeName
  446 + this.form.regionName = rn ? (rn.label || '') : this.form.regionName
439 447 this.form.suggestedCategoryName = ct ? (ct.label || '') : this.form.suggestedCategoryName
440 448 this.form.investigatorName = iu ? (iu.label || '') : this.form.investigatorName
441 449 },
... ... @@ -445,6 +453,9 @@ export default {
445 453 const match = (options || []).find(o => String(o.label) === String(current) || String(o.value) === String(current))
446 454 this.sheet = { ...this.sheet, visible: true, title, options, field, value: match ? match.value : '' }
447 455 }
  456 + if (field === 'region') {
  457 + setSheet('区域', this.regionOptions)
  458 + } else
448 459 if (field === 'enterpriseType') {
449 460 setSheet('企业类型', this.enterpriseTypeOptions)
450 461 } else if (field === 'suggestedCategory') {
... ... @@ -515,6 +526,15 @@ export default {
515 526 this.enterpriseTypeOptions = []
516 527 }
517 528 },
  529 + async loadRegionOptions() {
  530 + try {
  531 + const res = await getArea()
  532 + const list = res.data || []
  533 + this.regionOptions = (list || []).map(it => ({ label: it.name || '', value: it.id || '' }))
  534 + } catch (e) {
  535 + this.regionOptions = []
  536 + }
  537 + },
518 538 async loadCategoryOptions() {
519 539 try {
520 540 const res = await getDicByCodeApi('CUSTOMER_CATEGORY')
... ... @@ -557,6 +577,7 @@ export default {
557 577 delete it.sexName
558 578 })
559 579 delete payload.enterpriseTypeName
  580 + delete payload.regionName
560 581 delete payload.suggestedCategoryName
561 582 delete payload.companyIdName
562 583 delete payload.investigatorName
... ... @@ -624,7 +645,6 @@ export default {
624 645
625 646 &__container {
626 647 padding: 32rpx;
627   - align-items: center;
628 648
629 649 .uni-easyinput {
630 650
... ... @@ -738,4 +758,4 @@ export default {
738 758 }
739 759 }
740 760 }
741   -</style>
\ No newline at end of file
  761 +</style>
... ...
... ... @@ -6,7 +6,7 @@
6 6 <text class="row company">{{ form.companyName }}</text>
7 7 <view :class="['status', `status_${form.status}`]" />
8 8 <view class="row"><text class="label">编号</text><text class="value">{{ form.serialNumber }}</text></view>
9   - <view class="row"><text class="label">区域</text><text class="value">{{ form.region }}</text></view>
  9 + <view class="row"><text class="label">区域</text><text class="value">{{ form.regionName }}</text></view>
10 10 <view class="row"><text class="label">客户简称</text><text class="value">{{ form.customerShortName }}</text>
11 11 </view>
12 12 <view class="row"><text class="label">企业类型</text><text class="value">{{ getDicName('ENTERPRISE_TYPE',
... ... @@ -184,6 +184,7 @@ export default {
184 184 return {
185 185 form: {},
186 186 enterpriseTypeOptions: [],
  187 + regionOptions: [],
187 188 genderOptions: [],
188 189 categoryOptions: [],
189 190 historyList: [],
... ... @@ -192,7 +193,7 @@ export default {
192 193 { text: '审核详情', visible: true, variant: 'outline', event: 'auditDetail' },
193 194 { text: '审核', visible: true, variant: 'primary', event: 'audit' },
194 195 { text: '申请变更', visible: true, variant: 'outline', event: 'changeApply' },
195   - { text: '取消', visible: true, variant: 'outline', event: 'cancel', style: { color: 'rgba(0,0,0,0.9)', border: '1px solid #DCDCDC' } },
  196 + { text: '取消', visible: true, vxrariant: 'outline', event: 'cancel', style: { color: 'rgba(0,0,0,0.9)', border: '1px solid #DCDCDC' } },
196 197 ],
197 198 }
198 199 },
... ... @@ -210,15 +211,16 @@ export default {
210 211 displayButtons() {
211 212 const f = this.statusFlags
212 213 return [
213   - { ...this.buttons[0], visible: f.isRefuse },
214   - { ...this.buttons[1], visible: true },
215   - { ...this.buttons[2], visible: f.isAudit && f.canExamine },
216   - { ...this.buttons[3], visible: f.isPass },
217   - { ...this.buttons[4], visible: f.isRefuse },
  214 + { ...this.buttons[0], visible: f.isRefuse && this.$auth.hasPermi('customer-credit-manage:customer-credit-plan:modify') },
  215 + { ...this.buttons[1], visible: this.$auth.hasPermi('customer-credit-manage:customer-credit-plan:review') },
  216 + { ...this.buttons[2], visible: f.isAudit && f.canExamine && this.$auth.hasPermi('customer-credit-manage:customer-credit-plan:approve') },
  217 + { ...this.buttons[3], visible: f.isPass && this.$auth.hasPermi('customer-credit-manage:customer-credit-plan:change') },
  218 + { ...this.buttons[4], visible: f.isRefuse && this.$auth.hasPermi('customer-credit-manage:customer-credit-plan:close') },
218 219 ]
219 220 }
220 221 },
221 222 created() {
  223 + this.loadRegionOptions()
222 224 this.loadEnterpriseTypeOptions()
223 225 this.loadGenderOptions()
224 226 this.loadCategoryOptions()
... ... @@ -248,6 +250,15 @@ export default {
248 250 this.enterpriseTypeOptions = []
249 251 }
250 252 },
  253 + async loadRegionOptions() {
  254 + try {
  255 + const res = await getDicByCodeApi('CREDIT_ZONE')
  256 + const list = res.data || []
  257 + this.regionOptions = Array.isArray(list) ? list : []
  258 + } catch (e) {
  259 + this.regionOptions = []
  260 + }
  261 + },
251 262 async loadGenderOptions() {
252 263 try {
253 264 const res = await getDicByCodeApi('GENDER_TYPE')
... ... @@ -553,4 +564,4 @@ export default {
553 564 font-weight: 600;
554 565 }
555 566 }
556   -</style>
\ No newline at end of file
  567 +</style>
... ...
... ... @@ -6,7 +6,7 @@
6 6 cancelButton="none" bgColor="#F3F3F3" textColor="rgba(0,0,0,0.4)" @confirm="search"
7 7 @input="onSearchInput" />
8 8 <view class="tool-icons">
9   - <image class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
  9 + <image v-if="$auth.hasPermi('customer-credit-manage:customer-credit-plan:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
10 10 <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
11 11 </view>
12 12 </view>
... ... @@ -33,7 +33,7 @@
33 33 <text>企业类型</text><text>{{ getDicName('ENTERPRISE_TYPE', item.enterpriseType, dicOptions.ENTERPRISE_TYPE) || '-' }}</text>
34 34 </view>
35 35 <view class="info-row">
36   - <text>区域</text><text>{{ item.region || '-' }}</text>
  36 + <text>区域</text><text>{{ item.regionName || '-' }}</text>
37 37 </view>
38 38 <view class="info-row">
39 39 <text>客户分类</text><text
... ... @@ -122,7 +122,8 @@
122 122 dicOptions: {
123 123 CUSTOMER_CATEGORY: [],
124 124 AUDIT_STATUS: [],
125   - ENTERPRISE_TYPE: []
  125 + ENTERPRISE_TYPE: [],
  126 + CREDIT_ZONE: []
126 127 },
127 128 statusLocal: [],
128 129 categoryLocal: []
... ... @@ -267,11 +268,12 @@
267 268 })
268 269 },
269 270 loadAllDicData() {
270   - const dicCodes = ['CUSTOMER_CATEGORY', 'AUDIT_STATUS', 'ENTERPRISE_TYPE']
  271 + const dicCodes = ['CUSTOMER_CATEGORY', 'AUDIT_STATUS', 'ENTERPRISE_TYPE', 'CREDIT_ZONE']
271 272 return getDicByCodes(dicCodes).then(results => {
272 273 this.dicOptions.CUSTOMER_CATEGORY = results.CUSTOMER_CATEGORY.data || []
273 274 this.dicOptions.AUDIT_STATUS = results.AUDIT_STATUS.data || []
274 275 this.dicOptions.ENTERPRISE_TYPE = results.ENTERPRISE_TYPE.data || []
  276 + this.dicOptions.CREDIT_ZONE = results.CREDIT_ZONE.data || [];
275 277 this.categoryLocal = (this.dicOptions.CUSTOMER_CATEGORY || []).map(it => ({
276 278 value: it.code,
277 279 text: it.name
... ... @@ -284,7 +286,8 @@
284 286 this.dicOptions = {
285 287 CUSTOMER_CATEGORY: [],
286 288 AUDIT_STATUS: [],
287   - ENTERPRISE_TYPE: []
  289 + ENTERPRISE_TYPE: [],
  290 + CREDIT_ZONE: []
288 291 }
289 292 this.categoryLocal = []
290 293 this.statusLocal = []
... ...
... ... @@ -13,9 +13,10 @@
13 13 </template>
14 14 </uni-list-item>
15 15
16   - <uni-list-item title="区域">
17   - <template v-slot:footer>
18   - <uni-easyinput v-model="form.region" placeholder="请输入区域" :inputBorder="false" />
  16 + <uni-list-item class="select-item" :class="form.region ? 'is-filled' : 'is-empty'" clickable
  17 + @click="openSheet('region')" :rightText="displayLabel('regionName')" showArrow>
  18 + <template v-slot:body>
  19 + <view class="item-title"><text>区域</text></view>
19 20 </template>
20 21 </uni-list-item>
21 22 <uni-list-item title="客户简称">
... ... @@ -175,9 +176,9 @@
175 176 <uni-easyinput v-model="form.majorCustomers" placeholder="请输入主要客户" :inputBorder="false" />
176 177 </template>
177 178 </uni-list-item>
178   - <uni-list-item title="主营项目">
  179 + <uni-list-item class="mgb10" title="主营项目">
179 180 <template v-slot:footer>
180   - <uni-easyinput v-model="form.mainProjects" placeholder="请输入主营项目" :inputBorder="false" />
  181 + <uni-easyinput type="textarea" v-model="form.mainProjects" placeholder="请输入主营项目" :inputBorder="false" />
181 182 </template>
182 183 </uni-list-item>
183 184 <uni-list-item title="从事行业">
... ... @@ -314,7 +315,7 @@
314 315 <script>
315 316 import SingleSelectSheet from '@/components/single-select/index.vue'
316 317 import RelateSelectSheet from '@/components/relate-select/index.vue'
317   -import { getDetailApi, updateApi, getAllUser } from '@/api/credit_manage.js'
  318 +import { getDetailApi, updateApi, getAllUser, getArea } from '@/api/credit_manage.js'
318 319 import { getDicByCodeApi } from '@/api/base.js'
319 320 import CorePersonnel from './corePersonnel.vue'
320 321
... ... @@ -328,6 +329,7 @@ export default {
328 329 id: '',
329 330 serialNumber: '',
330 331 region: '',
  332 + regionName: '',
331 333 customerShortName: '',
332 334 enterpriseType: '',
333 335 enterpriseTypeName: '',
... ... @@ -383,6 +385,7 @@ export default {
383 385 sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
384 386 relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
385 387 enterpriseTypeOptions: [],
  388 + regionOptions: [],
386 389 categoryOptions: [],
387 390 investigatorOptions: [],
388 391 genderOptions: []
... ... @@ -393,6 +396,7 @@ export default {
393 396 if (this.id) this.loadDetail(this.id)
394 397 },
395 398 created() {
  399 + this.loadRegionOptions()
396 400 this.loadEnterpriseTypeOptions()
397 401 this.loadCategoryOptions()
398 402 this.loadInvestigatorOptions()
... ... @@ -400,6 +404,7 @@ export default {
400 404 },
401 405 watch: {
402 406 enterpriseTypeOptions() { this.refreshLabelFields() },
  407 + regionOptions() { this.refreshLabelFields() },
403 408 categoryOptions() { this.refreshLabelFields() },
404 409 investigatorOptions() { this.refreshLabelFields() }
405 410 },
... ... @@ -425,6 +430,7 @@ export default {
425 430 displayLabel(field) {
426 431 const m = this.form
427 432 const map = {
  433 + regionName: '请选择区域',
428 434 enterpriseTypeName: '请选择企业类型',
429 435 suggestedCategoryName: '请选择建议客户分类',
430 436 }
... ... @@ -433,9 +439,11 @@ export default {
433 439 },
434 440 refreshLabelFields() {
435 441 const et = this.enterpriseTypeOptions.find(o => String(o.value) === String(this.form.enterpriseType))
  442 + const rn = this.regionOptions.find(o => String(o.value) === String(this.form.region))
436 443 const ct = this.categoryOptions.find(o => String(o.value) === String(this.form.suggestedCategory))
437 444 const iu = this.investigatorOptions.find(o => String(o.value) === String(this.form.investigator))
438 445 this.form.enterpriseTypeName = et ? (et.label || '') : this.form.enterpriseTypeName
  446 + this.form.regionName = rn ? (rn.label || '') : this.form.regionName
439 447 this.form.suggestedCategoryName = ct ? (ct.label || '') : this.form.suggestedCategoryName
440 448 this.form.investigatorName = iu ? (iu.label || '') : this.form.investigatorName
441 449 },
... ... @@ -445,6 +453,9 @@ export default {
445 453 const match = (options || []).find(o => String(o.label) === String(current) || String(o.value) === String(current))
446 454 this.sheet = { ...this.sheet, visible: true, title, options, field, value: match ? match.value : '' }
447 455 }
  456 + if (field === 'region') {
  457 + setSheet('区域', this.regionOptions)
  458 + } else
448 459 if (field === 'enterpriseType') {
449 460 setSheet('企业类型', this.enterpriseTypeOptions)
450 461 } else if (field === 'suggestedCategory') {
... ... @@ -515,6 +526,15 @@ export default {
515 526 this.enterpriseTypeOptions = []
516 527 }
517 528 },
  529 + async loadRegionOptions() {
  530 + try {
  531 + const res = await getArea()
  532 + const list = res.data || []
  533 + this.regionOptions = (list || []).map(it => ({ label: it.name || '', value: it.id || '' }))
  534 + } catch (e) {
  535 + this.regionOptions = []
  536 + }
  537 + },
518 538 async loadCategoryOptions() {
519 539 try {
520 540 const res = await getDicByCodeApi('CUSTOMER_CATEGORY')
... ... @@ -557,6 +577,7 @@ export default {
557 577 delete it.sexName
558 578 })
559 579 delete payload.enterpriseTypeName
  580 + delete payload.regionName
560 581 delete payload.suggestedCategoryName
561 582 delete payload.companyIdName
562 583 delete payload.investigatorName
... ... @@ -625,7 +646,6 @@ export default {
625 646
626 647 &__container {
627 648 padding: 32rpx;
628   - align-items: center;
629 649
630 650 .uni-easyinput {
631 651
... ... @@ -739,4 +759,4 @@ export default {
739 759 }
740 760 }
741 761 }
742   -</style>
\ No newline at end of file
  762 +</style>
... ...
... ... @@ -3,7 +3,7 @@
3 3 <view class="section">
4 4 <text class="row company">{{ form.companyName }}</text>
5 5 <view class="row"><text class="label">编号</text><text class="value">{{ form.serialNumber }}</text></view>
6   - <view class="row"><text class="label">区域</text><text class="value">{{ form.region }}</text></view>
  6 + <view class="row"><text class="label">区域</text><text class="value">{{ form.regionName }}</text></view>
7 7 <view class="row"><text class="label">客户简称</text><text class="value">{{ form.customerShortName }}</text>
8 8 </view>
9 9 <view class="row"><text class="label">企业类型</text><text class="value">{{ getDicName('ENTERPRISE_TYPE',
... ... @@ -188,12 +188,14 @@ export default {
188 188 return {
189 189 form: {},
190 190 enterpriseTypeOptions: [],
  191 + regionOptions: [],
191 192 genderOptions: [],
192 193 categoryOptions: [],
193 194 historyList: []
194 195 }
195 196 },
196 197 created() {
  198 + this.loadRegionOptions()
197 199 this.loadEnterpriseTypeOptions()
198 200 this.loadGenderOptions()
199 201 this.loadCategoryOptions()
... ... @@ -228,6 +230,15 @@ export default {
228 230 this.enterpriseTypeOptions = []
229 231 }
230 232 },
  233 + async loadRegionOptions() {
  234 + try {
  235 + const res = await getDicByCodeApi('CREDIT_ZONE')
  236 + const list = res.data || []
  237 + this.regionOptions = Array.isArray(list) ? list : []
  238 + } catch (e) {
  239 + this.regionOptions = []
  240 + }
  241 + },
231 242 async loadGenderOptions() {
232 243 try {
233 244 const res = await getDicByCodeApi('GENDER_TYPE')
... ... @@ -427,4 +438,4 @@ export default {
427 438 .mgb10 {
428 439 margin-bottom: 20rpx;
429 440 }
430   -</style>
\ No newline at end of file
  441 +</style>
... ...
... ... @@ -19,8 +19,8 @@
19 19 </uni-list-item>
20 20
21 21 <!-- 客户名称 关联页选择 -->
22   - <uni-list-item class="select-item" :class="form.customerId ? 'is-filled' : 'is-empty'" clickable @click="openRelate('customerId')" :rightText="form.customerIdName || '请选择客户名称'"
23   - showArrow>
  22 + <uni-list-item class="select-item" :class="form.customerId ? 'is-filled' : 'is-empty'" clickable
  23 + @click="openRelate('customerId')" :rightText="form.customerIdName || '请选择客户名称'" showArrow>
24 24 <template v-slot:body>
25 25 <view class="item-title"><text class="required">*</text><text>客户名称</text></view>
26 26 </template>
... ... @@ -98,7 +98,8 @@
98 98 </uni-list-item>
99 99 <!-- 责任人 关联页选择 -->
100 100 <uni-list-item class="select-item" :class="form.chargeUserIdName ? 'is-filled' : 'is-empty'" title="责任人"
101   - clickable @click="openRelate('chargeUserId')" :rightText="form.chargeUserIdName || '请选择责任人'" showArrow />
  101 + clickable @click="openRelate('chargeUserId')" :rightText="form.chargeUserIdName || '请选择责任人'"
  102 + showArrow />
102 103 </uni-list>
103 104
104 105 </scroll-view>
... ... @@ -114,435 +115,441 @@
114 115 <!-- 关联选择弹框:客户名称、责任人 -->
115 116 <RelateSelectSheet :visible.sync="relate.visible" :title="relate.title" :source="relate.source"
116 117 :display-fields="relate.display" :multiple="relate.multiple" :row-key="relate.rowKey"
117   - :selectedKeys.sync="relate.selectedKeys" :source-extra="{ source: 'CUSTOMER_DEVELOP' }" @confirm="onRelateConfirm" />
  118 + :selectedKeys.sync="relate.selectedKeys" :source-extra="{ source: 'CUSTOMER_DEVELOP' }"
  119 + @confirm="onRelateConfirm" />
118 120 </view>
119 121 </template>
120 122
121 123 <script>
122   - import SingleSelectSheet from '@/components/single-select/index.vue'
123   - import RelateSelectSheet from '@/components/relate-select/index.vue'
124   - import constant from '@/utils/constant'
125   - import storage from '@/utils/storage'
126   - import {
127   - createApi,
128   - officeQueryApi,
129   - productVarietyQueryApi,
130   - workshopQueryApi
131   - } from '@/api/devManage.js'
132   - import {
133   - getDicByCodeApi
134   - } from '@/api/base.js'
  124 +import SingleSelectSheet from '@/components/single-select/index.vue'
  125 +import RelateSelectSheet from '@/components/relate-select/index.vue'
  126 +import constant from '@/utils/constant'
  127 +import storage from '@/utils/storage'
  128 +import {
  129 + createApi,
  130 + officeQueryApi,
  131 + productVarietyQueryApi,
  132 + workshopQueryApi
  133 +} from '@/api/devManage.js'
  134 +import {
  135 + getDicByCodeApi
  136 +} from '@/api/base.js'
135 137
136   - export default {
137   - name: 'DevManageAdd',
138   - components: {
139   - SingleSelectSheet,
140   - RelateSelectSheet
141   - },
142   - data() {
143   - return {
144   - form: {
145   - workshopIdName: '',
146   - workshopId: '',
147   - officeIdName: '',
148   - officeId: '',
149   - customerIdName: '',
150   - customerId: '',
151   - customerType: '',
152   - customerTypeName: '',
153   - chargeUserId: '',
154   - chargeUserIdName: '',
155   - productVarietyId: '',
156   - productVarietyIdName: '',
157   - monthlyUsage: '',
158   - targetQuantity: '',
159   - industry: '',
160   - mark: '',
161   - thickness: '',
162   - width: '',
163   - materialRequire: '',
164   - qualityRequire: '',
165   - peer: '',
166   - pricingMode: '',
167   - settleDays: '',
168   - },
169   - sheet: {
170   - visible: false,
171   - title: '请选择',
172   - field: '',
173   - options: [],
174   - value: ''
175   - },
176   - relate: {
177   - visible: false,
178   - title: '选择',
179   - source: '',
180   - display: [],
181   - multiple: false,
182   - rowKey: 'id',
183   - selectedKeys: []
184   - },
185   - officeOptions: [],
186   - customerTypeOptions: [],
187   - productVarietyIdOptions: []
188   - }
189   - },
190   - created() {
191   - // 责任人默认使用当前用户昵称/用户名
192   - const user = storage.get(constant.name);
193   - const userId = storage.get(constant.id);
194   - this.form.chargeUserIdName = user || '';
195   - this.form.chargeUserId = userId || '';
196   - // 科办
197   - this.loadOfficeOptions()
198   - // 客户类型
199   - this.loadCustomerTypeOptions()
200   - // 生产厂
201   - this.loadproductVarietyIdOptions()
202   - },
203   - methods: {
204   - // 校验必填项:生产厂、科办、客户名称、客户类型、产品品种
205   - validateRequired() {
206   - const checks = [{
207   - key: 'workshopId',
208   - label: '生产厂'
209   - },
210   - {
211   - key: 'officeId',
212   - label: '科办'
213   - },
214   - {
215   - key: 'customerId',
216   - label: '客户名称'
217   - },
218   - {
219   - key: 'customerType',
220   - label: '客户类型'
221   - },
222   - {
223   - key: 'productVarietyId',
224   - label: '产品品种'
225   - }
226   - ]
227   - for (const it of checks) {
228   - const val = this.form[it.key]
229   - if (val === undefined || val === null || String(val).trim() === '') {
230   - uni.showToast({
231   - title: `请先选择${it.label}`,
232   - icon: 'none'
233   - })
234   - return false
235   - }
236   - }
237   - return true
  138 +export default {
  139 + name: 'DevManageAdd',
  140 + components: {
  141 + SingleSelectSheet,
  142 + RelateSelectSheet
  143 + },
  144 + data() {
  145 + return {
  146 + form: {
  147 + workshopIdName: '',
  148 + workshopId: '',
  149 + officeIdName: '',
  150 + officeId: '',
  151 + customerIdName: '',
  152 + customerId: '',
  153 + customerType: '',
  154 + customerTypeName: '',
  155 + chargeUserId: '',
  156 + chargeUserIdName: '',
  157 + productVarietyId: '',
  158 + productVarietyIdName: '',
  159 + monthlyUsage: '',
  160 + targetQuantity: '',
  161 + industry: '',
  162 + mark: '',
  163 + thickness: '',
  164 + width: '',
  165 + materialRequire: '',
  166 + qualityRequire: '',
  167 + peer: '',
  168 + pricingMode: '',
  169 + settleDays: '',
238 170 },
239   - async loadOfficeOptions() {
240   - try {
241   - const res = await officeQueryApi({
242   - pageIndex: 1,
243   - pageSize: 9999
244   - })
245   - const _data = res.data || {}
246   - const list = _data.datas || []
247   - this.officeOptions = (list || []).map(it => ({
248   - label: it.name || it.text || it.officeName || it.label,
249   - value: it.id || it.code || it.value
250   - }))
251   - } catch (e) {
252   - this.officeOptions = []
253   - }
  171 + sheet: {
  172 + visible: false,
  173 + title: '请选择',
  174 + field: '',
  175 + options: [],
  176 + value: ''
254 177 },
255   - displayLabel(field) {
256   - const m = this.form
257   - const map = {
258   - workshopIdName: '请选择生产厂',
259   - officeIdName: '请选择科办',
260   - customerTypeName: '请选择客户类型',
261   - productVarietyIdName: '请选择产品品种'
262   - }
263   - const val = m[field]
264   - return val ? String(val) : map[field]
  178 + relate: {
  179 + visible: false,
  180 + title: '选择',
  181 + source: '',
  182 + display: [],
  183 + multiple: false,
  184 + rowKey: 'id',
  185 + selectedKeys: []
265 186 },
266   - async openSheet(field) {
267   - const setSheet = (title, options) => {
268   - const current = this.form[field]
269   - const match = (options || []).find(o => String(o.label) === String(current) || String(o.value) === String(current))
270   - this.sheet = {
271   - ...this.sheet,
272   - visible: true,
273   - title,
274   - options,
275   - field,
276   - value: match ? match.value : ''
277   - }
278   - }
279   - if (field === 'workshopId') {
280   - const res = await workshopQueryApi({ pageIndex: 1, pageSize: 9999 })
281   - const _data = res.data || {}
282   - const list = _data.datas || (Array.isArray(_data) ? _data : [])
283   - const opts = (list || []).map(it => ({
284   - label: it.name ,
285   - value: it.id
286   - }))
287   - setSheet('生产厂', opts)
288   - } else if (field === 'officeId') {
289   - setSheet('科办', this.officeOptions)
290   - } else if (field === 'customerType') {
291   - const opts = this.customerTypeOptions || [];
292   - setSheet('客户类型', opts)
293   - } else if (field === 'productVarietyId') {
294   - const opts = this.productVarietyIdOptions;
295   - setSheet('产品品种', opts)
296   - }
297   - },
298   - onSheetConfirm({
299   - value,
300   - label
301   - }) {
302   - const field = this.sheet.field
303   - if (!field) return
304   - this.form[field] = value || '';
305   - this.form[field + 'Name'] = label || ''
306   - this.sheet.visible = false
307   - },
308   - openRelate(fieldKey) {
309   - let config = {};
310   - switch(fieldKey) {
311   - case 'customerId':
312   - config = {
313   - title: '客户名称',
314   - source: 'customer',
315   - rowKey: 'id',
316   - multiple: false,
317   - display: [{
318   - label: '名称',
319   - field: 'name'
320   - },
321   - {
322   - label: '编号',
323   - field: 'code'
324   - },
325   - {
326   - label: '状态',
327   - field: 'available',
328   - format: v => (v ? '启用' : '停用')
329   - }
330   - ]
331   - }
332   - break
333   - case 'chargeUserId':
334   - config = {
335   - title: '责任人',
336   - source: 'user',
337   - rowKey: 'id',
338   - multiple: false,
339   - display: [{
340   - label: '姓名',
341   - field: 'name'
342   - },
343   - {
344   - label: '编号',
345   - field: 'code'
346   - },
347   - {
348   - label: '状态',
349   - field: 'available',
350   - format: v => (v ? '启用' : '停用')
351   - }
352   - ]};
353   - break
354   - }
355   - const selectedKeys = this.form[fieldKey] ? [this.form[fieldKey]] : [];
356   - // 逐一赋值,避免整体替换对象导致子组件 prop 更新不及时
357   - this.sheet.visible = false
358   - this.relate.title = config.title
359   - this.relate.source = config.source
360   - this.relate.display = config.display
361   - this.relate.multiple = config.multiple
362   - this.relate.rowKey = config.rowKey
363   - this.relate.selectedKeys = selectedKeys
364   - this.relate.fieldKey = fieldKey;
365   - // 最后再打开弹框,确保选中键已传入
366   - this.$nextTick(() => {
367   - this.relate.visible = true
368   - })
  187 + officeOptions: [],
  188 + customerTypeOptions: [],
  189 + productVarietyIdOptions: []
  190 + }
  191 + },
  192 + created() {
  193 + // 责任人默认使用当前用户昵称/用户名
  194 + const user = storage.get(constant.name);
  195 + const userId = storage.get(constant.id);
  196 + this.form.chargeUserIdName = user || '';
  197 + this.form.chargeUserId = userId || '';
  198 + // 科办
  199 + this.loadOfficeOptions()
  200 + // 客户类型
  201 + this.loadCustomerTypeOptions()
  202 + // 生产厂
  203 + this.loadproductVarietyIdOptions()
  204 + },
  205 + methods: {
  206 + // 校验必填项:生产厂、科办、客户名称、客户类型、产品品种
  207 + validateRequired() {
  208 + const checks = [{
  209 + key: 'workshopId',
  210 + label: '生产厂'
369 211 },
370   - onRelateConfirm({
371   - items
372   - }) {
373   - console.log('onRelateConfirm__item', items)
374   - const _fieldKey = this.relate.fieldKey;
375   - console.log('onRelateConfirm__fieldKey', _fieldKey)
376   - const first = (items && items.length > 0) ? items[0] : null
377   - // 若无选中项,确认时清空之前的值
378   - this.form[_fieldKey] = first.id || '';
379   - this.form[_fieldKey + 'Name'] = first.name || '';
  212 + {
  213 + key: 'officeId',
  214 + label: '科办'
380 215 },
381   - async loadCustomerTypeOptions() {
382   - try {
383   - const res = await getDicByCodeApi('ENTERPRISE_TYPE');
384   - const list = res.data || [];
385   - this.customerTypeOptions = (list || []).map(it => ({
386   - label: it.name || '',
387   - value: it.code || ''
388   - }))
389   - } catch (e) {
390   - this.customerTypeOptions = []
391   - }
  216 + {
  217 + key: 'customerId',
  218 + label: '客户名称'
392 219 },
393   -
394   - async loadproductVarietyIdOptions() {
395   - try {
396   - const res = await productVarietyQueryApi({ pageIndex: 1, pageSize: 9999 })
397   - const _data = res.data || {}
398   - const list = _data.datas || (Array.isArray(_data) ? _data : [])
399   - this.productVarietyIdOptions = (list || []).map(it => ({
400   - label: it.name || it.text || it.label,
401   - value: it.id || it.code || it.value
402   - }))
403   - } catch (e) {
404   - this.productVarietyIdOptions = []
405   - }
  220 + {
  221 + key: 'customerType',
  222 + label: '客户类型'
406 223 },
407   - async onSubmit() {
408   - // 必填校验
409   - if (!this.validateRequired()) return
410   - const payload = {
411   - ...this.form
412   - }
413   - delete payload.workshopIdName
414   - delete payload.officeIdName
415   - delete payload.customerTypeName
416   - delete payload.customerIdName
417   - delete payload.productVarietyIdName
418   - delete payload.chargeUserIdName
419   - createApi(payload).then(res => {
420   - uni.showToast({
421   - title: '提交成功',
422   - icon: 'success'
423   - })
424   - setTimeout(() => uni.navigateBack(), 600)
425   - }).catch(e => {
426   - console.log('createApi__e', e)
  224 + {
  225 + key: 'productVarietyId',
  226 + label: '产品品种'
  227 + }
  228 + ]
  229 + for (const it of checks) {
  230 + const val = this.form[it.key]
  231 + if (val === undefined || val === null || String(val).trim() === '') {
427 232 uni.showToast({
428   - title: e.msg || '提交失败',
  233 + title: `请先选择${it.label}`,
429 234 icon: 'none'
430 235 })
  236 + return false
  237 + }
  238 + }
  239 + return true
  240 + },
  241 + async loadOfficeOptions() {
  242 + try {
  243 + const res = await officeQueryApi({
  244 + pageIndex: 1,
  245 + pageSize: 9999
431 246 })
  247 + const _data = res.data || {}
  248 + const list = _data.datas || []
  249 + this.officeOptions = (list || []).map(it => ({
  250 + label: it.name || it.text || it.officeName || it.label,
  251 + value: it.id || it.code || it.value
  252 + }))
  253 + } catch (e) {
  254 + this.officeOptions = []
  255 + }
  256 + },
  257 + displayLabel(field) {
  258 + const m = this.form
  259 + const map = {
  260 + workshopIdName: '请选择生产厂',
  261 + officeIdName: '请选择科办',
  262 + customerTypeName: '请选择客户类型',
  263 + productVarietyIdName: '请选择产品品种'
  264 + }
  265 + const val = m[field]
  266 + return val ? String(val) : map[field]
  267 + },
  268 + async openSheet(field) {
  269 + const setSheet = (title, options) => {
  270 + const current = this.form[field]
  271 + const match = (options || []).find(o => String(o.label) === String(current) || String(o.value) === String(current))
  272 + this.sheet = {
  273 + ...this.sheet,
  274 + visible: true,
  275 + title,
  276 + options,
  277 + field,
  278 + value: match ? match.value : ''
  279 + }
  280 + }
  281 + if (field === 'workshopId') {
  282 + const res = await workshopQueryApi({ pageIndex: 1, pageSize: 9999 })
  283 + const _data = res.data || {}
  284 + const list = _data.datas || (Array.isArray(_data) ? _data : [])
  285 + const opts = (list || []).map(it => ({
  286 + label: it.name,
  287 + value: it.id
  288 + }))
  289 + setSheet('生产厂', opts)
  290 + } else if (field === 'officeId') {
  291 + setSheet('科办', this.officeOptions)
  292 + } else if (field === 'customerType') {
  293 + const opts = this.customerTypeOptions || [];
  294 + setSheet('客户类型', opts)
  295 + } else if (field === 'productVarietyId') {
  296 + const opts = this.productVarietyIdOptions;
  297 + setSheet('产品品种', opts)
  298 + }
  299 + },
  300 + onSheetConfirm({
  301 + value,
  302 + label
  303 + }) {
  304 + const field = this.sheet.field
  305 + if (!field) return
  306 + this.form[field] = value || '';
  307 + this.form[field + 'Name'] = label || ''
  308 + this.sheet.visible = false
  309 + },
  310 + openRelate(fieldKey) {
  311 + let config = {};
  312 + switch (fieldKey) {
  313 + case 'customerId':
  314 + config = {
  315 + title: '客户名称',
  316 + source: 'customer',
  317 + rowKey: 'id',
  318 + multiple: false,
  319 + display: [{
  320 + label: '名称',
  321 + field: 'name'
  322 + },
  323 + {
  324 + label: '编号',
  325 + field: 'code'
  326 + },
  327 + {
  328 + label: '状态',
  329 + field: 'available',
  330 + format: v => (v ? '启用' : '停用')
  331 + }
  332 + ]
  333 + }
  334 + break
  335 + case 'chargeUserId':
  336 + config = {
  337 + title: '责任人',
  338 + source: 'user',
  339 + rowKey: 'id',
  340 + multiple: false,
  341 + display: [{
  342 + label: '姓名',
  343 + field: 'name'
  344 + },
  345 + {
  346 + label: '编号',
  347 + field: 'code'
  348 + },
  349 + {
  350 + label: '状态',
  351 + field: 'available',
  352 + format: v => (v ? '启用' : '停用')
  353 + }
  354 + ]
  355 + };
  356 + break
  357 + }
  358 + const selectedKeys = this.form[fieldKey] ? [this.form[fieldKey]] : [];
  359 + // 逐一赋值,避免整体替换对象导致子组件 prop 更新不及时
  360 + this.sheet.visible = false
  361 + this.relate.title = config.title
  362 + this.relate.source = config.source
  363 + this.relate.display = config.display
  364 + this.relate.multiple = config.multiple
  365 + this.relate.rowKey = config.rowKey
  366 + this.relate.selectedKeys = selectedKeys
  367 + this.relate.fieldKey = fieldKey;
  368 + // 最后再打开弹框,确保选中键已传入
  369 + this.$nextTick(() => {
  370 + this.relate.visible = true
  371 + })
  372 + },
  373 + onRelateConfirm({
  374 + items
  375 + }) {
  376 + console.log('onRelateConfirm__item', items)
  377 + const _fieldKey = this.relate.fieldKey;
  378 + console.log('onRelateConfirm__fieldKey', _fieldKey)
  379 + const first = (items && items.length > 0) ? items[0] : null
  380 + // 若无选中项,确认时清空之前的值
  381 + this.form[_fieldKey] = first.id || '';
  382 + this.form[_fieldKey + 'Name'] = first.name || '';
  383 + },
  384 + async loadCustomerTypeOptions() {
  385 + try {
  386 + const res = await getDicByCodeApi('ENTERPRISE_TYPE');
  387 + const list = res.data || [];
  388 + this.customerTypeOptions = (list || []).map(it => ({
  389 + label: it.name || '',
  390 + value: it.code || ''
  391 + }))
  392 + } catch (e) {
  393 + this.customerTypeOptions = []
  394 + }
  395 + },
  396 +
  397 + async loadproductVarietyIdOptions() {
  398 + try {
  399 + const res = await productVarietyQueryApi({ pageIndex: 1, pageSize: 9999 })
  400 + const _data = res.data || {}
  401 + const list = _data.datas || (Array.isArray(_data) ? _data : [])
  402 + this.productVarietyIdOptions = (list || []).map(it => ({
  403 + label: it.name || it.text || it.label,
  404 + value: it.id || it.code || it.value
  405 + }))
  406 + } catch (e) {
  407 + this.productVarietyIdOptions = []
  408 + }
  409 + },
  410 + async onSubmit() {
  411 + // 必填校验
  412 + if (!this.validateRequired()) return
  413 + const payload = {
  414 + ...this.form
432 415 }
  416 + delete payload.workshopIdName
  417 + delete payload.officeIdName
  418 + delete payload.customerTypeName
  419 + delete payload.customerIdName
  420 + delete payload.productVarietyIdName
  421 + delete payload.chargeUserIdName
  422 + createApi(payload).then(res => {
  423 + uni.showToast({
  424 + title: '提交成功',
  425 + icon: 'success'
  426 + })
  427 + setTimeout(() => { uni.redirectTo({ url: '/pages/dev_manage/index' }) }, 300)
  428 + }).catch(e => {
  429 + console.log('createApi__e', e)
  430 + uni.showToast({
  431 + title: e.msg || '提交失败',
  432 + icon: 'none'
  433 + })
  434 + })
433 435 }
434 436 }
  437 +}
435 438 </script>
436 439
437 440 <style lang="scss" scoped>
438   - .page {
439   - display: flex;
440   - flex-direction: column;
441   - height: 100%;
  441 +.page {
  442 + display: flex;
  443 + flex-direction: column;
  444 + height: 100%;
  445 +}
  446 +
  447 +.scroll {
  448 + flex: 1;
  449 + padding: 12rpx 0 160rpx;
  450 +}
  451 +
  452 +.footer {
  453 + position: fixed;
  454 + left: 0;
  455 + right: 0;
  456 + bottom: 0;
  457 + padding: 32rpx;
  458 + padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
  459 + background: #fff;
  460 + box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
  461 + z-index: 10;
  462 +
  463 + .btn {
  464 + height: 80rpx;
  465 + line-height: 80rpx;
  466 + border-radius: 12rpx;
  467 + font-size: 32rpx;
442 468 }
443 469
444   - .scroll {
445   - flex: 1;
446   - padding: 12rpx 0 160rpx;
  470 + .submit {
  471 + background: $theme-primary;
  472 + color: #fff;
447 473 }
  474 +}
448 475
449   - .footer {
450   - position: fixed;
451   - left: 0;
452   - right: 0;
453   - bottom: 0;
454   - padding: 32rpx;
455   - padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
456   - background: #fff;
457   - box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
458   - z-index: 10;
  476 +::v-deep .uni-list {
  477 + background: transparent;
459 478
460   - .btn {
461   - height: 80rpx;
462   - line-height: 80rpx;
463   - border-radius: 12rpx;
  479 + &-item {
  480 + &__extra-text {
464 481 font-size: 32rpx;
465 482 }
466 483
467   - .submit {
468   - background: $theme-primary;
469   - color: #fff;
  484 + &__content-title {
  485 + font-size: 32rpx;
  486 + color: rgba(0, 0, 0, 0.9);
470 487 }
471   - }
472 488
473   - ::v-deep .uni-list {
474   - background: transparent;
475   - &-item {
476   - &__extra-text {
477   - font-size: 32rpx;
478   - }
479   - &__content-title {
480   - font-size: 32rpx;
481   - color: rgba(0, 0, 0, 0.9);
482   - }
  489 + &__container {
  490 + padding: 32rpx;
  491 +
  492 + .uni-easyinput {
  493 + &__placeholder-class {
  494 + font-size: 32rpx;
  495 + color: rgba(0, 0, 0, 0.4);
  496 + }
483 497
484   - &__container {
485   - padding: 32rpx;
  498 + &__content {
  499 + border: none;
486 500
487   - .uni-easyinput {
488   - &__placeholder-class {
  501 + &-input {
  502 + padding-left: 0 !important;
  503 + height: 48rpx;
  504 + line-height: 48rpx;
489 505 font-size: 32rpx;
490   - color: rgba(0, 0, 0, 0.4);
491 506 }
492 507
493   - &__content {
494   - border: none;
495   -
496   - &-input {
497   - padding-left: 0 !important;
498   - height: 48rpx;
499   - line-height: 48rpx;
500   - font-size: 32rpx;
501   - }
502   -
503   - .content-clear-icon {
504   - font-size: 44rpx !important;
505   - }
  508 + .content-clear-icon {
  509 + font-size: 44rpx !important;
506 510 }
507 511 }
  512 + }
508 513
509   - .item-title,
510   - .uni-list-item__content {
511   - flex: none;
512   - min-height: 48rpx;
513   - line-height: 48rpx;
514   - font-size: 32rpx;
515   - position: relative;
516   - width: 210rpx;
517   - margin-right: 32rpx;
518   - color: rgba(0, 0, 0, 0.9);
  514 + .item-title,
  515 + .uni-list-item__content {
  516 + flex: none;
  517 + min-height: 48rpx;
  518 + line-height: 48rpx;
  519 + font-size: 32rpx;
  520 + position: relative;
  521 + width: 210rpx;
  522 + margin-right: 32rpx;
  523 + color: rgba(0, 0, 0, 0.9);
519 524
520   - .required {
521   - color: red;
522   - position: absolute;
523   - top: 50%;
524   - transform: translateY(-50%);
525   - left: -16rpx;
526   - }
  525 + .required {
  526 + color: red;
  527 + position: absolute;
  528 + top: 50%;
  529 + transform: translateY(-50%);
  530 + left: -16rpx;
527 531 }
528   -
529 532 }
530   - &.select-item {
531   - &.is-empty {
532   - .uni-list-item__extra-text {
533   - color: rgba(0, 0, 0, 0.4) !important;
534   - }
535   - }
536   - &.is-filled {
537   - .uni-list-item__extra-text {
538   - color: rgba(0, 0, 0, 0.9) !important;
539   - }
  533 +
  534 + }
  535 +
  536 + &.select-item {
  537 + &.is-empty {
  538 + .uni-list-item__extra-text {
  539 + color: rgba(0, 0, 0, 0.4) !important;
540 540 }
541 541 }
542   - &.mgb10 {
543   - margin-bottom: 20rpx;
  542 +
  543 + &.is-filled {
  544 + .uni-list-item__extra-text {
  545 + color: rgba(0, 0, 0, 0.9) !important;
  546 + }
544 547 }
545 548 }
546   - }
547 549
  550 + &.mgb10 {
  551 + margin-bottom: 20rpx;
  552 + }
  553 + }
  554 +}
548 555 </style>
\ No newline at end of file
... ...
... ... @@ -5,21 +5,27 @@
5 5 <view class="section">
6 6 <text class="row customer">{{ form.customer.name }}</text>
7 7 <view :class="['status', `status_${form.status}`]" />
8   - <view class="row"><text class="label">生产厂</text><text class="value">{{ form.workshop ? form.workshop.name : '' }}</text>
  8 + <view class="row"><text class="label">生产厂</text><text class="value">{{ form.workshop ?
  9 + form.workshop.name : '' }}</text>
9 10 </view>
10   - <view class="row"><text class="label">科办</text><text class="value">{{ form.office ? form.office.name : '' }}</text>
  11 + <view class="row"><text class="label">科办</text><text class="value">{{ form.office ? form.office.name
  12 + : '' }}</text>
11 13 </view>
12   - <view class="row"><text class="label">客户类型</text><text
13   - class="value">{{ getDicName('ENTERPRISE_TYPE', form.customerType, customerTypeOptions) }}</text>
  14 + <view class="row"><text class="label">客户类型</text><text class="value">{{
  15 + getDicName('ENTERPRISE_TYPE', form.customerType, customerTypeOptions) }}</text>
14 16 </view>
15   - <view class="row"><text class="label">产品品种</text><text
16   - class="value">{{ form.productVariety.name }}</text></view>
  17 + <view class="row"><text class="label">产品品种</text><text class="value">{{ form.productVariety.name
  18 + }}</text></view>
17 19 <view class="row"><text class="label">月用量</text><text class="value">{{ form.monthlyUsage }}</text>
18 20 </view>
19 21 <view class="row"><text class="label">目标量</text><text class="value">{{ form.targetQuantity }}</text>
20 22 </view>
  23 + <view class="row"><text class="label">订单吨位(kg)</text><text class="value">{{ form.orderQuantity }}</text>
  24 + </view>
  25 + <view class="row"><text class="label">发货吨位(kg)</text><text class="value">{{ form.shipmentQuantity }}</text>
  26 + </view>
21 27 <view class="row"><text class="label">行业</text><text class="value">{{ form.industry }}</text></view>
22   - <view class="row"><text class="label">创建日期</text><text class="value">{{ form.createTime }}</text>
  28 + <view class="row"><text class="label">创建日期</text><text class="value">{{ form.createTime }}</text>
23 29 </view>
24 30 </view>
25 31 <view class="section">
... ... @@ -27,10 +33,10 @@
27 33 <view class="row"><text class="label">厚度</text><text class="value">{{ form.thickness }}</text>
28 34 </view>
29 35 <view class="row"><text class="label">宽度</text><text class="value">{{ form.width }}</text></view>
30   - <view class="row"><text class="label">材质要求</text><text
31   - class="value">{{ form.materialRequire }}</text></view>
32   - <view class="row"><text class="label">品质要求</text><text
33   - class="value">{{ form.qualityRequire }}</text></view>
  36 + <view class="row"><text class="label">材质要求</text><text class="value">{{ form.materialRequire
  37 + }}</text></view>
  38 + <view class="row"><text class="label">品质要求</text><text class="value">{{ form.qualityRequire
  39 + }}</text></view>
34 40 <view class="row"><text class="label">同行</text><text class="value">{{ form.peer }}</text></view>
35 41 </view>
36 42 <view class="section">
... ... @@ -43,271 +49,292 @@
43 49 <view class="row"><text class="label">责任人</text><text class="value">{{ form.chargeUserName }}</text>
44 50 </view>
45 51 </view>
  52 + <VisitList mode="view" :list="form.visitRecords || []" />
46 53 </view>
47 54 </scroll-view>
48   - <detail-buttons :buttons="displayButtons" @click="handleButtonClick" />
  55 + <detail-buttons :buttons="displayButtons" @click="handleButtonClick" />
49 56 </view>
50 57 </template>
51 58
52 59 <script>
53   - import {
54   - getDetailApi,
55   - cancelApi
56   - } from '@/api/devManage.js'
57   - import {
58   - getDicName
59   - } from '@/utils/dic.js'
60   - import {
61   - getDicByCodeApi
62   - } from '@/api/base.js'
63   - import DetailButtons from '@/components/detail-buttons/index.vue'
  60 +import {
  61 + getDetailApi,
  62 + cancelApi
  63 +} from '@/api/devManage.js'
  64 +import {
  65 + getDicName
  66 +} from '@/utils/dic.js'
  67 +import {
  68 + getDicByCodeApi
  69 +} from '@/api/base.js'
  70 +import DetailButtons from '@/components/detail-buttons/index.vue'
  71 +import VisitList from './visitList.vue'
64 72
65   - export default {
66   - name: 'DevManageDetail',
67   - components: {
68   - DetailButtons
  73 +
  74 +export default {
  75 + name: 'DevManageDetail',
  76 + components: {
  77 + DetailButtons,
  78 + VisitList
  79 + },
  80 + data() {
  81 + return {
  82 + form: {
  83 + workshop: {},
  84 + office: {},
  85 + customer: {},
  86 + customerType: '',
  87 + chargeUserId: '',
  88 + chargeUserIdName: '',
  89 + productVariety: {},
  90 + monthlyUsage: '',
  91 + targetQuantity: '',
  92 + orderQuantity: '',
  93 + shipmentQuantity: '',
  94 + industry: '',
  95 + mark: '',
  96 + thickness: '',
  97 + width: '',
  98 + materialRequire: '',
  99 + qualityRequire: '',
  100 + peer: '',
  101 + pricingMode: '',
  102 + settleDays: '',
  103 + createTime: '',
  104 + status: ''
  105 + },
  106 + customerTypeOptions: [],
  107 + todoType: '',
  108 + buttons: [{
  109 + text: '编辑',
  110 + visible: true,
  111 + variant: 'outline',
  112 + event: 'edit',
  113 + },
  114 + {
  115 + text: '审核详情',
  116 + visible: true,
  117 + variant: 'outline',
  118 + event: 'auditDetail'
  119 + },
  120 + {
  121 + text: '审核',
  122 + visible: true,
  123 + variant: 'primary',
  124 + event: 'audit'
  125 + },
  126 + {
  127 + text: '拜访记录',
  128 + visible: true,
  129 + variant: 'primary',
  130 + event: 'visitAdd',
  131 + },
  132 + {
  133 + text: '取消',
  134 + visible: true,
  135 + variant: 'outline',
  136 + event: 'cancel',
  137 + style: {
  138 + color: 'rgba(0,0,0,0.9)',
  139 + border: '1px solid #DCDCDC'
  140 + }
  141 + }
  142 + ],
  143 + }
  144 + },
  145 + computed: {
  146 + displayButtons() {
  147 + const s = Number(this.form && this.form.status || 0)
  148 + const t = this.todoType || '';
  149 + return [
  150 + { ...this.buttons[0], visible: (s === 3 && t === '' && this.$auth.hasPermi('customer-dev-manage:customer-dev-plan:modify')) },
  151 + { ...this.buttons[1], visible: this.$auth.hasPermi('customer-dev-manage:customer-dev-plan:reviewDetail') },
  152 + { ...this.buttons[2], visible: (s === 1 && t === 'WAIT' && this.$auth.hasPermi('customer-dev-manage:customer-dev-plan:review')) },
  153 + { ...this.buttons[3], visible: (s === 2 && t === '' && this.$auth.hasPermi('customer-dev-manage:customer-dev-plan:record')) },
  154 + { ...this.buttons[4], visible: (s === 3 && t === '' && this.$auth.hasPermi('customer-dev-manage:customer-dev-plan:close')) }
  155 + ]
  156 + }
  157 + },
  158 + created() {
  159 + this.loadCustomerTypeOptions()
  160 + },
  161 + onShow() {
  162 + uni.$on('dev_manage_detail_reload', this.onReload)
  163 + },
  164 + onUnload() {
  165 + uni.$off('dev_manage_detail_reload', this.onReload)
  166 + },
  167 + onLoad(query) {
  168 + const id = (query && (query.id || query.code)) || ''
  169 + const t = (query && (query.todoType)) || ''
  170 + this.todoType = t
  171 + if (id) this.loadDetail(id)
  172 + },
  173 + methods: {
  174 + onReload(payload) {
  175 + const id = (payload && (payload.id || payload.code)) || this.form.id || this.form.code || ''
  176 + if (id) this.loadDetail(id)
69 177 },
70   - data() {
71   - return {
72   - form: {
73   - workshop: {},
74   - office: {},
75   - customer: {},
76   - customerType: '',
77   - chargeUserId: '',
78   - chargeUserIdName: '',
79   - productVariety: {},
80   - monthlyUsage: '',
81   - targetQuantity: '',
82   - industry: '',
83   - mark: '',
84   - thickness: '',
85   - width: '',
86   - materialRequire: '',
87   - qualityRequire: '',
88   - peer: '',
89   - pricingMode: '',
90   - settleDays: '',
91   - createTime: '',
92   - status: ''
93   - },
94   - customerTypeOptions: [],
95   - todoType: '',
96   - buttons: [{
97   - text: '编辑',
98   - visible: true,
99   - variant: 'outline',
100   - event: 'edit',
101   - },
102   - {
103   - text: '审核详情',
104   - visible: true,
105   - variant: 'outline',
106   - event: 'auditDetail'
107   - },
108   - {
109   - text: '审核',
110   - visible: true,
111   - variant: 'primary',
112   - event: 'audit'
113   - },
114   - {
115   - text: '取消',
116   - visible: true,
117   - variant: 'outline',
118   - event: 'cancel',
119   - style: {
120   - color: 'rgba(0,0,0,0.9)',
121   - border: '1px solid #DCDCDC'
122   - }
123   - }
124   - ],
125   - }
126   - },
127   - computed: {
128   - displayButtons() {
129   - const s = Number(this.form && this.form.status || 0)
130   - const t = this.todoType || ''
131   - return [
132   - { ...this.buttons[0], visible: (s === 3 && t === '') },
133   - { ...this.buttons[1] },
134   - { ...this.buttons[2], visible: (s === 1 && t === 'WAIT') },
135   - { ...this.buttons[3], visible: (s === 3 && t === '') }
136   - ]
137   - }
138   - },
139   - created() {
140   - this.loadCustomerTypeOptions()
  178 + async loadDetail(id) {
  179 + try {
  180 + const res = await getDetailApi(id)
  181 + console.log('getDetailApi res', res)
  182 + const data = res.data || {};
  183 + this.form = {
  184 + ...data
  185 + }
  186 + } catch (e) {
  187 + console.error('loadDetail error', e)
  188 + }
141 189 },
142   - onShow() {
143   - uni.$on('dev_manage_detail_reload', this.onReload)
  190 + async loadCustomerTypeOptions() {
  191 + try {
  192 + const res = await getDicByCodeApi('ENTERPRISE_TYPE')
  193 + const list = res.data || []
  194 + this.customerTypeOptions = Array.isArray(list) ? list : []
  195 + } catch (e) {
  196 + this.customerTypeOptions = []
  197 + }
144 198 },
145   - onUnload() {
146   - uni.$off('dev_manage_detail_reload', this.onReload)
  199 + getDicName: getDicName,
  200 + handleButtonClick(btn) {
  201 + if (!btn || btn.disabled) return
  202 + if (typeof btn.onClick === 'function') return btn.onClick(this.form, btn.params)
  203 + const e = btn.event || ''
  204 + if (e === 'edit') return this.onEdit(btn && btn.params)
  205 + if (e === 'auditDetail') return this.onAuditDetail(btn && btn.params)
  206 + if (e === 'audit') return this.onAudit(btn && btn.params)
  207 + if (e === 'cancel') return this.onCancel(btn && btn.params)
  208 + if (e === 'visitAdd') return this.onVisitAdd(btn && btn.params)
147 209 },
148   - onLoad(query) {
149   - const id = (query && (query.id || query.code)) || ''
150   - const t = (query && (query.todoType)) || ''
151   - this.todoType = t
152   - if (id) this.loadDetail(id)
153   - },
154   - methods: {
155   - onReload(payload) {
156   - const id = (payload && (payload.id || payload.code)) || this.form.id || this.form.code || ''
157   - if (id) this.loadDetail(id)
158   - },
159   - async loadDetail(id) {
160   - try {
161   - const res = await getDetailApi(id)
162   - console.log('getDetailApi res', res)
163   - const data = res.data || {};
164   - this.form = {
165   - ...data
  210 + onEdit() {
  211 + const id = this.form.id || this.form.code || ''
  212 + const query = id ? ('?id=' + encodeURIComponent(id)) : ''
  213 + uni.navigateTo({
  214 + url: '/pages/dev_manage/modify' + query
  215 + })
  216 + },
  217 + onAuditDetail() {
  218 + const CACHE_KEY = 'sourceBusinessId';
  219 + uni.setStorageSync(CACHE_KEY, this.form.id)
  220 + uni.navigateTo({ url: '/pages/flow/audit_detail' })
  221 + },
  222 + onAudit() {
  223 + const CACHE_KEY = 'sourceBusinessId';
  224 + uni.setStorageSync(CACHE_KEY, this.form.id);
  225 + uni.navigateTo({ url: '/pages/flow/audit' })
  226 + },
  227 + onCancel() {
  228 + const id = this.form && (this.form.id || this.form.code) || ''
  229 + if (!id) return
  230 + uni.showModal({
  231 + title: '系统提示',
  232 + content: '是否确定取消该流程?',
  233 + confirmText: '确定',
  234 + cancelText: '取消',
  235 + success: (res) => {
  236 + if (res && res.confirm) {
  237 + cancelApi(id).then(() => {
  238 + uni.showToast({ title: '已取消', icon: 'none' })
  239 + setTimeout(() => {
  240 + uni.redirectTo({ url: '/pages/dev_manage/index' })
  241 + }, 300)
  242 + }).catch(() => {
  243 + uni.showToast({ title: '取消失败', icon: 'none' })
  244 + })
166 245 }
167   - } catch (e) {
168   - console.error('loadDetail error', e)
169 246 }
170   - },
171   - async loadCustomerTypeOptions() {
172   - try {
173   - const res = await getDicByCodeApi('ENTERPRISE_TYPE')
174   - const list = res.data || []
175   - this.customerTypeOptions = Array.isArray(list) ? list : []
176   - } catch (e) {
177   - this.customerTypeOptions = []
178   - }
179   - },
180   - getDicName: getDicName,
181   - handleButtonClick(btn) {
182   - if (!btn || btn.disabled) return
183   - if (typeof btn.onClick === 'function') return btn.onClick(this.form, btn.params)
184   - const e = btn.event || ''
185   - if (e === 'edit') return this.onEdit(btn && btn.params)
186   - if (e === 'auditDetail') return this.onAuditDetail(btn && btn.params)
187   - if (e === 'audit') return this.onAudit(btn && btn.params)
188   - if (e === 'cancel') return this.onCancel(btn && btn.params)
189   - },
190   - onEdit() {
191   - const id = this.form.id || this.form.code || ''
192   - const query = id ? ('?id=' + encodeURIComponent(id)) : ''
193   - uni.navigateTo({
194   - url: '/pages/dev_manage/modify' + query
195   - })
196   - },
197   - onAuditDetail() {
198   - const CACHE_KEY = 'sourceBusinessId';
199   - uni.setStorageSync(CACHE_KEY, this.form.id)
200   - uni.navigateTo({ url: '/pages/flow/audit_detail' })
201   - },
202   - onAudit() {
203   - const CACHE_KEY = 'sourceBusinessId';
204   - uni.setStorageSync(CACHE_KEY, this.form.id);
205   - uni.navigateTo({ url: '/pages/flow/audit' })
206   - },
207   - onCancel() {
208   - const id = this.form && (this.form.id || this.form.code) || ''
209   - if (!id) return
210   - uni.showModal({
211   - title: '系统提示',
212   - content: '是否确定取消该流程?',
213   - confirmText: '确定',
214   - cancelText: '取消',
215   - success: (res) => {
216   - if (res && res.confirm) {
217   - cancelApi(id).then(() => {
218   - uni.showToast({ title: '已取消', icon: 'none' })
219   - setTimeout(() => {
220   - uni.redirectTo({ url: '/pages/dev_manage/index' })
221   - }, 300)
222   - }).catch(() => {
223   - uni.showToast({ title: '取消失败', icon: 'none' })
224   - })
225   - }
226   - }
227   - })
228   - }
  247 + })
  248 + },
  249 + onVisitAdd() {
  250 + console.log('onVisitAdd', this.form)
  251 + const id = this.form && (this.form.id || this.form.code) || ''
  252 + if (!id) return
  253 + const query = id ? ('?id=' + encodeURIComponent(id)) : ''
  254 + uni.navigateTo({ url: '/pages/dev_manage/visit_add' + query })
229 255 }
230 256 }
  257 +}
231 258 </script>
232 259
233 260 <style lang="scss" scoped>
234   - .page {
235   - display: flex;
236   - flex-direction: column;
237   - height: 100%;
238   - }
239   -
240   - .scroll {
241   - flex: 1;
242   - padding: 8rpx 0 144rpx 0;
243   - }
  261 +.page {
  262 + display: flex;
  263 + flex-direction: column;
  264 + height: 100%;
  265 +}
244 266
245   - .detail-page {
246   - background: #f3f3f3;
247   - }
  267 +.scroll {
  268 + flex: 1;
  269 + padding: 8rpx 0 144rpx 0;
  270 +}
248 271
249   - .section {
250   - padding: 32rpx;
251   - background: #fff;
252   - margin-bottom: 20rpx;
253   - position: relative;
  272 +.detail-page {
  273 + background: #f3f3f3;
  274 +}
254 275
255   - .status {
256   - position: absolute;
257   - top: 16rpx;
258   - right: 52rpx;
259   - width: 180rpx;
260   - height: 146rpx;
261   - background-repeat: no-repeat;
262   - background-size: 100% 100%;
263   - background-position: center;
  276 +.section {
  277 + padding: 32rpx;
  278 + background: #fff;
  279 + margin-bottom: 20rpx;
  280 + position: relative;
264 281
265   - &_1 {
266   - background-image: url('~@/static/images/dev_manage/status_1.png');
267   - }
  282 + .status {
  283 + position: absolute;
  284 + top: 16rpx;
  285 + right: 52rpx;
  286 + width: 180rpx;
  287 + height: 146rpx;
  288 + background-repeat: no-repeat;
  289 + background-size: 100% 100%;
  290 + background-position: center;
268 291
269   - &_2 {
270   - background-image: url('~@/static/images/dev_manage/status_2.png');
271   - }
  292 + &_1 {
  293 + background-image: url('~@/static/images/dev_manage/status_1.png');
  294 + }
272 295
273   - &_3 {
274   - background-image: url('~@/static/images/dev_manage/status_3.png');
275   - }
  296 + &_2 {
  297 + background-image: url('~@/static/images/dev_manage/status_2.png');
  298 + }
276 299
277   - &_4 {
278   - background-image: url('~@/static/images/dev_manage/status_4.png');
279   - }
  300 + &_3 {
  301 + background-image: url('~@/static/images/dev_manage/status_3.png');
  302 + }
280 303
  304 + &_4 {
  305 + background-image: url('~@/static/images/dev_manage/status_4.png');
281 306 }
282 307
283   - .row {
284   - display: flex;
285   - margin-bottom: 28rpx;
  308 + }
286 309
287   - &:last-child {
288   - margin-bottom: 0;
289   - }
  310 + .row {
  311 + display: flex;
  312 + margin-bottom: 28rpx;
290 313
291   - &.customer {
292   - font-size: 36rpx;
293   - font-weight: 600;
294   - color: rgba(0, 0, 0, 0.9);
295   - }
  314 + &:last-child {
  315 + margin-bottom: 0;
  316 + }
296 317
297   - .label {
298   - width: 120rpx;
299   - line-height: 32rpx;
300   - font-size: 28rpx;
301   - color: rgba(0, 0, 0, 0.6);
302   - }
  318 + &.customer {
  319 + font-size: 36rpx;
  320 + font-weight: 600;
  321 + color: rgba(0, 0, 0, 0.9);
  322 + }
303 323
304   - .value {
305   - flex: 1;
306   - line-height: 32rpx;
307   - font-size: 28rpx;
308   - color: rgba(0, 0, 0, 0.9);
309   - text-align: right;
310   - }
  324 + .label {
  325 + max-width: 300rpx;
  326 + line-height: 32rpx;
  327 + font-size: 28rpx;
  328 + color: rgba(0, 0, 0, 0.6);
  329 + }
  330 +
  331 + .value {
  332 + flex: 1;
  333 + line-height: 32rpx;
  334 + font-size: 28rpx;
  335 + color: rgba(0, 0, 0, 0.9);
  336 + text-align: right;
311 337 }
312 338 }
313   -</style>
\ No newline at end of file
  339 +}
  340 +</style>
... ...
... ... @@ -5,13 +5,14 @@
5 5 <uni-search-bar v-model="searchKeyword" radius="6" placeholder="请输入客户名称" clearButton="auto"
6 6 cancelButton="none" bgColor="#F3F3F3" textColor="rgba(0,0,0,0.4)" @confirm="search"
7 7 @input="onSearchInput" />
8   - <view class="tool-icons">
9   - <image class="tool-icon"
10   - :src="batchMode ? '/static/images/dev_manage/close_icon.png' : '/static/images/dev_manage/batch_icon.png'"
11   - @click="toggleBatch" />
12   - <image class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
13   - <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
14   - </view>
  8 + <view class="tool-icons">
  9 + <image class="tool-icon"
  10 + v-if="$auth.hasPermi('customer-dev-manage:customer-dev-plan:batchReview')"
  11 + :src="batchMode ? '/static/images/dev_manage/close_icon.png' : '/static/images/dev_manage/batch_icon.png'"
  12 + @click="toggleBatch" />
  13 + <image v-if="$auth.hasPermi('customer-dev-manage:customer-dev-plan:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
  14 + <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
  15 + </view>
15 16 </view>
16 17
17 18 <!-- 页内 tabs -->
... ... @@ -355,11 +356,11 @@
355 356 })
356 357 })
357 358 },
358   - onAdd() {
359   - uni.navigateTo({
360   - url: '/pages/dev_manage/add'
361   - })
362   - },
  359 + onAdd() {
  360 + uni.navigateTo({
  361 + url: '/pages/dev_manage/add'
  362 + })
  363 + },
363 364 // 列表接口(真实请求)
364 365 fetchList({
365 366 pageIndex,
... ... @@ -811,4 +812,4 @@
811 812 }
812 813 }
813 814 }
814   -</style>
\ No newline at end of file
  815 +</style>
... ...
  1 +<template>
  2 + <view class="product" :class="{ 'history': mode == 'history' }">
  3 +
  4 + <!-- 详情-拜访记录 -->
  5 + <view class="header bp">
  6 + <image class="opCollapse" src="/static/images/title.png" />
  7 + <text class="title">拜访记录</text>
  8 + <view class="ops">
  9 + <view v-if="mode === 'view'" class="op1" @click="toggleViewCollapse">
  10 + <image class="opAdd" :src="collapsedView ? '/static/images/down.png' : '/static/images/up.png'" />
  11 + <text class="op">{{ collapsedView ? '展开' : '收起' }} </text>
  12 + </view>
  13 +
  14 + </view>
  15 + </view>
  16 + <view v-if="mode === 'view'" class="view-list" v-show="!collapsedView">
  17 + <view v-for="(item, idx) in items" :key="'v-' + idx" class="card">
  18 + <view class="row"><text class="label">拜访人姓名</text><text class="value">{{ item.userName }}</text></view>
  19 + <view class="row"><text class="label">拜访时间</text><text class="value">{{ item.visitTime }}</text></view>
  20 + <view class="row"><text class="label">拜访内容</text><text class="value">{{ item.visitContent }}</text></view>
  21 + </view>
  22 + </view>
  23 +
  24 + </view>
  25 +</template>
  26 +<script>
  27 +import { uuid } from '@/utils/uuid.js'
  28 +export default {
  29 + name: 'VisitList',
  30 + props: {
  31 + title: { type: String, default: '' },
  32 + mode: { type: String, default: 'add' },
  33 + list: { type: Array, default: () => [] },
  34 + },
  35 + data() {
  36 + return {
  37 + items: [],
  38 + collapsedView: false,
  39 + }
  40 + },
  41 + watch: {
  42 + items: {
  43 + handler() { this.emitChange() },
  44 + deep: true
  45 + },
  46 + list: {
  47 + handler(v) {
  48 + const arr = Array.isArray(v) ? v : []
  49 + this.items = arr.map(x => {
  50 + const it = { ...this.defaultItem(), ...x, collapsed: true }
  51 + return it
  52 + })
  53 + },
  54 + deep: true
  55 + },
  56 + },
  57 + created() {
  58 + const init = Array.isArray(this.list) && this.list.length > 0 ? this.list.map(v => ({ ...this.defaultItem(), ...v, collapsed: false })) : [{ ...this.defaultItem(), collapsed: false }]
  59 + this.items = init
  60 + },
  61 + methods: {
  62 + defaultItem() {
  63 + return { collapsed: false, packagingFee: '' }
  64 + },
  65 + toggleItem(idx) {
  66 + const it = this.items[idx]
  67 + if (!it) return
  68 + it.collapsed = !it.collapsed
  69 + this.$set(this.items, idx, it)
  70 + },
  71 + emitChange() {
  72 + console.log('emitChange__items', this.items)
  73 + const out = this.items.map(it => JSON.parse(JSON.stringify(it)))
  74 + console.log('emitChange__out', out)
  75 + this.$emit('input', out)
  76 + this.$emit('update:value', out)
  77 + this.$emit('change', out)
  78 + },
  79 + toggleViewCollapse() {
  80 + this.collapsedView = !this.collapsedView
  81 + },
  82 + }
  83 +}
  84 +</script>
  85 +<style lang="scss" scoped>
  86 +.header {
  87 + background-color: #fff;
  88 + display: flex;
  89 + align-items: center;
  90 + padding: 24rpx 32rpx;
  91 +
  92 + &.bp {
  93 + border-bottom: 1px solid #f0f0f0;
  94 + }
  95 +}
  96 +
  97 +.dot {
  98 + width: 16rpx;
  99 + height: 16rpx;
  100 + background: #3D48A3;
  101 + border-radius: 50%;
  102 + margin-right: 12rpx;
  103 +}
  104 +
  105 +.title {
  106 + font-size: 32rpx;
  107 + color: rgba(0, 0, 0, 0.9);
  108 + font-weight: 600;
  109 +}
  110 +
  111 +.ops {
  112 + margin-left: auto;
  113 +}
  114 +
  115 +.op {
  116 + color: $theme-primary;
  117 + font-size: 28rpx;
  118 + margin-left: 8rpx;
  119 +}
  120 +
  121 +.op1 {
  122 + display: flex;
  123 + align-items: center;
  124 +}
  125 +
  126 +.opAdd {
  127 + color: rgba(0, 0, 0, 0.6);
  128 + width: 40rpx;
  129 + height: 40rpx;
  130 +}
  131 +
  132 +.opCollapse {
  133 + color: rgba(0, 0, 0, 0.6);
  134 + width: 32rpx;
  135 + height: 28rpx;
  136 + margin-right: 16rpx;
  137 +}
  138 +
  139 +
  140 +::v-deep .uni-list {
  141 + background: transparent;
  142 +
  143 + &-item {
  144 + &__extra-text {
  145 + font-size: 32rpx;
  146 + }
  147 +
  148 + &__content-title {
  149 + font-size: 32rpx;
  150 + color: rgba(0, 0, 0, 0.9);
  151 + }
  152 +
  153 + &__container {
  154 + padding: 32rpx;
  155 +
  156 + .uni-easyinput {
  157 +
  158 + .is-disabled {
  159 + background-color: transparent !important;
  160 + }
  161 +
  162 + &__placeholder-class {
  163 + font-size: 32rpx;
  164 + color: rgba(0, 0, 0, 0.4);
  165 + }
  166 +
  167 + &__content {
  168 + border: none;
  169 +
  170 + &-input {
  171 + padding-left: 0 !important;
  172 + height: 48rpx;
  173 + line-height: 48rpx;
  174 + font-size: 32rpx;
  175 + }
  176 +
  177 + .content-clear-icon {
  178 + font-size: 44rpx !important;
  179 + }
  180 + }
  181 + }
  182 +
  183 + .amount-row {
  184 + flex: 1;
  185 + display: flex;
  186 + align-items: center;
  187 +
  188 + .uni-easyinput {
  189 + flex: 1;
  190 + }
  191 +
  192 + .unit {
  193 + margin-left: 16rpx;
  194 + color: rgba(0, 0, 0, 0.9);
  195 + }
  196 + }
  197 +
  198 + .item-title,
  199 + .uni-list-item__content {
  200 + flex: none;
  201 + min-height: 48rpx;
  202 + line-height: 48rpx;
  203 + font-size: 32rpx;
  204 + position: relative;
  205 + width: 210rpx;
  206 + margin-right: 32rpx;
  207 + color: rgba(0, 0, 0, 0.9);
  208 + padding-right: 0;
  209 +
  210 +
  211 + .required {
  212 + color: red;
  213 + position: absolute;
  214 + top: 50%;
  215 + transform: translateY(-50%);
  216 + left: -16rpx;
  217 + }
  218 + }
  219 +
  220 + }
  221 +
  222 + &.select-item {
  223 + &.is-empty {
  224 + .uni-list-item__extra-text {
  225 + color: rgba(0, 0, 0, 0.4) !important;
  226 + }
  227 + }
  228 +
  229 + &.is-filled {
  230 + .uni-list-item__extra-text {
  231 + color: rgba(0, 0, 0, 0.9) !important;
  232 + }
  233 + }
  234 +
  235 + .serial-number-row {
  236 + display: flex;
  237 + align-items: center;
  238 + }
  239 +
  240 + }
  241 +
  242 + &.mgb10 {
  243 + margin-bottom: 20rpx;
  244 + }
  245 +
  246 + }
  247 +
  248 + .title-header {
  249 + background-color: #fff;
  250 + display: flex;
  251 + align-items: center;
  252 + padding: 32rpx 32rpx 22rpx;
  253 +
  254 + &_icon {
  255 + width: 32rpx;
  256 + height: 28rpx;
  257 + margin-right: 16rpx;
  258 + }
  259 +
  260 + span {
  261 + color: rgba(0, 0, 0, 0.9);
  262 + font-size: 32rpx;
  263 + line-height: 44rpx;
  264 + font-weight: 600;
  265 + }
  266 + }
  267 +}
  268 +
  269 +/* 只读 easyinput 根据内容自适应高度 */
  270 +::v-deep .uni-list-item__container {
  271 + align-items: flex-start;
  272 +}
  273 +
  274 +.block-ops {
  275 + display: flex;
  276 + padding: 20rpx 32rpx 20rpx;
  277 + justify-content: space-around;
  278 +}
  279 +
  280 +.del {
  281 + color: #D54941;
  282 + font-size: 28rpx;
  283 + display: flex;
  284 + align-items: center;
  285 +
  286 + image {
  287 + width: 40rpx;
  288 + height: 40rpx;
  289 + }
  290 +}
  291 +
  292 +.toggle {
  293 + color: $theme-primary;
  294 + font-size: 28rpx;
  295 + display: flex;
  296 + align-items: center;
  297 +
  298 + image {
  299 + width: 40rpx;
  300 + height: 40rpx;
  301 + }
  302 +}
  303 +
  304 +.section {
  305 + background: #f1f1f1;
  306 + margin-bottom: 20rpx;
  307 +
  308 + .block {
  309 + background: #ffffff;
  310 + padding: 32rpx 0;
  311 + margin-bottom: 20rpx;
  312 +
  313 + &:last-child {
  314 + margin-bottom: 0;
  315 + }
  316 + }
  317 +
  318 + .row {
  319 + display: flex;
  320 + // margin-bottom: 24rpx;
  321 + line-height: 32rpx;
  322 + padding: 32rpx;
  323 + border-bottom: 1rpx solid #f2f2f2;
  324 +
  325 +
  326 + &.noneStyle {
  327 + border-bottom: 0;
  328 + border-bottom: none;
  329 + }
  330 +
  331 + &.row-spec {
  332 + align-items: center;
  333 + }
  334 + }
  335 +
  336 + .row:last-child {
  337 + margin-bottom: 0;
  338 + }
  339 +
  340 + .label {
  341 + width: 210rpx;
  342 + margin-right: 32rpx;
  343 + color: rgba(0, 0, 0, 0.9);
  344 + font-size: 32rpx;
  345 + line-height: 48rpx;
  346 + }
  347 +
  348 + .value {
  349 + flex: 1;
  350 + color: rgba(0, 0, 0, 0.9);
  351 + font-size: 32rpx;
  352 + white-space: pre-wrap;
  353 + word-break: break-all;
  354 + line-height: 48rpx;
  355 + }
  356 +
  357 + .value-spec {
  358 + height: 48rpx;
  359 + display: flex;
  360 + align-items: center;
  361 + color: #000000;
  362 +
  363 + &_box {
  364 + position: relative;
  365 + width: 60rpx;
  366 + height: 48rpx;
  367 +
  368 + &_1 {
  369 + font-size: 16rpx;
  370 + position: absolute;
  371 + top: -10rpx;
  372 + left: 0;
  373 + }
  374 +
  375 + &_2 {
  376 + font-size: 16rpx;
  377 + position: absolute;
  378 + bottom: -10rpx;
  379 + left: 0;
  380 + }
  381 + }
  382 +
  383 + &_val {
  384 + font-size: 28rpx;
  385 +
  386 + &.p12 {
  387 + padding-right: 12rpx;
  388 + }
  389 + }
  390 + }
  391 +
  392 + .view-total {
  393 + padding-top: 20rpx;
  394 +
  395 + .head {
  396 + font-size: 32rpx;
  397 + font-weight: 600;
  398 + line-height: 50rpx;
  399 + color: rgba(0, 0, 0, 0.9);
  400 + padding-bottom: 16rpx;
  401 + margin-bottom: 24rpx;
  402 + ;
  403 + border-bottom: 1px dashed #E7E7E7;
  404 + }
  405 +
  406 + .row {
  407 + display: flex;
  408 + margin-bottom: 24rpx;
  409 + line-height: 32rpx;
  410 +
  411 + .label {
  412 + width: 180rpx;
  413 + margin-right: 14rpx;
  414 + color: rgba(0, 0, 0, 0.6);
  415 + font-size: 28rpx;
  416 + }
  417 +
  418 + .value {
  419 + flex: 1;
  420 + color: rgba(0, 0, 0, 0.9);
  421 + font-size: 28rpx;
  422 + white-space: pre-wrap;
  423 + word-break: break-all;
  424 + }
  425 + }
  426 + }
  427 +}
  428 +
  429 +.view-list {
  430 + padding: 26rpx 32rpx;
  431 + background: #ffffff;
  432 +
  433 + .card {
  434 + background: #f3f3f3;
  435 + border-radius: 16rpx;
  436 + padding: 32rpx 44rpx;
  437 + margin-bottom: 20rpx;
  438 +
  439 + &:last-child {
  440 + margin-bottom: 0;
  441 + }
  442 + }
  443 +
  444 + .row {
  445 + display: flex;
  446 + margin-bottom: 24rpx;
  447 + line-height: 32rpx;
  448 +
  449 + &.row-spec {
  450 + height: 60rpx;
  451 + align-items: center;
  452 + }
  453 + }
  454 +
  455 + .row:last-child {
  456 + margin-bottom: 0;
  457 + }
  458 +
  459 + .label {
  460 + width: 140rpx;
  461 + margin-right: 14rpx;
  462 + color: rgba(0, 0, 0, 0.6);
  463 + font-size: 28rpx;
  464 + }
  465 +
  466 + .value {
  467 + flex: 1;
  468 + color: rgba(0, 0, 0, 0.9);
  469 + font-size: 28rpx;
  470 + white-space: pre-wrap;
  471 + word-break: break-all;
  472 + }
  473 +
  474 + .value-spec {
  475 + height: 60rpx;
  476 + display: flex;
  477 + align-items: center;
  478 + color: #000000;
  479 +
  480 + &_box {
  481 + position: relative;
  482 + width: 60rpx;
  483 + height: 60rpx;
  484 +
  485 + &_1 {
  486 + font-size: 16rpx;
  487 + position: absolute;
  488 + top: 0;
  489 + left: 0;
  490 + }
  491 +
  492 + &_2 {
  493 + font-size: 16rpx;
  494 + position: absolute;
  495 + bottom: 0;
  496 + left: 0;
  497 + }
  498 + }
  499 +
  500 + &_val {
  501 + font-size: 28rpx;
  502 +
  503 + &.p12 {
  504 + padding-right: 12rpx;
  505 + }
  506 + }
  507 + }
  508 +
  509 + .view-total {
  510 + padding-top: 20rpx;
  511 +
  512 + .head {
  513 + font-size: 32rpx;
  514 + font-weight: 600;
  515 + line-height: 50rpx;
  516 + color: rgba(0, 0, 0, 0.9);
  517 + padding-bottom: 16rpx;
  518 + margin-bottom: 24rpx;
  519 + ;
  520 + border-bottom: 1px dashed #E7E7E7;
  521 + }
  522 +
  523 + .row {
  524 + display: flex;
  525 + margin-bottom: 24rpx;
  526 + line-height: 32rpx;
  527 +
  528 + .label {
  529 + width: 180rpx;
  530 + margin-right: 14rpx;
  531 + color: rgba(0, 0, 0, 0.6);
  532 + font-size: 28rpx;
  533 + }
  534 +
  535 + .value {
  536 + flex: 1;
  537 + color: rgba(0, 0, 0, 0.9);
  538 + font-size: 28rpx;
  539 + white-space: pre-wrap;
  540 + word-break: break-all;
  541 + }
  542 + }
  543 + }
  544 +}
  545 +</style>
... ...
  1 +<template>
  2 + <view class="page">
  3 + <scroll-view class="scroll" scroll-y>
  4 + <uni-list>
  5 + <uni-list-item class="select-item" :class="form.userId ? 'is-filled' : 'is-empty'" clickable
  6 + @click="openRelate('userId')" :rightText="form.userName || '请选择拜访人'" showArrow>
  7 + <template v-slot:body>
  8 + <view class="item-title"><text class="required">*</text><text>拜访人姓名</text></view>
  9 + </template>
  10 + </uni-list-item>
  11 +
  12 + <uni-list-item>
  13 + <template v-slot:body>
  14 + <view class="item-title"><text class="required">*</text><text>拜访时间</text></view>
  15 + </template>
  16 + <template v-slot:footer>
  17 + <uni-datetime-picker type="date" v-model="form.visitTime" />
  18 + </template>
  19 + </uni-list-item>
  20 +
  21 + <uni-list-item title="拜访内容">
  22 + <template v-slot:footer>
  23 + <uni-easyinput type="textarea" v-model="form.visitContent" placeholder="请输入拜访内容" :inputBorder="false" />
  24 + </template>
  25 + </uni-list-item>
  26 + </uni-list>
  27 + </scroll-view>
  28 +
  29 + <view class="footer">
  30 + <button class="btn submit" type="primary" @click="onSubmit">提交</button>
  31 + </view>
  32 +
  33 + <RelateSelectSheet :visible.sync="relate.visible" :title="relate.title" :source="relate.source"
  34 + :display-fields="relate.display" :multiple="relate.multiple" :row-key="relate.rowKey"
  35 + :selectedKeys.sync="relate.selectedKeys" :source-extra="{ source: 'CUSTOMER_DEVELOP' }"
  36 + @confirm="onRelateConfirm" />
  37 + </view>
  38 +</template>
  39 +
  40 +<script>
  41 +import RelateSelectSheet from '@/components/relate-select/index.vue'
  42 +import storage from '@/utils/storage'
  43 +import constant from '@/utils/constant'
  44 +import {
  45 + createVisitRecordApi
  46 +} from '@/api/devManage.js'
  47 +
  48 +export default {
  49 + name: 'DevManageVisitAdd',
  50 + components: { RelateSelectSheet },
  51 + data() {
  52 + return {
  53 + customerId: '',
  54 + form: {
  55 + userId: '',
  56 + userName: '',
  57 + visitTime: new Date().toISOString().substring(0, 10),
  58 + visitContent: ''
  59 + },
  60 + relate: { visible: false, title: '选择拜访人', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' }
  61 + }
  62 + },
  63 + created() {
  64 + const user = storage.get(constant.name)
  65 + const userId = storage.get(constant.id)
  66 + this.form.userName = user || ''
  67 + this.form.userId = userId || ''
  68 + },
  69 + onLoad(query) {
  70 + this.customerId = (query && query.id) || '';
  71 + },
  72 + methods: {
  73 + openRelate(fieldKey) {
  74 + let config = {}
  75 + if (fieldKey === 'userId') {
  76 + config = {
  77 + title: '拜访人',
  78 + source: 'user',
  79 + rowKey: 'id',
  80 + multiple: false,
  81 + display: [
  82 + { label: '姓名', field: 'name' },
  83 + { label: '编号', field: 'code' },
  84 + { label: '状态', field: 'available', format: v => (v ? '启用' : '停用') }
  85 + ]
  86 + }
  87 + }
  88 + const selectedKeys = this.form.userId ? [this.form.userId] : []
  89 + this.relate.title = config.title
  90 + this.relate.source = config.source
  91 + this.relate.display = config.display
  92 + this.relate.multiple = config.multiple
  93 + this.relate.rowKey = config.rowKey
  94 + this.relate.selectedKeys = selectedKeys
  95 + this.relate.fieldKey = fieldKey
  96 + this.$nextTick(() => { this.relate.visible = true })
  97 + },
  98 + onRelateConfirm({ items }) {
  99 + const first = (items && items.length > 0) ? items[0] : null
  100 + this.form.userId = (first && (first.id || first.userId)) || ''
  101 + this.form.userName = (first && (first.name || first.userName)) || ''
  102 + },
  103 + validateRequired() {
  104 + const checks = [
  105 + { key: 'userId', label: '拜访人姓名' },
  106 + { key: 'visitTime', label: '拜访时间' }
  107 + ]
  108 + for (const it of checks) {
  109 + const val = this.form[it.key]
  110 + if (val === undefined || val === null || String(val).trim() === '') {
  111 + uni.showToast({
  112 + title: `请先选择${it.label}`,
  113 + icon: 'none'
  114 + })
  115 + return false
  116 + }
  117 + }
  118 + return true
  119 + },
  120 + onSubmit() {
  121 + if (!this.validateRequired()) return
  122 + const payload = { ...this.form }
  123 + payload.customerId = this.customerId;
  124 + delete payload.userName;
  125 + console.log('visit_add_submit', payload)
  126 + createVisitRecordApi(payload).then(res => {
  127 + uni.showToast({
  128 + title: '提交成功',
  129 + icon: 'success'
  130 + })
  131 + setTimeout(() => { uni.redirectTo({ url: '/pages/dev_manage/index' }) }, 300)
  132 + }).catch(e => {
  133 + uni.showToast({
  134 + title: e.msg || '提交失败',
  135 + icon: 'none'
  136 + })
  137 + })
  138 + }
  139 + }
  140 +}
  141 +</script>
  142 +
  143 +<style lang="scss" scoped>
  144 +.page {
  145 + display: flex;
  146 + flex-direction: column;
  147 + height: 100%;
  148 +}
  149 +
  150 +.scroll {
  151 + flex: 1;
  152 + padding: 12rpx 0 160rpx;
  153 +}
  154 +
  155 +.footer {
  156 + position: fixed;
  157 + left: 0;
  158 + right: 0;
  159 + bottom: 0;
  160 + padding: 32rpx;
  161 + padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
  162 + background: #fff;
  163 + box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
  164 + z-index: 10;
  165 +
  166 + .btn {
  167 + height: 80rpx;
  168 + line-height: 80rpx;
  169 + border-radius: 12rpx;
  170 + font-size: 32rpx;
  171 + }
  172 +
  173 + .submit {
  174 + background: $theme-primary;
  175 + color: #fff;
  176 + }
  177 +}
  178 +
  179 +::v-deep .uni-list {
  180 + background: transparent;
  181 +
  182 + &-item {
  183 + &__extra-text {
  184 + font-size: 32rpx;
  185 + }
  186 +
  187 + &__content-title {
  188 + font-size: 32rpx;
  189 + color: rgba(0, 0, 0, 0.9);
  190 + }
  191 +
  192 + &__container {
  193 + padding: 32rpx;
  194 +
  195 + .uni-easyinput {
  196 + &__placeholder-class {
  197 + font-size: 32rpx;
  198 + color: rgba(0, 0, 0, 0.4);
  199 + }
  200 +
  201 + &__content {
  202 + border: none;
  203 +
  204 + &-input {
  205 + padding-left: 0 !important;
  206 + height: 48rpx;
  207 + line-height: 48rpx;
  208 + font-size: 32rpx;
  209 + }
  210 +
  211 + .content-clear-icon {
  212 + font-size: 44rpx !important;
  213 + }
  214 + }
  215 + }
  216 +
  217 + .item-title,
  218 + .uni-list-item__content {
  219 + flex: none;
  220 + min-height: 48rpx;
  221 + line-height: 48rpx;
  222 + font-size: 32rpx;
  223 + position: relative;
  224 + width: 210rpx;
  225 + margin-right: 32rpx;
  226 + color: rgba(0, 0, 0, 0.9);
  227 +
  228 + .required {
  229 + color: red;
  230 + position: absolute;
  231 + top: 50%;
  232 + transform: translateY(-50%);
  233 + left: -16rpx;
  234 + }
  235 + }
  236 +
  237 + }
  238 +
  239 + &.select-item {
  240 + &.is-empty {
  241 + .uni-list-item__extra-text {
  242 + color: rgba(0, 0, 0, 0.4) !important;
  243 + }
  244 + }
  245 +
  246 + &.is-filled {
  247 + .uni-list-item__extra-text {
  248 + color: rgba(0, 0, 0, 0.9) !important;
  249 + }
  250 + }
  251 + }
  252 +
  253 + &.mgb10 {
  254 + margin-bottom: 20rpx;
  255 + }
  256 + }
  257 +}
  258 +</style>
... ...
... ... @@ -6,7 +6,7 @@
6 6 <!-- name:MsgCenter 消息中心权限-->
7 7 <view class="bell-wrap" v-if="hasMenu('MsgCenter')">
8 8 <image class="icon" src="/static/images/index/bell.png" mode="widthFix" />
9   - <view class="badge">99+</view>
  9 + <view class="badge">{{ toReadCount > 99 ? '99+' : toReadCount }}</view>
10 10 </view>
11 11 </view>
12 12 <view class="header-title">首页</view>
... ... @@ -55,6 +55,7 @@ export default {
55 55 return {
56 56 todoCount: '',
57 57 myCreateCount: '',
  58 + toReadCount: '',
58 59 sectionList: [{
59 60 title: '客户开发管理',
60 61 items: [{
... ... @@ -163,6 +164,7 @@ export default {
163 164 statisticsCountApi().then((res) => {
164 165 this.todoCount = res.data.todoCount || '';
165 166 this.myCreateCount = res.data.myCreateCount || '';
  167 + this.toReadCount = res.data.toReadCount || '';
166 168 });
167 169 },
168 170 async loadMenusAndFilter() {
... ...
  1 +<template>
  2 + <view class="page">
  3 + <scroll-view class="scroll" scroll-y>
  4 + <view class="detail-page">
  5 + <view class="section">
  6 + <text class="row company">{{ detail.title }}</text>
  7 + <view class="row"><text class="label">内容</text><text class="value">{{ detail.content }}</text></view>
  8 + </view>
  9 + </view>
  10 + </scroll-view>
  11 + </view>
  12 +</template>
  13 +
  14 +<script>
  15 +import { getContentApi } from '@/api/message.js'
  16 +
  17 +export default {
  18 + data() {
  19 + return {
  20 + detail: { title: '', content: '' }
  21 + }
  22 + },
  23 + onLoad(options) {
  24 + const id = options && (options.id || options.code) || ''
  25 + if (!id) return
  26 + this.loadDetail(id)
  27 + },
  28 + methods: {
  29 + loadDetail(id) {
  30 + getContentApi(id)
  31 + .then(res => {
  32 + const d = res && res.data ? res.data : {}
  33 + this.detail = { title: d.title || '', content: d.content || '' }
  34 + })
  35 + .catch(() => {
  36 + this.detail = { title: '', content: '' }
  37 + uni.showToast({ title: '加载失败', icon: 'none' })
  38 + })
  39 + }
  40 + }
  41 +}
  42 +</script>
  43 +
  44 +<style lang="scss" scoped>
  45 +.page { display: flex; flex-direction: column; height: 100%; }
  46 +.scroll { flex: 1; padding: 8rpx 0 0; }
  47 +.detail-page { background: #f3f3f3; }
  48 +.section { padding: 32rpx; background: #fff; }
  49 +.row {
  50 + display: flex;
  51 + margin-bottom: 28rpx;
  52 +
  53 + &:last-child {
  54 + margin-bottom: 0;
  55 + }
  56 +
  57 + &.company {
  58 + font-size: 36rpx;
  59 + font-weight: 600;
  60 + color: rgba(0, 0, 0, 0.9);
  61 + line-height: 50rpx;
  62 + }
  63 +
  64 + .label {
  65 + max-width: 420rpx;
  66 + line-height: 32rpx;
  67 + font-size: 28rpx;
  68 + color: rgba(0, 0, 0, 0.6);
  69 + }
  70 +
  71 + .value {
  72 + flex: 1;
  73 + line-height: 32rpx;
  74 + font-size: 28rpx;
  75 + color: rgba(0, 0, 0, 0.9);
  76 + text-align: right;
  77 +
  78 + &.act {
  79 + color: $theme-primary;
  80 + }
  81 + }
  82 +}
  83 +</style>
  84 +
... ...
  1 +<template>
  2 + <view class="page">
  3 + <view class="message-list-fixed">
  4 + <view class="search-row">
  5 + <uni-search-bar v-model="searchKeyword" radius="6" placeholder="请输入标题" clearButton="auto"
  6 + cancelButton="none" bgColor="#F3F3F3" textColor="rgba(0,0,0,0.4)" @confirm="search"
  7 + @input="onSearchInput" />
  8 + <view class="tool-icons">
  9 + <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
  10 + </view>
  11 + </view>
  12 + </view>
  13 +
  14 + <view class="list-box">
  15 + <card-list ref="cardRef" :fetch-fn="fetchList" :query="query" :extra="extraParams" row-key="id"
  16 + :enable-refresh="true" :enable-load-more="true" @loaded="onCardLoaded" @error="onCardError">
  17 + <template v-slot="{ item }">
  18 + <view class="card" @click.stop="onCardClick(item)">
  19 + <view class="card-header">
  20 + <text class="title omit2">{{ item.title || '-' }}</text>
  21 + </view>
  22 + <view class="info-row">
  23 + <text>是否已读</text><text>{{ item.readed ? '是' : '否' }}</text>
  24 + </view>
  25 + <view class="info-row">
  26 + <text>创建时间</text><text>{{ item.createTime || '-' }}</text>
  27 + </view>
  28 + </view>
  29 + </template>
  30 + </card-list>
  31 + </view>
  32 +
  33 + <filter-modal :visible.sync="filterVisible" :value.sync="filterForm" title="筛选" @reset="onFilterReset"
  34 + @confirm="onFilterConfirm">
  35 + <template v-slot="{ model }">
  36 + <view class="filter-form">
  37 + <view class="form-item">
  38 + <view class="label">是否已读</view>
  39 + <uni-data-checkbox mode="tag" :multiple="false" :value-field="'value'" :text-field="'text'"
  40 + v-model="model.readed" :localdata="readOptions" />
  41 + </view>
  42 + <view class="form-item">
  43 + <view class="label">创建时间</view>
  44 + <uni-datetime-picker type="daterange" v-model="model.dateRange" start="2023-01-01" />
  45 + </view>
  46 + </view>
  47 + </template>
  48 + </filter-modal>
  49 + </view>
  50 +</template>
  51 +
  52 +<script>
  53 +import CardList from '@/components/card/index.vue'
  54 +import FilterModal from '@/components/filter/index.vue'
  55 +import { queryApi as messageQueryApi } from '@/api/message.js'
  56 +
  57 +export default {
  58 + name: 'MessageList',
  59 + components: { CardList, FilterModal },
  60 + data() {
  61 + return {
  62 + searchKeyword: '',
  63 + searchKeywordDebounced: '',
  64 + searchDebounceTimer: null,
  65 +
  66 + // 给到 card 的筛选值
  67 + query: { readed: '', dateRange: [] },
  68 + extraParams: {},
  69 +
  70 + // 筛选弹框
  71 + filterVisible: false,
  72 + filterForm: { readed: false, dateRange: [] },
  73 + readOptions: [
  74 + { value: true, text: '是' },
  75 + { value: false, text: '否' }
  76 + ],
  77 +
  78 + currentItems: []
  79 + }
  80 + },
  81 + computed: {
  82 + extraCombined() {
  83 + return {
  84 + title: this.searchKeywordDebounced || undefined
  85 + }
  86 + }
  87 + },
  88 + watch: {
  89 + extraCombined: {
  90 + deep: true,
  91 + handler(v) {
  92 + this.extraParams = v
  93 + },
  94 + immediate: true
  95 + }
  96 + },
  97 + created() {
  98 + const [start, end] = this.getDefaultDateRange()
  99 + this.filterForm.dateRange = [start, end]
  100 + this.query = { readed: this.filterForm.readed, dateRange: [start, end] }
  101 + },
  102 + onReachBottom() {
  103 + if (this.$refs && this.$refs.cardRef && this.$refs.cardRef.onLoadMore) {
  104 + this.$refs.cardRef.onLoadMore()
  105 + }
  106 + },
  107 + beforeDestroy() {
  108 + if (this.searchDebounceTimer) {
  109 + clearTimeout(this.searchDebounceTimer)
  110 + this.searchDebounceTimer = null
  111 + }
  112 + },
  113 + methods: {
  114 + // 默认日期范围:当前日期前一个月到今日
  115 + getDefaultDateRange() {
  116 + const fmt = d => {
  117 + const y = d.getFullYear()
  118 + const m = String(d.getMonth() + 1).padStart(2, '0')
  119 + const dd = String(d.getDate()).padStart(2, '0')
  120 + return `${y}-${m}-${dd}`
  121 + }
  122 + const end = new Date()
  123 + const start = new Date(end)
  124 + start.setMonth(start.getMonth() - 1)
  125 + return [fmt(start), fmt(end)]
  126 + },
  127 + onCardLoaded({ items }) {
  128 + this.currentItems = items
  129 + },
  130 + onCardError() {
  131 + uni.showToast({ title: '列表加载失败', icon: 'none' })
  132 + },
  133 + onCardClick(item) {
  134 + const id = (item && (item.id || item.code)) || ''
  135 + if (!id) return
  136 + const query = '?id=' + encodeURIComponent(id)
  137 + uni.navigateTo({ url: '/pages/message/detail' + query })
  138 + },
  139 + // 输入实时搜索:1200ms 防抖
  140 + onSearchInput(val) {
  141 + if (this.searchDebounceTimer) clearTimeout(this.searchDebounceTimer)
  142 + this.searchDebounceTimer = setTimeout(() => {
  143 + this.searchKeywordDebounced = this.searchKeyword
  144 + this.searchDebounceTimer = null
  145 + }, 1200)
  146 + },
  147 + // 确认搜索
  148 + search(e) {
  149 + const val = e && e.value != null ? e.value : this.searchKeyword
  150 + this.searchKeyword = val
  151 + this.searchKeywordDebounced = val
  152 + },
  153 + openFilter() {
  154 + this.filterVisible = true
  155 + },
  156 + onFilterReset(payload) {
  157 + this.filterForm = payload
  158 + },
  159 + onFilterConfirm(payload) {
  160 + if ((payload.readed === '' || payload.readed == null) && this.filterForm.readed !== '') {
  161 + payload.readed = this.filterForm.readed
  162 + }
  163 + this.query = { ...payload }
  164 + },
  165 + // 列表接口
  166 + fetchList({ pageIndex, pageSize, query, extra }) {
  167 + const params = {
  168 + pageIndex,
  169 + pageSize,
  170 + ...extra,
  171 + ...query
  172 + }
  173 + if (Array.isArray(params.dateRange) && params.dateRange.length === 2) {
  174 + params.createTimeStart = params.dateRange[0] + ' 00:00:00'
  175 + params.createTimeEnd = params.dateRange[1] + ' 23:59:59'
  176 + delete params.dateRange
  177 + }
  178 + if (this.searchKeywordDebounced) {
  179 + params.title = this.searchKeywordDebounced
  180 + }
  181 + return messageQueryApi(params)
  182 + .then(res => {
  183 + const _data = res.data || {}
  184 + const records = _data.datas || []
  185 + const totalCount = _data.totalCount || 0
  186 + const hasNext = _data.hasNext || false
  187 + return { records, totalCount, hasNext }
  188 + })
  189 + .catch(err => {
  190 + console.error('fetchList error', err)
  191 + this.onCardError()
  192 + return { records: [], totalCount: 0, hasNext: false }
  193 + })
  194 + }
  195 + }
  196 +}
  197 +</script>
  198 +
  199 +<style lang="scss" scoped>
  200 +.page {
  201 + display: flex;
  202 + flex-direction: column;
  203 + height: 100vh;
  204 +}
  205 +
  206 +.message-list-fixed {
  207 + position: fixed;
  208 + top: 96rpx;
  209 + left: 0;
  210 + right: 0;
  211 + z-index: 2;
  212 + background: #fff;
  213 +
  214 + .search-row {
  215 + display: flex;
  216 + align-items: center;
  217 + padding: 16rpx 32rpx;
  218 +
  219 + .uni-searchbar {
  220 + padding: 0;
  221 + flex: 1;
  222 + }
  223 +
  224 + .tool-icons {
  225 + display: flex;
  226 +
  227 + .tool-icon {
  228 + width: 48rpx;
  229 + height: 48rpx;
  230 + display: block;
  231 + margin-left: 32rpx;
  232 + }
  233 + }
  234 + }
  235 +}
  236 +
  237 +/* 仅当前页覆盖 uni-search-bar 盒子高度 */
  238 +::v-deep .uni-searchbar__box {
  239 + height: 80rpx !important;
  240 + justify-content: start;
  241 +
  242 + .uni-searchbar__box-search-input {
  243 + font-size: 32rpx !important;
  244 + }
  245 +}
  246 +
  247 +.list-box {
  248 + flex: 1;
  249 + padding-top: 132rpx;
  250 +
  251 + .card {
  252 + position: relative;
  253 + }
  254 +
  255 + .card-header {
  256 + margin-bottom: 28rpx;
  257 +
  258 + .title {
  259 + font-size: 36rpx;
  260 + font-weight: 600;
  261 + line-height: 50rpx;
  262 + color: rgba(0, 0, 0, 0.9);
  263 + }
  264 + }
  265 +
  266 + .info-row {
  267 + display: flex;
  268 + align-items: center;
  269 + color: rgba(0, 0, 0, 0.6);
  270 + font-size: 28rpx;
  271 + margin-bottom: 24rpx;
  272 +
  273 + &:last-child {
  274 + margin-bottom: 0;
  275 + }
  276 +
  277 + text {
  278 + width: 60%;
  279 + line-height: 32rpx;
  280 +
  281 + &:last-child {
  282 + color: rgba(0, 0, 0, 0.9);
  283 + width: 40%;
  284 + }
  285 + }
  286 + }
  287 +}
  288 +
  289 +.filter-form {
  290 + .form-item {
  291 + margin-bottom: 24rpx;
  292 + }
  293 +
  294 + .label {
  295 + margin-bottom: 20rpx;
  296 + color: rgba(0, 0, 0, 0.9);
  297 + height: 44rpx;
  298 + line-height: 44rpx;
  299 + font-size: 30rpx;
  300 + }
  301 +
  302 + .uni-easyinput {
  303 + border: 1rpx solid #f3f3f3;
  304 + }
  305 +
  306 +}
  307 +
  308 +/* 深度覆盖 uni-data-checkbox(mode=tag)内部的 tag 展示与间距 */
  309 +::v-deep .filter-form .uni-data-checklist .checklist-group {
  310 + .checklist-box {
  311 + &.is--tag {
  312 + width: 212rpx;
  313 + margin-top: 0;
  314 + margin-bottom: 24rpx;
  315 + margin-right: 24rpx;
  316 + height: 80rpx;
  317 + padding: 0;
  318 + border-radius: 12rpx;
  319 + background-color: #f3f3f3;
  320 + border-color: #f3f3f3;
  321 +
  322 + &:nth-child(3n) {
  323 + margin-right: 0;
  324 + }
  325 +
  326 + .checklist-content {
  327 + display: flex;
  328 + justify-content: center;
  329 + }
  330 +
  331 + .checklist-text {
  332 + color: rgba(0, 0, 0, 0.9);
  333 + font-size: 28rpx;
  334 + }
  335 + }
  336 +
  337 + &.is-checked {
  338 + background-color: $theme-primary-plain-bg !important;
  339 + border-color: $theme-primary-plain-bg !important;
  340 +
  341 + .checklist-text {
  342 + color: $theme-primary !important;
  343 + }
  344 + }
  345 + }
  346 +
  347 +}
  348 +</style>
... ...
... ... @@ -37,14 +37,15 @@
37 37
38 38 <uni-list-item title="交货方式">
39 39 <template v-slot:footer>
40   - <uni-easyinput v-model="form.deliveryMethod" placeholder="请输入交货方式" :inputBorder="false" />
  40 + <view class="readonly-text">{{ form.deliveryMethod }}</view>
41 41 </template>
42 42 </uni-list-item>
43 43 </view>
44 44
45 45 <!-- 产品 -->
46 46 <view class="section2">
47   - <Product mode="add" :list="initPurchaseOrderLineList" @change="purchaseOrderLineListChange" />
  47 + <Product mode="add" :list="initPurchaseOrderLineList" @change="purchaseOrderLineListChange"
  48 + :orderDate="form.orderDate" />
48 49 </view>
49 50
50 51 <view class="section">
... ... @@ -69,17 +70,6 @@
69 70 </view>
70 71 </template>
71 72 </uni-list-item>
72   - <uni-list-item class="amount-item">
73   - <template v-slot:body>
74   - <view class="item-title"><text>包装费</text></view>
75   - </template>
76   - <template v-slot:footer>
77   - <view class="amount-row">
78   - <uni-easyinput type="number" v-model="form.packagingFee" placeholder="0.00" :inputBorder="false" />
79   - <text class="unit">元</text>
80   - </view>
81   - </template>
82   - </uni-list-item>
83 73 <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
84 74 @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
85 75 <template v-slot:body>
... ... @@ -170,18 +160,18 @@
170 160
171 161 <!-- 产品 -->
172 162 <view class="mgb10">
173   - <Product mode="view" :list="form.purchaseOrderLineList"
174   - :totalQuantity="form.totalQuantity || 0" />
  163 + <Product mode="view" :list="form.purchaseOrderLineList" :totalQuantity="form.totalQuantity || 0" />
175 164 </view>
176 165
177 166 <view class="section">
178 167 <view class="row"><text class="label">价格表编号</text><text class="value">{{ form.priceListNo }}</text></view>
179 168 <view class="row"><text class="label">开票情况</text><text class="value">{{ form.invoicingStatus }}</text></view>
180 169 <view class="row"><text class="label">运费</text><text class="value">{{ form.shippingCost }}</text></view>
181   - <view class="row"><text class="label">包装费</text><text class="value">{{ form.packagingFee }}</text></view>
182 170 <view class="row"><text class="label">执行标准</text><text class="value">{{ getDicName('APPLICABLE_STANDARD',
183 171 form.executionStandard, dicOptions.APPLICABLE_STANDARD) }}</text></view>
184   - <view v-if="form.executionStandard === 'OTHER'" class="row"><text class="label">标准</text><text class="value">{{ form.executionStandardRemarks }}</text></view>
  172 + <view v-if="form.executionStandard === 'OTHER'" class="row"><text class="label">标准</text><text
  173 + class="value">{{
  174 + form.executionStandardRemarks }}</text></view>
185 175 </view>
186 176
187 177 <view class="title-header">
... ... @@ -198,7 +188,15 @@
198 188 <view class="row"><text class="label">包装</text><text class="value">{{ form.packaging }}</text></view>
199 189 <view class="row"><text class="label">备注</text><text class="value">{{ form.remarks }}</text></view>
200 190 </view>
201   -
  191 + <!-- 品质科 可填写(不是办事处内勤) -->
  192 + <uni-list v-if="form.showProductionProcess" >
  193 + <uni-list-item title="生产工艺">
  194 + <template v-slot:footer>
  195 + <uni-easyinput type="textarea" v-model="form.productionProcess" placeholder="请输入生产工艺"
  196 + :inputBorder="false" />
  197 + </template>
  198 + </uni-list-item>
  199 + </uni-list>
202 200 </view>
203 201 </scroll-view>
204 202
... ... @@ -411,7 +409,7 @@ export default {
411 409
412 410 &__container {
413 411 padding: 32rpx;
414   - align-items: center;
  412 + align-items: start !important;
415 413
416 414 .uni-easyinput {
417 415
... ...
... ... @@ -13,7 +13,8 @@
13 13 </view>
14 14 <view class="row"><text class="label">订货日期</text><text class="value">{{ form.orderDate }}</text></view>
15 15 <view class="row"><text class="label">生产厂</text><text class="value">{{ form.workshopName }}</text></view>
16   - <view class="row"><text class="label">结算方式或期限</text><text class="value">{{ form.settlementTerms }}</text></view>
  16 + <view class="row"><text class="label">结算方式或期限</text><text class="value">{{ form.settlementTerms }}</text>
  17 + </view>
17 18 <view class="row"><text class="label">交货方式</text><text class="value">{{ form.deliveryMethod }}</text></view>
18 19 </view>
19 20
... ... @@ -21,29 +22,33 @@
21 22 <view class="mgb10">
22 23 <Product mode="view" :list="form.purchaseOrderLineList" :totalQuantity="form.totalQuantity || 0" />
23 24 </view>
24   -
  25 +
25 26 <view class="section">
26 27 <view class="row"><text class="label">价格表编号</text><text class="value">{{ form.priceListNo }}</text></view>
27 28 <view class="row"><text class="label">开票情况</text><text class="value">{{ form.invoicingStatus }}</text></view>
28 29 <view class="row"><text class="label">运费</text><text class="value">{{ form.shippingCost }}</text></view>
29   - <view class="row"><text class="label">包装费</text><text class="value">{{ form.packagingFee }}</text></view>
30 30 <view class="row"><text class="label">执行标准</text><text class="value">{{ getDicName('APPLICABLE_STANDARD',
31 31 form.executionStandard, dicOptions.APPLICABLE_STANDARD) }}</text></view>
32   - <view v-if="form.executionStandard === 'OTHER'" class="row"><text class="label">标准</text><text class="value">{{ form.executionStandardRemarks }}</text></view>
  32 + <view v-if="form.executionStandard === 'OTHER'" class="row"><text class="label">标准</text><text
  33 + class="value">{{ form.executionStandardRemarks }}</text></view>
33 34 </view>
34   -
  35 +
35 36 <view class="title-header">
36 37 <image class="title-header_icon" src="/static/images/title.png" />
37 38 <span>具体质量要求</span>
38 39 </view>
39 40 <view class="section">
40   - <view class="row"><text class="label">件重条头</text><text class="value">{{ form.pieceWeightHeader }}</text></view>
  41 + <view class="row"><text class="label">件重条头</text><text class="value">{{ form.pieceWeightHeader }}</text>
  42 + </view>
41 43 <view class="row"><text class="label">表面</text><text class="value">{{ form.surface }}</text></view>
42 44 <view class="row"><text class="label">公差</text><text class="value">{{ form.tolerance }}</text></view>
43 45 <view class="row"><text class="label">性能</text><text class="value">{{ form.performance }}</text></view>
44 46 <view class="row"><text class="label">成分</text><text class="value">{{ form.element }}</text></view>
45 47 <view class="row"><text class="label">包装</text><text class="value">{{ form.packaging }}</text></view>
46 48 <view class="row"><text class="label">备注</text><text class="value">{{ form.remarks }}</text></view>
  49 + <!-- 品质科 可查看 -->
  50 + <view v-if="form.showProductionProcess" class="row"><text class="label">生产工艺</text><text class="value">{{
  51 + form.productionProcess }}</text></view>
47 52 </view>
48 53
49 54 </view>
... ... @@ -53,7 +58,7 @@
53 58 </template>
54 59
55 60 <script>
56   -import { getDetailApi, cancelApi } from '@/api/order_list.js'
  61 +import { getDetailApi, cancelApi, checkApi } from '@/api/order_list.js'
57 62 import Product from './product.vue'
58 63 import DetailButtons from '@/components/detail-buttons/index.vue'
59 64 import {
... ... @@ -100,11 +105,11 @@ export default {
100 105 const f = this.statusFlags;
101 106 console.log('displayButtons__f', f)
102 107 return [
103   - { ...this.buttons[0], visible: f.isRefuse && f.contractCreateBy },
104   - { ...this.buttons[1], visible: true },
105   - { ...this.buttons[2], visible: f.isAudit && f.canExamine },
106   - { ...this.buttons[3], visible: f.canDeliveryApply },
107   - { ...this.buttons[4], visible: f.isRefuse && f.contractCreateBy },
  108 + { ...this.buttons[0], visible: f.isRefuse && f.contractCreateBy && this.$auth.hasPermi('order-manage:order-list:modify') },
  109 + { ...this.buttons[1], visible: this.$auth.hasPermi('order-manage:order-list:review') },
  110 + { ...this.buttons[2], visible: f.isAudit && f.canExamine && this.$auth.hasPermi('order-manage:order-list:approve') },
  111 + { ...this.buttons[3], visible: f.canDeliveryApply && this.$auth.hasPermi('order-manage:order-list:apply') },
  112 + { ...this.buttons[4], visible: f.isRefuse && f.contractCreateBy && this.$auth.hasPermi('order-manage:order-list:cancel') },
108 113 ]
109 114 }
110 115 },
... ... @@ -157,8 +162,16 @@ export default {
157 162 },
158 163 onShipmentApply() {
159 164 const id = this.getBusinessId()
160   - const query = id ? ('?id=' + encodeURIComponent(id)) : ''
161   - uni.navigateTo({ url: '/pages/order_list/shipment_apply' + query })
  165 + const query = id ? ('?id=' + encodeURIComponent(id)) : '';
  166 + checkApi({ id }).then(res => {
  167 + if (res.code === 200) {
  168 + uni.navigateTo({ url: '/pages/order_list/shipment_apply' + query })
  169 + } else {
  170 + uni.showToast({ title: res.msg || '失败', icon: 'none' })
  171 + }
  172 + }).catch((e) => {
  173 + uni.showToast({ title: e.msg, icon: 'none' })
  174 + })
162 175 },
163 176 onCancel() {
164 177 const id = this.getBusinessId()
... ...
... ... @@ -23,9 +23,11 @@
23 23 <view class="card-header">
24 24 <text class="title omit2">{{ item.orderingUnitName }}</text>
25 25 <text v-if="item.status" :class="['status', `status_${item.status}`]">{{ filterStatus(item.status)
26   - }}</text>
  26 + }}</text>
27 27 </view>
28 28 <view class="info-row"><text>订单编号</text><text>{{ item.orderNo }}</text></view>
  29 + <view class="info-row"><text>审核状态</text><text><span :class="['status', `status_${item.examineStatus}`]">{{
  30 + filterExamineStatus(item.examineStatus) }}</span></text></view>
29 31 <view class="info-row"><text>生产厂</text><text>{{ item.workshopName }}</text></view>
30 32 <view class="info-row"><text>办事处</text><text>{{ item.deptName }}</text></view>
31 33 <view class="info-row"><text>订货日期</text><text>{{ item.orderDate }}</text></view>
... ... @@ -40,7 +42,8 @@
40 42 <view class="filter-form">
41 43 <view class="form-item">
42 44 <view class="label">办事处</view>
43   - <uni-easyinput v-model="model.deptName" placeholder="请输入办事处" :inputBorder="false" />
  45 + <uni-easyinput v-model="model.deptName" placeholder="请输入办事处" :inputBorder="false"
  46 + placeholderStyle="font-size:14px" />
44 47 </view>
45 48
46 49 <view class="form-item">
... ... @@ -56,6 +59,12 @@
56 59 </view>
57 60
58 61 <view class="form-item">
  62 + <view class="label">审核状态</view>
  63 + <uni-data-checkbox mode="tag" :multiple="false" :value-field="'value'" :text-field="'text'"
  64 + v-model="model.examineStatus" @change="onExamineStatusChange" :localdata="examineStatusOptions" />
  65 + </view>
  66 +
  67 + <view class="form-item">
59 68 <view class="label">订货日期</view>
60 69 <uni-datetime-picker type="daterange" v-model="model.dateRange" start="2023-01-01" />
61 70 </view>
... ... @@ -93,6 +102,7 @@ export default {
93 102 },
94 103 workshopOptions: [],
95 104 statusOptions: [],
  105 + examineStatusOptions: [],
96 106 query: {},
97 107 extraParams: {},
98 108 currentItems: []
... ... @@ -105,6 +115,7 @@ export default {
105 115 ]
106 116 this.extraParams = { type: this.tabValue }
107 117 this.loadStatusOptions()
  118 + this.loadExamineStatusOptions()
108 119 this.loadWorkshopOptions()
109 120 },
110 121 onReachBottom() {
... ... @@ -118,11 +129,19 @@ export default {
118 129 const res = await getDicByCodeApi('ORDER_STATUS')
119 130 const list = res.data || []
120 131 this.statusOptions = list.map(it => ({ text: it.name || '', value: it.code || '' }));
121   - console.log('this.statusOptions', this.statusOptions)
122 132 } catch (e) {
123 133 this.statusOptions = []
124 134 }
125 135 },
  136 + async loadExamineStatusOptions() {
  137 + try {
  138 + const res = await getDicByCodeApi('AUDIT_STATUS')
  139 + const list = res.data || []
  140 + this.examineStatusOptions = list.map(it => ({ text: it.name || '', value: it.code || '' }));
  141 + } catch (e) {
  142 + this.examineStatusOptions = []
  143 + }
  144 + },
126 145 async loadWorkshopOptions() {
127 146 try {
128 147 const res = await workshopQueryApi({ pageIndex: 1, pageSize: 9999 })
... ... @@ -179,6 +198,10 @@ export default {
179 198 const raw = e && e.detail && e.detail.value !== undefined ? e.detail.value : (e && e.value !== undefined ? e.value : '')
180 199 this.filterForm.status = raw
181 200 },
  201 + onExamineStatusChange(e) {
  202 + const raw = e && e.detail && e.detail.value !== undefined ? e.detail.value : (e && e.value !== undefined ? e.value : '')
  203 + this.filterForm.examineStatus = raw
  204 + },
182 205 onWorkshopChange(e) {
183 206 const raw = e && e.detail && e.detail.value !== undefined ? e.detail.value : (e && e.value !== undefined ? e.value : '')
184 207 this.filterForm.workshopId = raw
... ... @@ -201,13 +224,8 @@ export default {
201 224 let records = _data.datas || _data.list || _data.records || []
202 225 const totalCount = _data.totalCount || _data.count || 0
203 226 const hasNext = _data.hasNext || false
204   - const statusTextMap = (this.statusOptions || []).reduce((acc, it) => {
205   - acc[String(it.value)] = it.text
206   - return acc
207   - }, {})
208 227 records = records.map(it => ({
209   - ...it,
210   - statusName: statusTextMap[String(it.status)] || ''
  228 + ...it
211 229 }))
212 230 return { records, totalCount, hasNext }
213 231 }).catch(() => {
... ... @@ -218,6 +236,9 @@ export default {
218 236 filterStatus(status) {
219 237 return this.statusOptions.filter(item => item.value === status)[0].text || '';
220 238 },
  239 + filterExamineStatus(status) {
  240 + return this.examineStatusOptions.filter(item => item.value === status)[0].text || '';
  241 + },
221 242 onCardClick(item) {
222 243 const id = (item && (item.id || item.code)) || ''
223 244 if (!id) return
... ... @@ -383,6 +404,41 @@ export default {
383 404 &:last-child {
384 405 color: rgba(0, 0, 0, 0.9);
385 406 }
  407 +
  408 + .status {
  409 + display: inline-block;
  410 + padding: 4rpx 12rpx;
  411 + border-radius: 6rpx;
  412 + font-size: 24rpx;
  413 + color: #fff;
  414 + line-height: 40rpx;
  415 +
  416 + // 审核中
  417 + &.status_AUDIT {
  418 + background: rgb(242, 243, 255);
  419 + color: $theme-primary;
  420 +
  421 + }
  422 +
  423 + // 审核通过
  424 + &.status_PASS {
  425 + color: rgb(43, 164, 113);
  426 + background-color: rgb(227, 249, 233);
  427 + }
  428 +
  429 + // 已驳回
  430 + &.status_REFUSE {
  431 + color: rgb(213, 73, 65);
  432 + background-color: rgb(255, 240, 237);
  433 + }
  434 +
  435 + // 已取消
  436 + &.status_CANCEL {
  437 + background: #e7e7e7;
  438 + color: rgba(0, 0, 0, 0.6);
  439 + }
  440 + }
  441 +
386 442 }
387 443 }
388 444
... ...
... ... @@ -36,14 +36,14 @@
36 36
37 37 <uni-list-item title="交货方式">
38 38 <template v-slot:footer>
39   - <uni-easyinput v-model="form.deliveryMethod" placeholder="请输入交货方式" :inputBorder="false" />
  39 + <view class="readonly-text">{{ form.deliveryMethod }}</view>
40 40 </template>
41 41 </uni-list-item>
42 42 </view>
43 43
44 44 <!-- 产品 -->
45 45 <view class="section2">
46   - <Product mode="add" :list="initPurchaseOrderLineList" @change="purchaseOrderLineListChange" />
  46 + <Product mode="add" :list="initPurchaseOrderLineList" @change="purchaseOrderLineListChange" :pageType="'modify'" :orderDate="form.orderDate" />
47 47 </view>
48 48
49 49 <view class="section">
... ... @@ -68,17 +68,6 @@
68 68 </view>
69 69 </template>
70 70 </uni-list-item>
71   - <uni-list-item class="amount-item">
72   - <template v-slot:body>
73   - <view class="item-title"><text>包装费</text></view>
74   - </template>
75   - <template v-slot:footer>
76   - <view class="amount-row">
77   - <uni-easyinput type="number" v-model="form.packagingFee" placeholder="0.00" :inputBorder="false" />
78   - <text class="unit">元</text>
79   - </view>
80   - </template>
81   - </uni-list-item>
82 71 <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
83 72 @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
84 73 <template v-slot:body>
... ... @@ -276,6 +265,7 @@ export default {
276 265 }
277 266 },
278 267 purchaseOrderLineListChange(data) {
  268 + console.log('purchaseOrderLineListChange__data', data)
279 269 const list = Array.isArray(data) ? data : []
280 270 this.form.purchaseOrderLineList = list;
281 271 },
... ...
... ... @@ -52,17 +52,32 @@
52 52 <view class="row" :class="{ 'noneStyle': item.showSalesPrice }" v-if="item.showSalesPrice"><text
53 53 class="label">销售价格</text><text class="value">{{
54 54 item.salesPrice }}</text></view>
55   -
56 55 <uni-list class="edit-list">
  56 + <uni-list-item class="amount-item">
  57 + <template v-slot:body>
  58 + <view class="item-title"><text>包装费</text></view>
  59 + </template>
  60 + <template v-slot:footer>
  61 + <view class="amount-row">
  62 + <uni-easyinput type="digit" v-model="item.packagingFee" placeholder="0.00"
  63 + :inputBorder="false"
  64 + @input="onNonNegativeNumberInput($event, item, idx, 'packagingFee')"
  65 + @blur="onNonNegativeNumberBlur(item, idx, 'packagingFee')" />
  66 + <text class="unit">元</text>
  67 + </view>
  68 + </template>
  69 + </uni-list-item>
57 70 <uni-list-item title="发货日期">
58 71 <template v-slot:footer>
59   - <uni-datetime-picker type="date" v-model="item.deliveryDate" />
  72 + <uni-datetime-picker type="date" v-model="item.deliveryDate" :start="minDeliveryDate"
  73 + @change="onDeliveryChange($event, item, idx)" />
60 74 </template>
61 75 </uni-list-item>
62 76 <uni-list-item title="考核超协">
63 77 <template v-slot:footer>
64   - <uni-easyinput v-model="item.assessmentExceedsAgreement" placeholder="请输入考核超协"
65   - :inputBorder="false" />
  78 + <uni-easyinput :disabled="pageType === 'modify'"
  79 + v-model="item.assessmentExceedsAgreement"
  80 + :placeholder="pageType === 'modify' ? '' : '请输入考核超协'" :inputBorder="false" />
66 81 </template>
67 82 </uni-list-item>
68 83 </uni-list>
... ... @@ -112,10 +127,12 @@
112 127 <!-- showSalesPrice 判断是否显示 -->
113 128 <view class="row" v-if="item.showSalesPrice"><text class="label">销售价格</text><text class="value">{{
114 129 item.salesPrice }}</text></view>
  130 + <view class="row"><text class="label">包装费</text><text class="value">{{
  131 + item.packagingFee }}</text></view>
115 132 <view class="row"><text class="label">发货日期</text><text class="value">{{ item.deliveryDate }}</text>
116 133 </view>
117 134 <view class="row"><text class="label">考核超协</text><text class="value">{{ item.assessmentExceedsAgreement
118   - }}</text></view>
  135 + }}</text></view>
119 136 </view>
120 137 <view class="view-total">
121 138 <view class="head">合计</view>
... ... @@ -136,7 +153,9 @@ export default {
136 153 mode: { type: String, default: 'add' },
137 154 list: { type: Array, default: () => [] },
138 155 max: { type: Number, default: 8 },
139   - totalQuantity: { type: Number, default: 0 }
  156 + totalQuantity: { type: Number, default: 0 },
  157 + pageType: { type: String, default: '' },
  158 + orderDate: { type: String, default: '' }
140 159 },
141 160 data() {
142 161 return {
... ... @@ -145,6 +164,21 @@ export default {
145 164 }
146 165 },
147 166 computed: {
  167 + minDeliveryDate() {
  168 + const s = this.orderDate
  169 + if (!s) return ''
  170 + const parts = String(s).split('-')
  171 + const y = Number(parts[0])
  172 + const m = Number(parts[1])
  173 + const d = Number(parts[2])
  174 + if (!y || !m || !d) return ''
  175 + const dt = new Date(y, m - 1, d)
  176 + dt.setDate(dt.getDate() + 1)
  177 + const yy = dt.getFullYear()
  178 + const mm = String(dt.getMonth() + 1).padStart(2, '0')
  179 + const dd = String(dt.getDate()).padStart(2, '0')
  180 + return `${yy}/${mm}/${dd}`
  181 + }
148 182 },
149 183 watch: {
150 184 items: {
... ... @@ -168,7 +202,7 @@ export default {
168 202 },
169 203 methods: {
170 204 defaultItem() {
171   - return { collapsed: false }
  205 + return { collapsed: false, packagingFee: '' }
172 206 },
173 207 toggleItem(idx) {
174 208 const it = this.items[idx]
... ... @@ -177,13 +211,58 @@ export default {
177 211 this.$set(this.items, idx, it)
178 212 },
179 213 emitChange() {
180   - const out = this.items.map(it => ({ ...it }))
  214 + console.log('emitChange__items', this.items)
  215 + const out = this.items.map(it => JSON.parse(JSON.stringify(it)))
  216 + console.log('emitChange__out', out)
181 217 this.$emit('input', out)
182 218 this.$emit('update:value', out)
183 219 this.$emit('change', out)
184 220 },
185 221 toggleViewCollapse() {
186 222 this.collapsedView = !this.collapsedView
  223 + },
  224 + onDeliveryChange(e, item, idx) {
  225 + const getStr = (x) => {
  226 + if (x && x.detail && x.detail.value !== undefined) return x.detail.value
  227 + if (typeof x === 'string') return x
  228 + return item && item.deliveryDate ? item.deliveryDate : ''
  229 + }
  230 + const val = getStr(e)
  231 + if (!val || !this.orderDate) return
  232 + const parse = (s) => {
  233 + const p = String(s).replace(/\//g, '-').split('-')
  234 + const y = Number(p[0])
  235 + const m = Number(p[1])
  236 + const d = Number(p[2])
  237 + return new Date(y, m - 1, d)
  238 + }
  239 + const sel = parse(val)
  240 + const ord = parse(this.orderDate)
  241 + if (!(sel > ord)) {
  242 + item.deliveryDate = ''
  243 + this.$set(this.items, idx, { ...item })
  244 + uni.showToast({ title: '发货日期必须大于订货日期', icon: 'none' })
  245 + }
  246 + },
  247 + onNonNegativeNumberInput(val, item, idx, field) {
  248 + let v = String(val != null ? val : (item && item[field]) || '')
  249 + v = v.replace(/[^0-9.]/g, '')
  250 + v = v.replace(/(\..*)\./g, '$1')
  251 + if (v.startsWith('.')) v = '0' + v
  252 + if (v === '') { item[field] = ''; if (typeof idx === 'number') this.$set(this.items, idx, { ...item }); return }
  253 + const num = Number(v)
  254 + if (isNaN(num) || num < 0) {
  255 + item[field] = '0'
  256 + } else {
  257 + item[field] = v
  258 + }
  259 + if (typeof idx === 'number') this.$set(this.items, idx, { ...item })
  260 + },
  261 + onNonNegativeNumberBlur(item, idx, field) {
  262 + const v = String((item && item[field]) || '')
  263 + const num = Number(v)
  264 + if (isNaN(num) || num < 0) item[field] = '0'
  265 + if (typeof idx === 'number') this.$set(this.items, idx, { ...item })
187 266 }
188 267 }
189 268 }
... ...
... ... @@ -24,7 +24,6 @@
24 24 <view class="row"><text class="label">价格表编号</text><text class="value">{{ form.priceListNo }}</text></view>
25 25 <view class="row"><text class="label">开票情况</text><text class="value">{{ form.invoicingStatus }}</text></view>
26 26 <view class="row"><text class="label">运费</text><text class="value">{{ form.shippingCost }}</text></view>
27   - <view class="row"><text class="label">包装费</text><text class="value">{{ form.packagingFee }}</text></view>
28 27 <view class="row"><text class="label">执行标准</text><text class="value">{{ getDicName('APPLICABLE_STANDARD',
29 28 form.executionStandard, dicOptions.APPLICABLE_STANDARD) }}</text></view>
30 29 <view v-if="form.executionStandard === 'OTHER'" class="row"><text class="label">标准</text><text class="value">{{ form.executionStandardRemarks }}</text></view>
... ... @@ -42,6 +41,8 @@
42 41 <view class="row"><text class="label">成分</text><text class="value">{{ form.element }}</text></view>
43 42 <view class="row"><text class="label">包装</text><text class="value">{{ form.packaging }}</text></view>
44 43 <view class="row"><text class="label">备注</text><text class="value">{{ form.remarks }}</text></view>
  44 + <!-- 品质科 可查看 -->
  45 + <view v-if="form.showProductionProcess" class="row"><text class="label">生产工艺</text><text class="value">{{ form.productionProcess }}</text></view>
45 46 </view>
46 47
47 48 </view>
... ...
... ... @@ -64,10 +64,10 @@ export default {
64 64 displayButtons() {
65 65 const f = this.statusFlags
66 66 return [
67   - { ...this.buttons[0], visible: f.canEdit },
68   - { ...this.buttons[1], visible: true },
69   - { ...this.buttons[2], visible: f.canAudit },
70   - { ...this.buttons[3], visible: f.canCancel },
  67 + { ...this.buttons[0], visible: f.canEdit && this.$auth.hasPermi('order-manage:revoke-list:modify') },
  68 + { ...this.buttons[1], visible: this.$auth.hasPermi('order-manage:revoke-list:review') },
  69 + { ...this.buttons[2], visible: f.canAudit && this.$auth.hasPermi('order-manage:revoke-list:approve') },
  70 + { ...this.buttons[3], visible: f.canCancel && this.$auth.hasPermi('order-manage:revoke-list:cancel') },
71 71 ]
72 72 }
73 73 },
... ...
... ... @@ -5,7 +5,7 @@
5 5 <uni-search-bar v-model="searchKeyword" radius="6" placeholder="请输入订货单位或订单编号" clearButton="auto"
6 6 cancelButton="none" bgColor="#F3F3F3" textColor="rgba(0,0,0,0.4)" @confirm="onSearchConfirm"
7 7 @input="onSearchInput" />
8   - <image class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
  8 + <image v-if="$auth.hasPermi('order-manage:revoke-list:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
9 9 <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
10 10 </view>
11 11 </view>
... ...
... ... @@ -2,9 +2,12 @@ import store from '@/store'
2 2
3 3 function authPermission(permission) {
4 4 const all_permission = "*:*:*"
5   - const permissions = store.getters && store.getters.permissions
  5 + const g = store.getters || {}
  6 + const permissions = Array.isArray(g.permissions) ? g.permissions : []
  7 + const roles = Array.isArray(g.roles) ? g.roles : []
  8 + const sources = [...permissions, ...roles]
6 9 if (permission && permission.length > 0) {
7   - return permissions.some(v => {
  10 + return sources.some(v => {
8 11 return all_permission === v || v === permission
9 12 })
10 13 } else {
... ...
... ... @@ -845,6 +845,16 @@
845 845 display: flex;
846 846 align-items: center;
847 847 position: relative;
  848 + border: none;
  849 + }
  850 +
  851 + .uni-date-editor--x .uni-date-range {
  852 + border: 1px solid #e5e5e5;
  853 + padding-right: 80rpx;
  854 + }
  855 +
  856 + .uni-date-editor--x .uniui-calendar {
  857 + display: none;
848 858 }
849 859
850 860 .uni-date-editor--x .uni-date__icon-clear {
... ... @@ -854,6 +864,8 @@
854 864 /* #ifdef H5 */
855 865 cursor: pointer;
856 866 /* #endif */
  867 + position: relative;
  868 + left: -60rpx;
857 869 }
858 870
859 871 .uni-date__x-input {
... ... @@ -865,8 +877,9 @@
865 877 position: relative;
866 878 flex: 1;
867 879 line-height: 35px;
868   - font-size: 14px;
  880 + font-size: 16px;
869 881 overflow: hidden;
  882 + color: rgba(0, 0, 0, 0.4);
870 883 }
871 884
872 885 .text-center {
... ...