Commit 7dd1bc0ed69efd3f11a4d4b3c5e507041ea1439e

Authored by gesilong
1 parent 2a7bf4f7

commit: 数量拆分

... ... @@ -207,6 +207,16 @@ export function priceLock(data) {
207 207 region
208 208 })
209 209 }
  210 +//拆分数量
  211 +export function splitQuantityLock(data) {
  212 + return request({
  213 + url: `${baseUrl}/contractDistributorStandard/split`,
  214 + method: 'post',
  215 + data,
  216 + contentType: ContentTypeEnum.JSON,
  217 + region
  218 + })
  219 +}
210 220
211 221 // 删除合同
212 222 export function deleteContractApi(id) {
... ...
... ... @@ -4,9 +4,9 @@ module.exports = {
4 4 themeColor: '#3d48a3',
5 5
6 6 // baseUrl: 'http://ft.wecando21cn.com/api',
7   - baseUrl: 'http://gjtd.ahcjxc.com:81/api',
8   - // baseUrl: 'http://erp.qgutech.com//api',
9   - // baseUrl: 'http://127.0.0.1:8085',
  7 + // baseUrl: 'http://gjtd.ahcjxc.com:81/api',
  8 + baseUrl: 'http://erp.qgutech.com/api',
  9 + // baseUrl: 'http://10.9.5.246:8081',
10 10 // 应用信息
11 11 appInfo: {
12 12 // 应用名称
... ...
... ... @@ -428,6 +428,14 @@
428 428 }
429 429 },
430 430 {
  431 + "path": "pages/contract_stock/split",
  432 + "style": {
  433 + "navigationBarTitleText": "拆分",
  434 + "navigationBarBackgroundColor": "#ffffff",
  435 + "navigationBarTextStyle": "black"
  436 + }
  437 + },
  438 + {
431 439 "path": "pages/contract_unplan/index",
432 440 "style": {
433 441 "navigationBarTitleText": "经销未锁规合同",
... ... @@ -612,6 +620,14 @@
612 620 }
613 621 },
614 622 {
  623 + "path": "pages/contract_foreign_stock/split",
  624 + "style": {
  625 + "navigationBarTitleText": "拆分",
  626 + "navigationBarBackgroundColor": "#ffffff",
  627 + "navigationBarTextStyle": "black"
  628 + }
  629 + },
  630 + {
615 631 "path": "pages/contract_foreign_unplan/index",
616 632 "style": {
617 633 "navigationBarTitleText": "外贸未锁规合同",
... ...
... ... @@ -291,6 +291,12 @@ export default {
291 291 variant: 'outline',
292 292 event: 'print'
293 293 },
  294 + {
  295 + text: '拆分',
  296 + visible: true,
  297 + variant: 'outline',
  298 + event: 'split'
  299 + },
294 300 ],
295 301 }
296 302 },
... ... @@ -302,6 +308,7 @@ export default {
302 308 const a = this.detail.standardApproved || false
303 309 const e = this.detail.showExamine || false
304 310 const f = this.detail.standardShowExamine || false
  311 + const g = this.detail.canSplit || false
305 312 return [
306 313 { ...this.buttons[0], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:modify')) }, //编辑
307 314 { ...this.buttons[1], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:delete')) }, //删除
... ... @@ -318,6 +325,7 @@ export default {
318 325 { ...this.buttons[8], visible: (s === 'STANDARD' && f && a === 'AUDIT' && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:standard-approve')) },
319 326 { ...this.buttons[13], visible: (s !== 'DELETED' && this.$auth.hasPermi('contract-manage:foreign-trade-inventory-contract:copy')) },
320 327 { ...this.buttons[14], visible: true },
  328 + { ...this.buttons[15], visible: g },
321 329 ]
322 330 }
323 331 },
... ... @@ -474,6 +482,12 @@ export default {
474 482 if (e === 'uploadSeal') return this.uploadContract(this.detail.id || '', 'seal')
475 483 if (e === 'copy') return this.onCopy(btn && btn.params)
476 484 if (e === 'print') return this.onPrint(this.detail.id || '')
  485 + if (e === 'split') return this.onSplit(this.detail.id || '')
  486 + },
  487 + onSplit(id) {
  488 + uni.navigateTo({
  489 + url: '/pages/contract_foreign_stock/split?id=' + id
  490 + })
477 491 },
478 492 onPrint(id) {
479 493 printFile(id)
... ...
... ... @@ -90,11 +90,6 @@
90 90 placeholder="不可编辑" />
91 91 </template>
92 92 </uni-list-item>
93   - <uni-list-item title="本次锁价数量">
94   - <template v-slot:footer>
95   - <uni-easyinput v-model="item.currentQuantity" type="number" :inputBorder="false" placeholder="请输入本次锁价数量" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'currentQuantity', 3)" />
96   - </template>
97   - </uni-list-item>
98 93 <uni-list-item title="单价">
99 94 <template v-slot:footer>
100 95 <uni-easyinput v-model="item.unitPrice" type="digit" :inputBorder="false"
... ... @@ -260,7 +255,6 @@ export default {
260 255 lengthTolNeg: v.lengthTolNeg || '',
261 256 materialCode: v.materialCode || '',
262 257 status: v.status || '',
263   - currentQuantity: v.currentQuantity === 0 ? 0 : (v.currentQuantity || ''),
264 258 quantity: v.productQuantity || v.quantity || '',
265 259 unitPrice: v.unitPrice || '',
266 260 // amountExcludingTax: v.amountExcludingTax || 0,
... ... @@ -341,7 +335,6 @@ export default {
341 335 this.items = this.items.map((it, i) => ({
342 336 ...it,
343 337 quantity: '',
344   - currentQuantity: '',
345 338 unitPrice: '',
346 339 // amountExcludingTax: 0
347 340 }))
... ... @@ -351,12 +344,10 @@ export default {
351 344 const raw = { ...(it.raw || {}) }
352 345 const qty = this.toNumber(it.quantity)
353 346 const price = this.toNumber(it.unitPrice)
354   - const curQtyRaw = it.currentQuantity
355 347 const total = this.toNumber(it.totalAmount)
356 348 // const excl = this.toNumber(it.amountExcludingTax)
357 349 if (Object.prototype.hasOwnProperty.call(raw, 'productQuantity')) raw.productQuantity = qty
358 350 else raw.quantity = qty
359   - raw.currentQuantity = (curQtyRaw === '' || curQtyRaw === null || curQtyRaw === undefined) ? null : this.toNumber(curQtyRaw)
360 351 raw.unitPrice = price
361 352 raw.totalAmount = total
362 353 // raw.amountExcludingTax = excl
... ... @@ -374,14 +365,6 @@ export default {
374 365 uni.showToast({ title: '请填写单价', icon: 'none' })
375 366 return
376 367 }
377   - const invalidQty = selected.find(r => {
378   - const q = this.toNumber(r.currentQuantity)
379   - return !(q > 0)
380   - })
381   - if (invalidQty) {
382   - uni.showToast({ title: '请填写本次锁价数量', icon: 'none' })
383   - return
384   - }
385 368 this.selectedItems = selected
386 369 const payload = {
387 370 id: this.id,
... ...
  1 +<template>
  2 + <view class="page">
  3 + <scroll-view class="scroll" scroll-y>
  4 + <view class="lock-page">
  5 + <view class="block" v-for="(item, idx) in items" :key="idx">
  6 + <view class="block-header">
  7 + <uni-data-checkbox multiple mode="default" :localdata="[{ text: '拆分', value: 'LOCKED' }]"
  8 + :modelValue="item.locked ? ['LOCKED'] : []" :disabled="true"
  9 + @change="onLockChange(idx, $event)" />
  10 + <view class="ops" @click="toggleItem(idx)">
  11 + <image class="opIcon"
  12 + :src="item.collapsed ? '/static/images/up.png' : '/static/images/down.png'" />
  13 + <text class="opText">{{ item.collapsed ? '收起' : '展开' }}</text>
  14 + </view>
  15 + </view>
  16 +
  17 + <uni-list v-show="item.collapsed">
  18 + <uni-list-item title="产品名称">
  19 + <template v-slot:footer>
  20 + <uni-easyinput v-model="item.productName" placeholder="请输入产品名称" :clearable="false"
  21 + disabled />
  22 + </template>
  23 + </uni-list-item>
  24 + <uni-list-item title="行业">
  25 + <template v-slot:footer>
  26 + <uni-easyinput v-model="item.industry" placeholder="请输入行业" :clearable="false"
  27 + disabled />
  28 + </template>
  29 + </uni-list-item>
  30 + <uni-list-item title="牌号">
  31 + <template v-slot:footer>
  32 + <uni-easyinput v-model="item.brand" placeholder="请输入牌号" :clearable="false" disabled />
  33 + </template>
  34 + </uni-list-item>
  35 + <uni-list-item title="品质">
  36 + <template v-slot:footer>
  37 + <uni-easyinput v-model="item.quality" placeholder="请输入品质" :clearable="false" disabled />
  38 + </template>
  39 + </uni-list-item>
  40 + <uni-list-item title="规格(mm)">
  41 + <template v-slot:footer>
  42 + <view class="value value-spec">
  43 + <view v-if="item.thickness" class="value-spec_val">{{ item.thickness }}</view>
  44 + <view v-if="item.thickness" class="value-spec_box">
  45 + <view v-if="item.thicknessTolPos" class="value-spec_box_1">{{
  46 + item.thicknessTolPos > 0 ? '+' + item.thicknessTolPos : item.thicknessTolPos
  47 + }}
  48 + </view>
  49 + <view v-if="item.thicknessTolNeg" class="value-spec_box_2">{{
  50 + item.thicknessTolNeg > 0 ? '+' + item.thicknessTolNeg : item.thicknessTolNeg
  51 + }}
  52 + </view>
  53 + </view>
  54 + <view v-if="item.width" class="value-spec_val p12">*</view>
  55 + <view v-if="item.width" class="value-spec_val">{{ item.width }}</view>
  56 + <view v-if="item.width" class="value-spec_box">
  57 + <view v-if="item.widthTolPos" class="value-spec_box_1">{{ item.widthTolPos > 0 ?
  58 + '+' + item.widthTolPos : item.widthTolPos }}
  59 + </view>
  60 + <view v-if="item.widthTolNeg" class="value-spec_box_2">{{ item.widthTolNeg > 0 ?
  61 + '+' + item.widthTolNeg : item.widthTolNeg }}
  62 + </view>
  63 + </view>
  64 + <view v-if="item.length" class="value-spec_val p12">*</view>
  65 + <view v-if="item.length" class="value-spec_val">{{ item.length }}</view>
  66 + <view v-if="item.length" class="value-spec_box">
  67 + <view v-if="item.lengthTolPos" class="value-spec_box_1">{{ item.lengthTolPos > 0
  68 + ? '+' + item.lengthTolPos : item.lengthTolPos }}
  69 + </view>
  70 + <view v-if="item.lengthTolNeg" class="value-spec_box_2">{{ item.lengthTolNeg > 0
  71 + ? '+' + item.lengthTolNeg : item.lengthTolNeg }}
  72 + </view>
  73 + </view>
  74 + </view>
  75 + </template>
  76 + </uni-list-item>
  77 + <uni-list-item title="物料编码">
  78 + <template v-slot:footer>
  79 + <uni-easyinput v-model="item.materialCode" placeholder="请输入物料编码" :clearable="false" disabled />
  80 + </template>
  81 + </uni-list-item>
  82 + <uni-list-item title="状态">
  83 + <template v-slot:footer>
  84 + <uni-easyinput v-model="item.status" placeholder="请输入状态" :clearable="false" disabled />
  85 + </template>
  86 + </uni-list-item>
  87 + <uni-list-item title="数量">
  88 + <template v-slot:footer>
  89 + <uni-easyinput v-model="item.quantity" type="number" :inputBorder="false" disabled
  90 + placeholder="不可编辑" />
  91 + </template>
  92 + </uni-list-item>
  93 + <uni-list-item title="本次锁价数量">
  94 + <template v-slot:footer>
  95 + <uni-easyinput v-model="item.currentQuantity" type="number" :inputBorder="false" placeholder="请输入本次锁价数量" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'currentQuantity', 3)" />
  96 + </template>
  97 + </uni-list-item>
  98 + <uni-list-item title="单价">
  99 + <template v-slot:footer>
  100 + <uni-easyinput v-model="item.unitPrice" type="digit" :inputBorder="false" disabled
  101 + placeholder="不可编辑" @input="onImmediateChange(idx)"
  102 + @blur="onNumberBlur(idx, 'unitPrice', 0)" />
  103 + </template>
  104 + </uni-list-item>
  105 + <!-- <uni-list-item title="不含税金额">
  106 + <template v-slot:footer>
  107 + <uni-easyinput v-model="item.amountExcludingTax" type="number" :inputBorder="false"
  108 + disabled placeholder="" />
  109 + </template>
  110 + </uni-list-item> -->
  111 + <uni-list-item title="总金额">
  112 + <template v-slot:footer>
  113 + <uni-easyinput v-model="item.totalAmount" type="number" :inputBorder="false" disabled
  114 + placeholder="" />
  115 + </template>
  116 + </uni-list-item>
  117 + <uni-list-item title="发货日期">
  118 + <template v-slot:footer>
  119 + <uni-easyinput v-model="item.deliveryDate" :inputBorder="false" disabled />
  120 + </template>
  121 + </uni-list-item>
  122 + </uni-list>
  123 +
  124 + <uni-list v-show="!item.collapsed">
  125 + <uni-list-item title="产品名称">
  126 + <template v-slot:footer>
  127 + <uni-easyinput v-model="item.productName" placeholder="请输入产品名称" :clearable="false"
  128 + disabled />
  129 + </template>
  130 + </uni-list-item>
  131 + <uni-list-item title="行业">
  132 + <template v-slot:footer>
  133 + <uni-easyinput v-model="item.industry" placeholder="请输入行业" :clearable="false"
  134 + disabled />
  135 + </template>
  136 + </uni-list-item>
  137 + <uni-list-item title="牌号">
  138 + <template v-slot:footer>
  139 + <uni-easyinput v-model="item.brand" placeholder="请输入牌号" :clearable="false" disabled />
  140 + </template>
  141 + </uni-list-item>
  142 +
  143 + </uni-list>
  144 + </view>
  145 + <view class="footer">
  146 + <button class="btn submit" type="primary" @click="onSubmit">提交</button>
  147 + </view>
  148 + </view>
  149 + </scroll-view>
  150 +
  151 +
  152 + </view>
  153 +</template>
  154 +
  155 +<script>
  156 +import { getContractApi, splitQuantityLock } from '@/api/contract'
  157 +
  158 +export default {
  159 + name: 'ContractUnplanLock',
  160 + data() {
  161 + return {
  162 + id: '',
  163 + items: [],
  164 + planQty: 30,
  165 + }
  166 + },
  167 + onLoad(options) {
  168 + const id = options && options.id ? options.id : ''
  169 + this.id = id
  170 + this.loadDetail()
  171 + },
  172 + methods: {
  173 + onLockChange(idx, e) {
  174 + const it = this.items[idx]
  175 + if (!it) return
  176 + const arr = e && e.detail && e.detail.value ? e.detail.value : []
  177 + it.locked = Array.isArray(arr) && arr.length > 0
  178 + this.$set(this.items, idx, it)
  179 + },
  180 + async loadDetail() {
  181 + if (!this.id) return
  182 + try {
  183 + const res = await getContractApi(this.id)
  184 + const data = res && res.data ? res.data : {}
  185 + const lines = Array.isArray(data.contractDistributorLineList) ? data.contractDistributorLineList : []
  186 + const init = lines.map(v => ({
  187 + locked: true,
  188 + collapsed: true,
  189 + raw: v,
  190 + productName: v.rawProductName || v.productName || '',
  191 + industry: v.industry || '',
  192 + brand: v.rawProductGrade || v.brand || '',
  193 + quality: v.quality || '',
  194 + thickness: v.thickness || '',
  195 + thicknessTolPos: v.thicknessTolPos || '',
  196 + thicknessTolNeg: v.thicknessTolNeg || '',
  197 + width: v.width || '',
  198 + widthTolPos: v.widthTolPos || '',
  199 + widthTolNeg: v.widthTolNeg || '',
  200 + length: v.length || '',
  201 + lengthTolPos: v.lengthTolPos || '',
  202 + lengthTolNeg: v.lengthTolNeg || '',
  203 + materialCode: v.materialCode || '',
  204 + status: v.status || '',
  205 + currentQuantity: v.currentQuantity === 0 ? 0 : (v.currentQuantity || ''),
  206 + quantity: v.productQuantity || v.quantity || '',
  207 + unitPrice: v.unitPrice || '',
  208 + // amountExcludingTax: v.amountExcludingTax || 0,
  209 + totalAmount: v.totalAmount || 0,
  210 + deliveryDate: v.deliveryDate || '',
  211 + specDisplay: ''
  212 + }))
  213 + this.items = init.map(it => ({ ...it, specDisplay: this.specOf(it) }))
  214 + this.recalculateAll()
  215 + } catch (e) {
  216 + this.items = []
  217 + }
  218 + },
  219 + toggleItem(idx) {
  220 + const it = this.items[idx]
  221 + if (!it) return
  222 + it.collapsed = !it.collapsed
  223 + this.$set(this.items, idx, it)
  224 + },
  225 + onImmediateChange(idx) {
  226 + this.$nextTick(() => this.recalculate(idx))
  227 + },
  228 + onNumberBlur(idx, field, digits) {
  229 + const it = this.items[idx]
  230 + if (!it) return
  231 + const raw = it[field]
  232 + if (raw === '' || raw === null || raw === undefined) {
  233 + this.$set(this.items, idx, it)
  234 + this.recalculate(idx)
  235 + return
  236 + }
  237 + const num = this.toNumber(raw)
  238 + const rounded = this.round(num, digits)
  239 + it[field] = rounded
  240 + this.$set(this.items, idx, it)
  241 + this.recalculate(idx)
  242 + },
  243 + recalculate(idx) {
  244 + const TAX_RATE = 0.13
  245 + const it = this.items[idx]
  246 + if (!it) return
  247 + const qty = this.toNumber(it.quantity)
  248 + const price = this.toNumber(it.unitPrice)
  249 + const total = this.round(qty * price, 2)
  250 + // const excl = this.round(total / (1 + TAX_RATE), 2)
  251 + // it.amountExcludingTax = excl
  252 + it.totalAmount = total
  253 + this.$set(this.items, idx, it)
  254 + },
  255 + recalculateAll() {
  256 + for (let i = 0; i < this.items.length; i++) this.recalculate(i)
  257 + },
  258 + toNumber(val) {
  259 + if (typeof val === 'number') return isNaN(val) ? 0 : val
  260 + const n = parseFloat(String(val).replace(/[^0-9.\-]/g, ''))
  261 + return isNaN(n) ? 0 : n
  262 + },
  263 + round(val, digits = 2) {
  264 + const n = Number(val)
  265 + if (isNaN(n)) return 0
  266 + const m = Math.pow(10, digits)
  267 + return Math.round(n * m) / m
  268 + },
  269 + specOf(item) {
  270 + const t = [item.thickness, item.thicknessTolPos, item.thicknessTolNeg].filter(Boolean).join('/ ')
  271 + const w = [item.width, item.widthTolPos, item.widthTolNeg].filter(Boolean).join('/ ')
  272 + const l = [item.length, item.lengthTolPos, item.lengthTolNeg].filter(Boolean).join('/ ')
  273 + return [t, w, l].filter(Boolean).join(' × ')
  274 + },
  275 + formatCurrency(val) {
  276 + if (val == null || val === '') return ''
  277 + const num = Number(val)
  278 + const pre = isNaN(num) ? '' : '¥'
  279 + const fixed = isNaN(num) ? String(val) : num.toFixed(2)
  280 + return `${pre}${fixed}`
  281 + },
  282 + onReset() {
  283 + this.items = this.items.map((it, i) => ({
  284 + ...it,
  285 + quantity: '',
  286 + currentQuantity: '',
  287 + unitPrice: '',
  288 + // amountExcludingTax: 0
  289 + }))
  290 + },
  291 + async onSubmit() {
  292 + const selected = this.items.filter(it => it.locked).map(it => {
  293 + const raw = { ...(it.raw || {}) }
  294 + const qty = this.toNumber(it.quantity)
  295 + const price = this.toNumber(it.unitPrice)
  296 + const curQtyRaw = it.currentQuantity
  297 + const total = this.toNumber(it.totalAmount)
  298 + // const excl = this.toNumber(it.amountExcludingTax)
  299 + if (Object.prototype.hasOwnProperty.call(raw, 'productQuantity')) raw.productQuantity = qty
  300 + else raw.quantity = qty
  301 + raw.currentQuantity = (curQtyRaw === '' || curQtyRaw === null || curQtyRaw === undefined) ? null : this.toNumber(curQtyRaw)
  302 + raw.unitPrice = price
  303 + raw.totalAmount = total
  304 + // raw.amountExcludingTax = excl
  305 + return raw
  306 + })
  307 + if (!selected.length) {
  308 + uni.showToast({ title: '未选择任何拆分项', icon: 'none' })
  309 + return
  310 + }
  311 + const invalidQty = selected.find(r => {
  312 + const q = this.toNumber(r.currentQuantity)
  313 + return !(q > 0)
  314 + })
  315 + if (invalidQty) {
  316 + uni.showToast({ title: '请填写本次拆分数量', icon: 'none' })
  317 + return
  318 + }
  319 + this.selectedItems = selected
  320 + const payload = {
  321 + id: this.id,
  322 + contractDistributorLineList: selected
  323 + }
  324 +
  325 + uni.showModal({
  326 + title: '确认提交',
  327 + content: '确定提交拆分吗?',
  328 + success: (res) => {
  329 + if (res.confirm) {
  330 + splitQuantityLock(payload).then(() => {
  331 + uni.showToast({ title: '拆分已提交', icon: 'success' })
  332 + setTimeout(() => {
  333 + uni.navigateTo({ url: '/pages/contract_foreign_stock/index' })
  334 + }, 500)
  335 + }).catch((err) => {
  336 + uni.showToast({ title: err.msg || '提交失败', icon: 'none' })
  337 + })
  338 + }
  339 + }
  340 + })
  341 + }
  342 + }
  343 +}
  344 +</script>
  345 +
  346 +<style lang="scss" scoped>
  347 +.page {
  348 + display: flex;
  349 + flex-direction: column;
  350 + height: 100%;
  351 +}
  352 +
  353 +.scroll {
  354 + flex: 1;
  355 + padding: 12rpx 0 392rpx !important;
  356 +}
  357 +
  358 +.header {
  359 + background-color: #fff;
  360 + display: flex;
  361 + align-items: center;
  362 + padding: 24rpx 32rpx;
  363 + border-bottom: 1rpx solid #f0f0f0;
  364 +}
  365 +
  366 +.title {
  367 + font-size: 32rpx;
  368 + color: rgba(0, 0, 0, 0.9);
  369 + font-weight: 600;
  370 +}
  371 +
  372 +.opCollapse {
  373 + width: 24rpx;
  374 + height: 24rpx;
  375 + margin-right: 16rpx;
  376 + margin-top: 8rpx;
  377 +}
  378 +
  379 +.block {
  380 + background: #fff;
  381 + margin-top: 20rpx;
  382 +}
  383 +
  384 +.block-header {
  385 + display: flex;
  386 + align-items: center;
  387 + padding: 24rpx 32rpx;
  388 + border-bottom: 1rpx solid #f0f0f0;
  389 +}
  390 +
  391 +.block-header ::v-deep .uni-data-checklist .checkbox__inner {
  392 + width: 36rpx;
  393 + height: 36rpx;
  394 +}
  395 +
  396 +.block-header ::v-deep .uni-data-checklist .checklist-text {
  397 + font-size: 28rpx;
  398 + margin-left: 12rpx;
  399 +}
  400 +
  401 +.block-title {
  402 + margin-left: 12rpx;
  403 + font-size: 28rpx;
  404 + color: rgba(0, 0, 0, 0.9);
  405 +}
  406 +
  407 +.ops {
  408 + margin-left: auto;
  409 + display: flex;
  410 + align-items: center;
  411 + color: $theme-primary;
  412 + font-size: 28rpx;
  413 +}
  414 +
  415 +.opIcon {
  416 + width: 40rpx;
  417 + height: 40rpx;
  418 +}
  419 +
  420 +.opText {
  421 + margin-left: 8rpx;
  422 + color: $theme-primary;
  423 +}
  424 +
  425 +::v-deep .uni-list {
  426 + .uni-easyinput {
  427 + display: flex;
  428 +
  429 + .uni-input-input {
  430 + color: rgba(0, 0, 0, 0.9);
  431 + }
  432 + }
  433 +
  434 + .uni-input-placeholder {
  435 + z-index: 1;
  436 + }
  437 +
  438 + .uni-input-input {
  439 + background-color: #ffffff;
  440 + }
  441 +
  442 + background: transparent;
  443 +
  444 + &-item {
  445 + &__extra-text {
  446 + font-size: 32rpx;
  447 + }
  448 +
  449 + &__content-title {
  450 + font-size: 32rpx;
  451 + color: rgba(0, 0, 0, 0.9);
  452 + }
  453 +
  454 + &__container {
  455 + padding: 32rpx;
  456 +
  457 + .uni-easyinput {
  458 + &__placeholder-class {
  459 + font-size: 32rpx;
  460 + color: rgba(0, 0, 0, 0.4);
  461 + }
  462 +
  463 + &__content {
  464 + border: none;
  465 + background-color: #ffffff !important;
  466 +
  467 + &-input {
  468 + padding-left: 0 !important;
  469 + height: 48rpx;
  470 + line-height: 48rpx;
  471 + font-size: 32rpx;
  472 + }
  473 +
  474 + .content-clear-icon {
  475 + font-size: 44rpx !important;
  476 + }
  477 + }
  478 + }
  479 +
  480 + .item-title,
  481 + .uni-list-item__content {
  482 + flex: none;
  483 + min-height: 48rpx;
  484 + line-height: 48rpx;
  485 + font-size: 32rpx;
  486 + position: relative;
  487 + width: 210rpx;
  488 + margin-right: 32rpx;
  489 + color: rgba(0, 0, 0, 0.9);
  490 +
  491 + .required {
  492 + color: red;
  493 + position: absolute;
  494 + top: 50%;
  495 + transform: translateY(-50%);
  496 + left: -16rpx;
  497 + }
  498 + }
  499 + }
  500 +
  501 + &.select-item {
  502 + &.is-empty {
  503 + .uni-list-item__extra-text {
  504 + color: rgba(0, 0, 0, 0.4) !important;
  505 + }
  506 + }
  507 +
  508 + &.is-filled {
  509 + .uni-list-item__extra-text {
  510 + color: rgba(0, 0, 0, 0.9) !important;
  511 + }
  512 + }
  513 + }
  514 +
  515 + &.mgb10 {
  516 + margin-bottom: 20rpx;
  517 + }
  518 + }
  519 +}
  520 +
  521 +// ::v-deep .uni-list-item__container {
  522 +// padding: 32rpx;
  523 +// }
  524 +
  525 +::v-deep .is-disabled {
  526 + background-color: transparent !important;
  527 +}
  528 +
  529 +// ::v-deep .uni-list-item__content-title {
  530 +// font-size: 28rpx;
  531 +// color: rgba(0, 0, 0, 0.9);
  532 +// }
  533 +
  534 +// ::v-deep .uni-list-item__extra-text {
  535 +// font-size: 32rpx;
  536 +// }
  537 +
  538 +::v-deep .uni-easyinput {
  539 + width: 100%;
  540 +}
  541 +
  542 +::v-deep .uni-easyinput__placeholder-class {
  543 + font-size: 32rpx;
  544 + color: rgba(0, 0, 0, 0.4);
  545 +}
  546 +
  547 +::v-deep .uni-easyinput__content {
  548 + border: none;
  549 + display: flex;
  550 +}
  551 +
  552 +::v-deep .uni-easyinput__content-input {
  553 + padding-left: 0 !important;
  554 + height: 48rpx;
  555 + line-height: 48rpx;
  556 + font-size: 32rpx;
  557 + color: rgba(0, 0, 0, 0.9);
  558 +}
  559 +
  560 +.amount-item .item-title {
  561 + display: flex;
  562 + align-items: center;
  563 +}
  564 +
  565 +.amount-row {
  566 + display: flex;
  567 + align-items: center;
  568 +}
  569 +
  570 +.amount-row .unit {
  571 + margin-left: 12rpx;
  572 + color: rgba(0, 0, 0, 0.6);
  573 +}
  574 +
  575 +.summary {
  576 + margin-top: 20rpx;
  577 + background: #fff;
  578 + padding-bottom: 12rpx;
  579 +}
  580 +
  581 +.title-header {
  582 + display: flex;
  583 + align-items: center;
  584 + padding: 20rpx 32rpx;
  585 +}
  586 +
  587 +.title-header_icon {
  588 + width: 24rpx;
  589 + height: 24rpx;
  590 + margin-right: 16rpx;
  591 +}
  592 +
  593 +.sum-card {
  594 + background: #f3f3f3;
  595 + border-radius: 16rpx;
  596 + padding: 24rpx;
  597 + margin: 0 32rpx 20rpx;
  598 +}
  599 +
  600 +.row {
  601 + display: flex;
  602 + margin-bottom: 16rpx;
  603 +}
  604 +
  605 +.row .label {
  606 + width: 140rpx;
  607 + color: rgba(0, 0, 0, 0.6);
  608 + font-size: 28rpx;
  609 +}
  610 +
  611 +.row .value {
  612 + flex: 1;
  613 + text-align: right;
  614 + color: rgba(0, 0, 0, 0.9);
  615 + font-size: 28rpx;
  616 +}
  617 +
  618 +.row .amount {
  619 + color: #D54941;
  620 +}
  621 +
  622 +.total {
  623 + .total-text {
  624 + font-weight: 600;
  625 + font-size: 32rpx;
  626 + color: rgba(0, 0, 0, 0.9);
  627 + padding-bottom: 28rpx;
  628 + border-bottom: 2rpx solid #E7E7E7;
  629 + }
  630 +
  631 + .total-item {
  632 + display: flex;
  633 + align-items: center;
  634 +
  635 + .total-item-text {
  636 + font-weight: 400;
  637 + font-size: 28rpx;
  638 + color: rgba(0, 0, 0, 0.6);
  639 + line-height: 32rpx;
  640 + width: 240rpx;
  641 + padding: 12rpx 0;
  642 + }
  643 +
  644 + .total-item-price {
  645 + font-weight: 600;
  646 + font-size: 32rpx;
  647 + color: rgba(0, 0, 0, 0.9);
  648 + line-height: 32rpx;
  649 + }
  650 +
  651 + .text-red {
  652 + color: #D54941;
  653 + }
  654 + }
  655 +
  656 +}
  657 +
  658 +.footer {
  659 + z-index: 2;
  660 + position: fixed;
  661 + left: 0;
  662 + right: 0;
  663 + bottom: 0;
  664 + padding: 32rpx;
  665 + padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
  666 + background: #fff;
  667 + box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
  668 +
  669 + .btn {
  670 + height: 80rpx;
  671 + line-height: 80rpx;
  672 + border-radius: 12rpx;
  673 + font-size: 32rpx;
  674 + }
  675 +
  676 + .submit {
  677 + background: $theme-primary;
  678 + color: #fff;
  679 + }
  680 +}
  681 +
  682 +.btn {
  683 + height: 80rpx;
  684 + line-height: 80rpx;
  685 + border-radius: 12rpx;
  686 + font-size: 32rpx;
  687 + flex: 1;
  688 +}
  689 +
  690 +.submit {
  691 + background: $theme-primary;
  692 + color: #fff;
  693 +}
  694 +
  695 +.value-spec {
  696 + height: 48rpx;
  697 + display: flex;
  698 + align-items: center;
  699 + color: #000000;
  700 +
  701 + // justify-content: end;
  702 + &_box {
  703 + position: relative;
  704 + width: 60rpx;
  705 + height: 48rpx;
  706 +
  707 + &_1 {
  708 + font-size: 16rpx;
  709 + position: absolute;
  710 + top: -10rpx;
  711 + left: 0;
  712 + }
  713 +
  714 + &_2 {
  715 + font-size: 16rpx;
  716 + position: absolute;
  717 + bottom: -10rpx;
  718 + left: 0;
  719 + }
  720 + }
  721 +
  722 + &_val {
  723 + font-size: 28rpx;
  724 +
  725 + &.p12 {
  726 + padding-right: 12rpx;
  727 + }
  728 + }
  729 +}
  730 +
  731 +.row-spec {
  732 + height: 60rpx;
  733 + align-items: center;
  734 +}
  735 +</style>
\ No newline at end of file
... ...
... ... @@ -279,6 +279,12 @@ export default {
279 279 visible: true,
280 280 variant: 'outline',
281 281 event: 'print'
  282 + },
  283 + {
  284 + text: '拆分',
  285 + visible: true,
  286 + variant: 'outline',
  287 + event: 'split'
282 288 }
283 289 ],
284 290 uploadId: '',
... ... @@ -293,6 +299,7 @@ export default {
293 299 const a = this.detail.standardApproved || false
294 300 const e = this.detail.showExamine || false
295 301 const f = this.detail.standardShowExamine || false
  302 + const g = this.detail.canSplit || false
296 303 return [
297 304 { ...this.buttons[0], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:modify')) },
298 305 { ...this.buttons[1], visible: (s === 'DRAFT' && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:delete')) },
... ... @@ -308,6 +315,7 @@ export default {
308 315 { ...this.buttons[8], visible: (s === 'STANDARD' && f && a === 'AUDIT' && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:standard-approve')) },
309 316 { ...this.buttons[12], visible: (s !== 'DELETED' && this.$auth.hasPermi('contract-manage:distribution-inventory-contract:copy')) },
310 317 { ...this.buttons[13], visible: true },
  318 + { ...this.buttons[14], visible: g },
311 319 ]
312 320 }
313 321 },
... ... @@ -452,6 +460,12 @@ export default {
452 460 if (e === 'auditDetail3') return this.onAuditDetail(this.detail.id || '', 'STANDARD_CONTRACT')
453 461 if (e === 'copy') return this.onCopy(this.detail)
454 462 if (e === 'print') return this.onPrint(this.detail.id || '')
  463 + if (e === 'split') return this.onSplit(this.detail.id || '')
  464 + },
  465 + onSplit(id) {
  466 + uni.navigateTo({
  467 + url: '/pages/contract_stock/split?id=' + id || ''
  468 + })
455 469 },
456 470 onPrint(id) {
457 471 printFile(id)
... ...
... ... @@ -84,11 +84,6 @@
84 84 <uni-easyinput v-model="item.quantity" type="number" :inputBorder="false" disabled placeholder="不可编辑" />
85 85 </template>
86 86 </uni-list-item>
87   - <uni-list-item title="本次锁价数量">
88   - <template v-slot:footer>
89   - <uni-easyinput v-model="item.currentQuantity" type="number" :inputBorder="false" placeholder="请输入本次锁价数量" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'currentQuantity', 3)" />
90   - </template>
91   - </uni-list-item>
92 87 <uni-list-item title="单价">
93 88 <template v-slot:footer>
94 89 <uni-easyinput v-model="item.unitPrice" type="digit" :inputBorder="false" placeholder="请输入单价" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'unitPrice', 0)" />
... ... @@ -248,7 +243,6 @@ export default {
248 243 materialCode: v.materialCode || '',
249 244 status: v.status || '',
250 245 quantity: v.productQuantity || v.quantity || '',
251   - currentQuantity: v.currentQuantity === 0 ? 0 : (v.currentQuantity || ''),
252 246 unitPrice: v.unitPrice || '',
253 247 amountExcludingTax: v.amountExcludingTax || 0,
254 248 totalAmount: v.totalAmount || 0,
... ... @@ -328,7 +322,6 @@ export default {
328 322 this.items = this.items.map((it, i) => ({
329 323 ...it,
330 324 quantity: '',
331   - currentQuantity: '',
332 325 unitPrice: '',
333 326 amountExcludingTax: 0
334 327 }))
... ... @@ -337,13 +330,11 @@ export default {
337 330 const selected = this.items.filter(it => it.locked).map(it => {
338 331 const raw = { ...(it.raw || {}) }
339 332 const qty = this.toNumber(it.quantity)
340   - const curQtyRaw = it.currentQuantity
341 333 const price = this.toNumber(it.unitPrice)
342 334 const total = this.toNumber(it.totalAmount)
343 335 const excl = this.toNumber(it.amountExcludingTax)
344 336 if (Object.prototype.hasOwnProperty.call(raw, 'productQuantity')) raw.productQuantity = qty
345 337 else raw.quantity = qty
346   - raw.currentQuantity = (curQtyRaw === '' || curQtyRaw === null || curQtyRaw === undefined) ? null : this.toNumber(curQtyRaw)
347 338 raw.unitPrice = price
348 339 raw.totalAmount = total
349 340 raw.amountExcludingTax = excl
... ... @@ -361,14 +352,6 @@ export default {
361 352 uni.showToast({ title: '请填写单价', icon: 'none' })
362 353 return
363 354 }
364   - const invalidQty = selected.find(r => {
365   - const q = this.toNumber(r.currentQuantity)
366   - return !(q > 0)
367   - })
368   - if (invalidQty) {
369   - uni.showToast({ title: '请填写本次锁价数量', icon: 'none' })
370   - return
371   - }
372 355 this.selectedItems = selected
373 356 const payload = {
374 357 id: this.id,
... ... @@ -785,4 +768,4 @@ export default {
785 768 height: 60rpx;
786 769 align-items: center;
787 770 }
788   -</style>
  771 +</style>
\ No newline at end of file
... ...
  1 +<template>
  2 + <view class="page">
  3 + <scroll-view class="scroll" scroll-y>
  4 + <view class="lock-page">
  5 + <view class="block" v-for="(item, idx) in items" :key="idx">
  6 + <view class="block-header">
  7 + <uni-data-checkbox
  8 + multiple
  9 + mode="default"
  10 + :localdata="[{ text: '拆分数量', value: 'LOCKED' }]"
  11 + :modelValue="item.locked ? ['LOCKED'] : []"
  12 + :disabled="true"
  13 + @change="onLockChange(idx, $event)"
  14 + />
  15 + <view class="ops" @click="toggleItem(idx)">
  16 + <image class="opIcon"
  17 + :src="item.collapsed ? '/static/images/up.png' : '/static/images/down.png'" />
  18 + <text class="opText">{{ item.collapsed ? '收起' : '展开' }}</text>
  19 + </view>
  20 + </view>
  21 +
  22 + <uni-list v-show="item.collapsed">
  23 + <uni-list-item title="产品名称">
  24 + <template v-slot:footer>
  25 + <uni-easyinput v-model="item.productName" placeholder="请输入产品名称" :clearable="false" disabled />
  26 + </template>
  27 + </uni-list-item>
  28 + <uni-list-item title="行业">
  29 + <template v-slot:footer>
  30 + <uni-easyinput v-model="item.industry" placeholder="请输入行业" :clearable="false" disabled />
  31 + </template>
  32 + </uni-list-item>
  33 + <uni-list-item title="牌号">
  34 + <template v-slot:footer>
  35 + <uni-easyinput v-model="item.brand" placeholder="请输入牌号" :clearable="false" disabled />
  36 + </template>
  37 + </uni-list-item>
  38 + <uni-list-item title="品质">
  39 + <template v-slot:footer>
  40 + <uni-easyinput v-model="item.quality" placeholder="请输入品质" :clearable="false" disabled />
  41 + </template>
  42 + </uni-list-item>
  43 + <uni-list-item title="规格(mm)">
  44 + <template v-slot:footer>
  45 + <view class="value value-spec">
  46 + <view v-if="item.thickness" class="value-spec_val">{{ item.thickness }}</view>
  47 + <view v-if="item.thickness" class="value-spec_box">
  48 + <view v-if="item.thicknessTolPos" class="value-spec_box_1">{{ item.thicknessTolPos > 0 ? '+' + item.thicknessTolPos : item.thicknessTolPos }}
  49 + </view>
  50 + <view v-if="item.thicknessTolNeg" class="value-spec_box_2">{{ item.thicknessTolNeg > 0 ? '+' + item.thicknessTolNeg : item.thicknessTolNeg }}
  51 + </view>
  52 + </view>
  53 + <view v-if="item.width" class="value-spec_val p12">*</view>
  54 + <view v-if="item.width" class="value-spec_val">{{ item.width }}</view>
  55 + <view v-if="item.width" class="value-spec_box">
  56 + <view v-if="item.widthTolPos" class="value-spec_box_1">{{ item.widthTolPos > 0 ? '+' + item.widthTolPos : item.widthTolPos }}
  57 + </view>
  58 + <view v-if="item.widthTolNeg" class="value-spec_box_2">{{ item.widthTolNeg > 0 ? '+' + item.widthTolNeg : item.widthTolNeg }}
  59 + </view>
  60 + </view>
  61 + <view v-if="item.length" class="value-spec_val p12">*</view>
  62 + <view v-if="item.length" class="value-spec_val">{{ item.length }}</view>
  63 + <view v-if="item.length" class="value-spec_box">
  64 + <view v-if="item.lengthTolPos" class="value-spec_box_1">{{ item.lengthTolPos > 0 ? '+' + item.lengthTolPos : item.lengthTolPos }}
  65 + </view>
  66 + <view v-if="item.lengthTolNeg" class="value-spec_box_2">{{ item.lengthTolNeg > 0 ? '+' + item.lengthTolNeg : item.lengthTolNeg }}
  67 + </view>
  68 + </view>
  69 + </view>
  70 + </template>
  71 + </uni-list-item>
  72 + <uni-list-item title="物料编码">
  73 + <template v-slot:footer>
  74 + <uni-easyinput v-model="item.materialCode" placeholder="请输入物料编码" :clearable="false" disabled />
  75 + </template>
  76 + </uni-list-item>
  77 + <uni-list-item title="状态">
  78 + <template v-slot:footer>
  79 + <uni-easyinput v-model="item.status" placeholder="请输入状态" :clearable="false" disabled />
  80 + </template>
  81 + </uni-list-item>
  82 + <uni-list-item title="数量">
  83 + <template v-slot:footer>
  84 + <uni-easyinput v-model="item.quantity" type="number" :inputBorder="false" disabled placeholder="不可编辑" />
  85 + </template>
  86 + </uni-list-item>
  87 + <uni-list-item title="本次锁价数量">
  88 + <template v-slot:footer>
  89 + <uni-easyinput v-model="item.currentQuantity" type="number" :inputBorder="false" placeholder="请输入本次拆分数量" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'currentQuantity', 3)" />
  90 + </template>
  91 + </uni-list-item>
  92 + <uni-list-item title="单价">
  93 + <template v-slot:footer>
  94 + <uni-easyinput v-model="item.unitPrice" type="digit" :inputBorder="false" disabled placeholder="不可编辑" @input="onImmediateChange(idx)" @blur="onNumberBlur(idx, 'unitPrice', 0)" />
  95 + </template>
  96 + </uni-list-item>
  97 + <uni-list-item title="不含税金额">
  98 + <template v-slot:footer>
  99 + <uni-easyinput v-model="item.amountExcludingTax" type="number" :inputBorder="false" disabled placeholder="" />
  100 + </template>
  101 + </uni-list-item>
  102 + <uni-list-item title="总金额">
  103 + <template v-slot:footer>
  104 + <uni-easyinput v-model="item.totalAmount" type="number" :inputBorder="false" disabled placeholder="" />
  105 + </template>
  106 + </uni-list-item>
  107 + <uni-list-item title="发货日期">
  108 + <template v-slot:footer>
  109 + <uni-easyinput v-model="item.deliveryDate" :inputBorder="false" disabled />
  110 + </template>
  111 + </uni-list-item>
  112 + </uni-list>
  113 +
  114 + <uni-list v-show="!item.collapsed">
  115 + <uni-list-item title="产品名称">
  116 + <template v-slot:footer>
  117 + <uni-easyinput v-model="item.productName" placeholder="请输入产品名称" :clearable="false" disabled />
  118 + </template>
  119 + </uni-list-item>
  120 + <uni-list-item title="行业">
  121 + <template v-slot:footer>
  122 + <uni-easyinput v-model="item.industry" placeholder="请输入行业" :clearable="false" disabled />
  123 + </template>
  124 + </uni-list-item>
  125 + <uni-list-item title="牌号">
  126 + <template v-slot:footer>
  127 + <uni-easyinput v-model="item.brand" placeholder="请输入牌号" :clearable="false" disabled />
  128 + </template>
  129 + </uni-list-item>
  130 +
  131 + </uni-list>
  132 + </view>
  133 + <view class="footer">
  134 + <button class="btn submit" type="primary" @click="onSubmit">提交</button>
  135 + </view>
  136 + </view>
  137 + </scroll-view>
  138 +
  139 + </view>
  140 +</template>
  141 +
  142 +<script>
  143 +import { getContractApi, splitQuantityLock } from '@/api/contract'
  144 +
  145 +export default {
  146 + name: 'ContractUnplanLock',
  147 + data() {
  148 + return {
  149 + id: '',
  150 + items: [],
  151 + planQty: 30,
  152 + }
  153 + },
  154 + onLoad(options) {
  155 + const id = options && options.id ? options.id : ''
  156 + this.id = id
  157 + this.loadDetail()
  158 + },
  159 + methods: {
  160 + onLockChange(idx, e) {
  161 + const it = this.items[idx]
  162 + if (!it) return
  163 + const arr = e && e.detail && e.detail.value ? e.detail.value : []
  164 + it.locked = Array.isArray(arr) && arr.length > 0
  165 + this.$set(this.items, idx, it)
  166 + },
  167 + async loadDetail() {
  168 + if (!this.id) return
  169 + try {
  170 + const res = await getContractApi(this.id)
  171 + const data = res && res.data ? res.data : {}
  172 + const lines = Array.isArray(data.contractDistributorLineList) ? data.contractDistributorLineList : []
  173 + const init = lines.map(v => ({
  174 + locked: true,
  175 + collapsed: true,
  176 + raw: v,
  177 + productName: v.rawProductName || v.productName || '',
  178 + industry: v.industry || '',
  179 + brand: v.rawProductGrade || v.brand || '',
  180 + quality: v.quality || '',
  181 + thickness: v.thickness || '',
  182 + thicknessTolPos: v.thicknessTolPos || '',
  183 + thicknessTolNeg: v.thicknessTolNeg || '',
  184 + width: v.width || '',
  185 + widthTolPos: v.widthTolPos || '',
  186 + widthTolNeg: v.widthTolNeg || '',
  187 + length: v.length || '',
  188 + lengthTolPos: v.lengthTolPos || '',
  189 + lengthTolNeg: v.lengthTolNeg || '',
  190 + materialCode: v.materialCode || '',
  191 + status: v.status || '',
  192 + quantity: v.productQuantity || v.quantity || '',
  193 + currentQuantity: v.currentQuantity === 0 ? 0 : (v.currentQuantity || ''),
  194 + unitPrice: v.unitPrice || '',
  195 + amountExcludingTax: v.amountExcludingTax || 0,
  196 + totalAmount: v.totalAmount || 0,
  197 + deliveryDate: v.deliveryDate || '',
  198 + specDisplay: ''
  199 + }))
  200 + this.items = init.map(it => ({ ...it, specDisplay: this.specOf(it) }))
  201 + this.recalculateAll()
  202 + } catch (e) {
  203 + this.items = []
  204 + }
  205 + },
  206 + toggleItem(idx) {
  207 + const it = this.items[idx]
  208 + if (!it) return
  209 + it.collapsed = !it.collapsed
  210 + this.$set(this.items, idx, it)
  211 + },
  212 + onImmediateChange(idx) {
  213 + this.$nextTick(() => this.recalculate(idx))
  214 + },
  215 + onNumberBlur(idx, field, digits) {
  216 + const it = this.items[idx]
  217 + if (!it) return
  218 + const raw = it[field]
  219 + if (raw === '' || raw === null || raw === undefined) {
  220 + this.$set(this.items, idx, it)
  221 + this.recalculate(idx)
  222 + return
  223 + }
  224 + const num = this.toNumber(raw)
  225 + const rounded = this.round(num, digits)
  226 + it[field] = rounded
  227 + this.$set(this.items, idx, it)
  228 + this.recalculate(idx)
  229 + },
  230 + recalculate(idx) {
  231 + const TAX_RATE = 0.13
  232 + const it = this.items[idx]
  233 + if (!it) return
  234 + const qty = this.toNumber(it.quantity)
  235 + const price = this.toNumber(it.unitPrice)
  236 + const total = this.round(qty * price, 2)
  237 + const excl = this.round(total / (1 + TAX_RATE), 2)
  238 + it.amountExcludingTax = excl
  239 + it.totalAmount = total
  240 + this.$set(this.items, idx, it)
  241 + },
  242 + recalculateAll() {
  243 + for (let i = 0; i < this.items.length; i++) this.recalculate(i)
  244 + },
  245 + toNumber(val) {
  246 + if (typeof val === 'number') return isNaN(val) ? 0 : val
  247 + const n = parseFloat(String(val).replace(/[^0-9.\-]/g, ''))
  248 + return isNaN(n) ? 0 : n
  249 + },
  250 + round(val, digits = 2) {
  251 + const n = Number(val)
  252 + if (isNaN(n)) return 0
  253 + const m = Math.pow(10, digits)
  254 + return Math.round(n * m) / m
  255 + },
  256 + specOf(item) {
  257 + const t = [item.thickness, item.thicknessTolPos, item.thicknessTolNeg].filter(Boolean).join('/ ')
  258 + const w = [item.width, item.widthTolPos, item.widthTolNeg].filter(Boolean).join('/ ')
  259 + const l = [item.length, item.lengthTolPos, item.lengthTolNeg].filter(Boolean).join('/ ')
  260 + return [t, w, l].filter(Boolean).join(' × ')
  261 + },
  262 + formatCurrency(val) {
  263 + if (val == null || val === '') return ''
  264 + const num = Number(val)
  265 + const pre = isNaN(num) ? '' : '¥'
  266 + const fixed = isNaN(num) ? String(val) : num.toFixed(2)
  267 + return `${pre}${fixed}`
  268 + },
  269 + onReset() {
  270 + this.items = this.items.map((it, i) => ({
  271 + ...it,
  272 + quantity: '',
  273 + currentQuantity: '',
  274 + unitPrice: '',
  275 + amountExcludingTax: 0
  276 + }))
  277 + },
  278 + async onSubmit() {
  279 + const selected = this.items.filter(it => it.locked).map(it => {
  280 + const raw = { ...(it.raw || {}) }
  281 + const qty = this.toNumber(it.quantity)
  282 + const curQtyRaw = it.currentQuantity
  283 + const price = this.toNumber(it.unitPrice)
  284 + const total = this.toNumber(it.totalAmount)
  285 + const excl = this.toNumber(it.amountExcludingTax)
  286 + if (Object.prototype.hasOwnProperty.call(raw, 'productQuantity')) raw.productQuantity = qty
  287 + else raw.quantity = qty
  288 + raw.currentQuantity = (curQtyRaw === '' || curQtyRaw === null || curQtyRaw === undefined) ? null : this.toNumber(curQtyRaw)
  289 + raw.unitPrice = price
  290 + raw.totalAmount = total
  291 + raw.amountExcludingTax = excl
  292 + return raw
  293 + })
  294 + if (!selected.length) {
  295 + uni.showToast({ title: '未选择任何拆分项', icon: 'none' })
  296 + return
  297 + }
  298 + const invalidQty = selected.find(r => {
  299 + const q = this.toNumber(r.currentQuantity)
  300 + return !(q > 0)
  301 + })
  302 + if (invalidQty) {
  303 + uni.showToast({ title: '请填写本次拆分数量', icon: 'none' })
  304 + return
  305 + }
  306 + this.selectedItems = selected
  307 + const payload = {
  308 + id: this.id,
  309 + contractDistributorLineList: selected
  310 + }
  311 +
  312 + uni.showModal({
  313 + title: '确认提交',
  314 + content: '确定提交拆分吗?',
  315 + success: (res) => {
  316 + if (res.confirm) {
  317 + splitQuantityLock(payload).then(() => {
  318 + uni.showToast({ title: '拆分已提交', icon: 'success' })
  319 + setTimeout(() => {
  320 + uni.navigateTo({ url: '/pages/contract_stock/index' })
  321 + }, 500)
  322 + }).catch((err) => {
  323 + uni.showToast({ title: err.msg ||'提交失败', icon: 'none' })
  324 + })
  325 + }
  326 + }
  327 + })
  328 + }
  329 + }
  330 +}
  331 +</script>
  332 +
  333 +<style lang="scss" scoped>
  334 +.page {
  335 + display: flex;
  336 + flex-direction: column;
  337 + height: 100%;
  338 +}
  339 +
  340 +.scroll {
  341 + flex: 1;
  342 + padding: 12rpx 0 392rpx !important;
  343 +}
  344 +
  345 +.header {
  346 + background-color: #fff;
  347 + display: flex;
  348 + align-items: center;
  349 + padding: 24rpx 32rpx;
  350 + border-bottom: 1rpx solid #f0f0f0;
  351 +}
  352 +
  353 +.title {
  354 + font-size: 32rpx;
  355 + color: rgba(0, 0, 0, 0.9);
  356 + font-weight: 600;
  357 +}
  358 +
  359 +.opCollapse {
  360 + width: 24rpx;
  361 + height: 24rpx;
  362 + margin-right: 16rpx;
  363 + margin-top: 8rpx;
  364 +}
  365 +
  366 +.block {
  367 + background: #fff;
  368 + margin-top: 20rpx;
  369 +}
  370 +
  371 +.block-header {
  372 + display: flex;
  373 + align-items: center;
  374 + padding: 24rpx 32rpx;
  375 + border-bottom: 1rpx solid #f0f0f0;
  376 +}
  377 +
  378 +.block-header ::v-deep .uni-data-checklist .checkbox__inner {
  379 + width: 36rpx;
  380 + height: 36rpx;
  381 +}
  382 +.block-header ::v-deep .uni-data-checklist .checklist-text {
  383 + font-size: 28rpx;
  384 + margin-left: 12rpx;
  385 +}
  386 +
  387 +.block-title {
  388 + margin-left: 12rpx;
  389 + font-size: 28rpx;
  390 + color: rgba(0, 0, 0, 0.9);
  391 +}
  392 +
  393 +.ops {
  394 + margin-left: auto;
  395 + display: flex;
  396 + align-items: center;
  397 + color: $theme-primary;
  398 + font-size: 28rpx;
  399 +}
  400 +
  401 +.opIcon {
  402 + width: 40rpx;
  403 + height: 40rpx;
  404 +}
  405 +
  406 +.opText {
  407 + margin-left: 8rpx;
  408 + color: $theme-primary;
  409 +}
  410 +
  411 +::v-deep .uni-list {
  412 + .uni-easyinput {
  413 + display: flex;
  414 +
  415 + .uni-input-input {
  416 + color: rgba(0, 0, 0, 0.9);
  417 + }
  418 + }
  419 +
  420 + .uni-input-placeholder {
  421 + z-index: 1;
  422 + }
  423 +
  424 + .uni-input-input {
  425 + background-color: #ffffff;
  426 + }
  427 +
  428 + background: transparent;
  429 +
  430 + &-item {
  431 + &__extra-text {
  432 + font-size: 32rpx;
  433 + }
  434 +
  435 + &__content-title {
  436 + font-size: 32rpx;
  437 + color: rgba(0, 0, 0, 0.9);
  438 + }
  439 +
  440 + &__container {
  441 + padding: 32rpx;
  442 +
  443 + .uni-easyinput {
  444 + &__placeholder-class {
  445 + font-size: 32rpx;
  446 + color: rgba(0, 0, 0, 0.4);
  447 + }
  448 +
  449 + &__content {
  450 + border: none;
  451 + background-color: #ffffff !important;
  452 +
  453 + &-input {
  454 + padding-left: 0 !important;
  455 + height: 48rpx;
  456 + line-height: 48rpx;
  457 + font-size: 32rpx;
  458 + }
  459 +
  460 + .content-clear-icon {
  461 + font-size: 44rpx !important;
  462 + }
  463 + }
  464 + }
  465 +
  466 + .item-title,
  467 + .uni-list-item__content {
  468 + flex: none;
  469 + min-height: 48rpx;
  470 + line-height: 48rpx;
  471 + font-size: 32rpx;
  472 + position: relative;
  473 + width: 210rpx;
  474 + margin-right: 32rpx;
  475 + color: rgba(0, 0, 0, 0.9);
  476 +
  477 + .required {
  478 + color: red;
  479 + position: absolute;
  480 + top: 50%;
  481 + transform: translateY(-50%);
  482 + left: -16rpx;
  483 + }
  484 + }
  485 + }
  486 +
  487 + &.select-item {
  488 + &.is-empty {
  489 + .uni-list-item__extra-text {
  490 + color: rgba(0, 0, 0, 0.4) !important;
  491 + }
  492 + }
  493 +
  494 + &.is-filled {
  495 + .uni-list-item__extra-text {
  496 + color: rgba(0, 0, 0, 0.9) !important;
  497 + }
  498 + }
  499 + }
  500 +
  501 + &.mgb10 {
  502 + margin-bottom: 20rpx;
  503 + }
  504 + }
  505 +}
  506 +
  507 +// ::v-deep .uni-list-item__container {
  508 +// padding: 32rpx;
  509 +// }
  510 +
  511 +::v-deep .is-disabled {
  512 + background-color: transparent !important;
  513 +}
  514 +// ::v-deep .uni-list-item__content-title {
  515 +// font-size: 28rpx;
  516 +// color: rgba(0, 0, 0, 0.9);
  517 +// }
  518 +
  519 +// ::v-deep .uni-list-item__extra-text {
  520 +// font-size: 32rpx;
  521 +// }
  522 +
  523 +::v-deep .uni-easyinput {
  524 + width: 100%;
  525 +}
  526 +
  527 +::v-deep .uni-easyinput__placeholder-class {
  528 + font-size: 32rpx;
  529 + color: rgba(0, 0, 0, 0.4);
  530 +}
  531 +
  532 +::v-deep .uni-easyinput__content {
  533 + border: none;
  534 + display: flex;
  535 +}
  536 +
  537 +::v-deep .uni-easyinput__content-input {
  538 + padding-left: 0 !important;
  539 + height: 48rpx;
  540 + line-height: 48rpx;
  541 + font-size: 32rpx;
  542 + color: rgba(0, 0, 0, 0.9);
  543 +}
  544 +
  545 +.amount-item .item-title {
  546 + display: flex;
  547 + align-items: center;
  548 +}
  549 +
  550 +.amount-row {
  551 + display: flex;
  552 + align-items: center;
  553 +}
  554 +
  555 +.amount-row .unit {
  556 + margin-left: 12rpx;
  557 + color: rgba(0, 0, 0, 0.6);
  558 +}
  559 +
  560 +.summary {
  561 + margin-top: 20rpx;
  562 + background: #fff;
  563 + padding-bottom: 12rpx;
  564 +}
  565 +
  566 +.title-header {
  567 + display: flex;
  568 + align-items: center;
  569 + padding: 20rpx 32rpx;
  570 +}
  571 +
  572 +.title-header_icon {
  573 + width: 24rpx;
  574 + height: 24rpx;
  575 + margin-right: 16rpx;
  576 +}
  577 +
  578 +.sum-card {
  579 + background: #f3f3f3;
  580 + border-radius: 16rpx;
  581 + padding: 24rpx;
  582 + margin: 0 32rpx 20rpx;
  583 +}
  584 +
  585 +.row {
  586 + display: flex;
  587 + margin-bottom: 16rpx;
  588 +}
  589 +
  590 +.row .label {
  591 + width: 140rpx;
  592 + color: rgba(0, 0, 0, 0.6);
  593 + font-size: 28rpx;
  594 +}
  595 +
  596 +.row .value {
  597 + flex: 1;
  598 + text-align: right;
  599 + color: rgba(0, 0, 0, 0.9);
  600 + font-size: 28rpx;
  601 +}
  602 +
  603 +.row .amount {
  604 + color: #D54941;
  605 +}
  606 +
  607 +.total {
  608 + .total-text {
  609 + font-weight: 600;
  610 + font-size: 32rpx;
  611 + color: rgba(0, 0, 0, 0.9);
  612 + padding-bottom: 28rpx;
  613 + border-bottom: 2rpx solid #E7E7E7;
  614 + }
  615 +
  616 + .total-item {
  617 + display: flex;
  618 + align-items: center;
  619 +
  620 + .total-item-text {
  621 + font-weight: 400;
  622 + font-size: 28rpx;
  623 + color: rgba(0, 0, 0, 0.6);
  624 + line-height: 32rpx;
  625 + width: 240rpx;
  626 + padding: 12rpx 0;
  627 + }
  628 +
  629 + .total-item-price {
  630 + font-weight: 600;
  631 + font-size: 32rpx;
  632 + color: rgba(0, 0, 0, 0.9);
  633 + line-height: 32rpx;
  634 + }
  635 +
  636 + .text-red {
  637 + color: #D54941;
  638 + }
  639 + }
  640 +
  641 +}
  642 +
  643 +.footer {
  644 + z-index: 2;
  645 + position: fixed;
  646 + left: 0;
  647 + right: 0;
  648 + bottom: 0;
  649 + padding: 32rpx;
  650 + padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
  651 + background: #fff;
  652 + box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
  653 +
  654 + .btn {
  655 + height: 80rpx;
  656 + line-height: 80rpx;
  657 + border-radius: 12rpx;
  658 + font-size: 32rpx;
  659 + }
  660 +
  661 + .submit {
  662 + background: $theme-primary;
  663 + color: #fff;
  664 + }
  665 +}
  666 +
  667 +.btn {
  668 + height: 80rpx;
  669 + line-height: 80rpx;
  670 + border-radius: 12rpx;
  671 + font-size: 32rpx;
  672 + flex: 1;
  673 +}
  674 +
  675 +.submit {
  676 + background: $theme-primary;
  677 + color: #fff;
  678 +}
  679 +.value-spec {
  680 + height: 48rpx;
  681 + display: flex;
  682 + align-items: center;
  683 + color: #000000;
  684 + // justify-content: end;
  685 + &_box {
  686 + position: relative;
  687 + width: 60rpx;
  688 + height: 48rpx;
  689 +
  690 + &_1 {
  691 + font-size: 16rpx;
  692 + position: absolute;
  693 + top: -10rpx;
  694 + left: 0;
  695 + }
  696 +
  697 + &_2 {
  698 + font-size: 16rpx;
  699 + position: absolute;
  700 + bottom: -10rpx;
  701 + left: 0;
  702 + }
  703 + }
  704 +
  705 + &_val {
  706 + font-size: 28rpx;
  707 +
  708 + &.p12 {
  709 + padding-right: 12rpx;
  710 + }
  711 + }
  712 + }
  713 + .row-spec {
  714 + height: 60rpx;
  715 + align-items: center;
  716 + }
  717 +</style>
... ...