Commit 269e25532833fb391b3fe92c139d43783af65493

Authored by gesilong
1 parent 80343aa0

commit:合同审批 可以修改信息内容

... ... @@ -412,6 +412,14 @@
412 412 }
413 413 },
414 414 {
  415 + "path": "pages/contract_stock/uploadStandard",
  416 + "style": {
  417 + "navigationBarTitleText": "上传合同附件",
  418 + "navigationBarBackgroundColor": "#ffffff",
  419 + "navigationBarTextStyle": "black"
  420 + }
  421 + },
  422 + {
415 423 "path": "pages/contract_stock/lock",
416 424 "style": {
417 425 "navigationBarTitleText": "锁价",
... ... @@ -452,6 +460,14 @@
452 460 }
453 461 },
454 462 {
  463 + "path": "pages/contract_unplan/uploadStandard",
  464 + "style": {
  465 + "navigationBarTitleText": "上传合同附件",
  466 + "navigationBarBackgroundColor": "#ffffff",
  467 + "navigationBarTextStyle": "black"
  468 + }
  469 + },
  470 + {
455 471 "path": "pages/contract_unplan/lock",
456 472 "style": {
457 473 "navigationBarTitleText": "锁规",
... ... @@ -580,6 +596,14 @@
580 596 }
581 597 },
582 598 {
  599 + "path": "pages/contract_foreign_stock/uploadStandard",
  600 + "style": {
  601 + "navigationBarTitleText": "上传合同附件",
  602 + "navigationBarBackgroundColor": "#ffffff",
  603 + "navigationBarTextStyle": "black"
  604 + }
  605 + },
  606 + {
583 607 "path": "pages/contract_foreign_stock/lock",
584 608 "style": {
585 609 "navigationBarTitleText": "锁价",
... ... @@ -620,6 +644,14 @@
620 644 }
621 645 },
622 646 {
  647 + "path": "pages/contract_foreign_unplan/uploadStandard",
  648 + "style": {
  649 + "navigationBarTitleText": "上传合同附件",
  650 + "navigationBarBackgroundColor": "#ffffff",
  651 + "navigationBarTextStyle": "black"
  652 + }
  653 + },
  654 + {
623 655 "path": "pages/contract_foreign_unplan/lock",
624 656 "style": {
625 657 "navigationBarTitleText": "锁规",
... ...
... ... @@ -386,7 +386,7 @@ export default {
386 386 const e = btn.event || ''
387 387 if (e === 'edit') return this.onEdit(btn && btn.params)
388 388 if (e === 'delete') return this.onDelete(btn && btn.params)
389   - if (e === 'upload') return this.uploadContract(this.detail.id || '')
  389 + if (e === 'upload') return this.uploadContract(this.detail.id || '', 'standard')
390 390 if (e === 'uploadSeal') return this.uploadContract(this.detail.id || '', 'seal')
391 391 if (e === 'audit') return this.onAudit(btn && btn.params)
392 392 if (e === 'auditDetail') return this.onAuditDetail(btn && btn.params)
... ...
... ... @@ -373,6 +373,13 @@ export default {
373 373 uploadContract(id, type = 'formal') {
374 374 if (!id) return
375 375 this.uploadId = id
  376 + if ((type === 'uploadParent' || type === 'upload' )&& this.detail?.canEdit) {
  377 + const query = `?id=${encodeURIComponent(id)}&uploadType=${encodeURIComponent(type)}`
  378 + uni.navigateTo({
  379 + url: '/pages/contract_foreign_stock/uploadStandard' + query
  380 + })
  381 + return
  382 + }
376 383 this.uploadType = type
377 384 this.$refs.uploadPopup.open()
378 385 },
... ... @@ -456,8 +463,8 @@ export default {
456 463 if (e === 'edit') return this.onEdit(btn && btn.params)
457 464 if (e === 'delete') return this.onDelete(btn && btn.params)
458 465 if (e === 'lock') return this.onLock()
459   - if (e === 'upload') return this.uploadContract(this.detail.id || '')
460   - if (e === 'uploadParent') return this.uploadContract(this.detail.parentId || '')
  466 + if (e === 'upload') return this.uploadContract(this.detail.id || '','upload')
  467 + if (e === 'uploadParent') return this.uploadContract(this.detail.parentId || '', 'uploadParent')
461 468 if (e === 'uploadStandard') return this.uploadContract(this.detail.id || '', 'standard')
462 469 if (e === 'audit1') return this.onAudit(this.detail.id || '', 'FORMAL_CONTRACT')
463 470 if (e === 'audit2') return this.onAudit(this.detail.parentId || '', 'FORMAL_CONTRACT')
... ...
  1 +<template>
  2 + <view class="page">
  3 + <scroll-view class="scroll" scroll-y>
  4 + <uni-list>
  5 + <uni-list-item title="编号">
  6 + <template v-slot:footer>
  7 + <uni-easyinput v-model="form.code" :inputBorder="false" disabled />
  8 + </template>
  9 + </uni-list-item>
  10 +
  11 + <uni-list-item class="select-item" :class="form.supplier ? 'is-filled' : 'is-empty'" clickable
  12 + @click="openSheet('supplier')" :rightText="displayLabel('supplierName')" showArrow>
  13 + <template v-slot:body>
  14 + <view class="item-title"><text class="required">*</text><text>供方</text></view>
  15 + </template>
  16 + </uni-list-item>
  17 +
  18 + <uni-list-item class="select-item" :class="form.buyer ? 'is-filled' : 'is-empty'" clickable
  19 + @click="openRelate('buyer')" :rightText="form.buyerName || '请选择需方'" showArrow>
  20 + <template v-slot:body>
  21 + <view class="item-title"><text class="required">*</text><text>需方</text></view>
  22 + </template>
  23 + </uni-list-item>
  24 +
  25 + <uni-list-item class="select-item" :class="form.stockUpCompanyId ? 'is-filled' : 'is-empty'" clickable
  26 + @click="openRelate('stockUpCompanyId')" :rightText="form.stockUpCompanyName || '请选择备货单位'" showArrow>
  27 + <template v-slot:body>
  28 + <view class="item-title"><text class="required">*</text><text>备货单位/人(生产标准)</text></view>
  29 + </template>
  30 + </uni-list-item>
  31 +
  32 + <uni-list-item class="select-item" :class="form.workshopId ? 'is-filled' : 'is-empty'" clickable
  33 + @click="openSheet('workshopId')" :rightText="form.workshopName || '请选择生产厂'" showArrow>
  34 + <template v-slot:body>
  35 + <view class="item-title"><text class="required">*</text><text>生产厂</text></view>
  36 + </template>
  37 + </uni-list-item>
  38 + <uni-list-item class="select-item" :class="form.deptName ? 'is-filled' : 'is-empty'">
  39 + <template v-slot:body>
  40 + <view class="item-title"><text class="required">*</text><text>办事处</text></view>
  41 + </template>
  42 + <template v-slot:footer>
  43 + <view class="serial-number-row">
  44 + <uni-easyinput v-model="form.deptName" :inputBorder="false" disabled />
  45 + </view>
  46 + </template>
  47 + </uni-list-item>
  48 + <uni-list-item class="select-item" :class="form.region ? 'is-filled' : 'is-empty'" clickable
  49 + @click="openSheet('region')" :rightText="displayLabel('regionName')" showArrow>
  50 + <template v-slot:body>
  51 + <view class="item-title"><text class="required">*</text><text>区域</text></view>
  52 + </template>
  53 + </uni-list-item>
  54 +
  55 + <uni-list-item title="订货日期">
  56 + <template v-slot:footer>
  57 + <uni-datetime-picker type="date" v-model="form.orderDate" />
  58 + </template>
  59 + </uni-list-item>
  60 +
  61 + <uni-list-item title="单位">
  62 + <template v-slot:footer>
  63 + <uni-easyinput v-model="form.unit" :inputBorder="false" disabled />
  64 + </template>
  65 + </uni-list-item>
  66 +
  67 + <ProductRel ref="productRel" mode="add" :deliveryDate="form.orderDate" :deliveryDateBase="form.deliveryDate"
  68 + :list="productLineList" @change="onProductsChange" :options="productList" />
  69 +
  70 + <uni-list-item title="合计金额(大写)">
  71 + <template v-slot:footer>
  72 + <uni-easyinput v-model="form.totalAmountCapital" placeholder="" :inputBorder="false" disabled />
  73 + </template>
  74 + </uni-list-item>
  75 + <uni-list-item title="交付定金、数额、时间">
  76 + <template v-slot:footer>
  77 + <uni-easyinput v-model="form.depositInfo" placeholder="请输入交付定金、数额、时间" :inputBorder="false" />
  78 + </template>
  79 + </uni-list-item>
  80 + <uni-list-item title="包装要求">
  81 + <template v-slot:footer>
  82 + <uni-easyinput v-model="form.packagingRequirements" placeholder="请输入包装要求" :inputBorder="false" />
  83 + </template>
  84 + </uni-list-item>
  85 + <uni-list-item title="付款方式、付款期限">
  86 + <template v-slot:footer>
  87 + <uni-easyinput v-model="form.paymentTerms" placeholder="请输入付款方式、付款期限" :inputBorder="false" />
  88 + </template>
  89 + </uni-list-item>
  90 + <uni-list-item title="运输方式">
  91 + <template v-slot:footer>
  92 + <uni-easyinput v-model="form.transportMode" placeholder="请输入运输方式" :inputBorder="false" />
  93 + </template>
  94 + </uni-list-item>
  95 + <uni-list-item class="select-item" :class="(Array.isArray(form.destinationId) && form.destinationId.length) ? 'is-filled' : 'is-empty'" clickable
  96 + @click="openCitySelector" :rightText="form.destinationLabel || '请选择'" showArrow>
  97 + <template v-slot:body>
  98 + <view class="item-title"><text>目的地</text></view>
  99 + <CitySelector ref="citySelectorRef" v-model="form.destinationId" @change="onCityChange" />
  100 + </template>
  101 + </uni-list-item>
  102 +
  103 + <uni-list-item class="select-item" :class="form.includesPackagingFeeName ? 'is-filled' : 'is-empty'" clickable
  104 + @click="openSheet('includesPackagingFee')" :rightText="form.includesPackagingFeeName || '请选择'" showArrow>
  105 + <template v-slot:body>
  106 + <view class="item-title"><text>单价中是否已包含包装费</text></view>
  107 + </template>
  108 + </uni-list-item>
  109 + <uni-list-item class="select-item" :class="form.includesTransportFeeName ? 'is-filled' : 'is-empty'" clickable
  110 + @click="openSheet('includesTransportFee')" :rightText="form.includesTransportFeeName || '请选择'" showArrow>
  111 + <template v-slot:body>
  112 + <view class="item-title"><text>单价中是否已包含运费</text></view>
  113 + </template>
  114 + </uni-list-item>
  115 + <uni-list-item title="需方指定收货人">
  116 + <template v-slot:footer>
  117 + <uni-easyinput v-model="form.designatedConsignee" placeholder="请输入需方指定收货人" :inputBorder="false" />
  118 + </template>
  119 + </uni-list-item>
  120 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  121 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  122 + <template v-slot:body>
  123 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  124 + </template>
  125 + </uni-list-item>
  126 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  127 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  128 + <template v-slot:body>
  129 + <view class="item-title"><text>执行标准</text></view>
  130 + </template>
  131 + </uni-list-item>
  132 + <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
  133 + <template v-slot:footer>
  134 + <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注" :inputBorder="false" />
  135 + </template>
  136 + </uni-list-item>
  137 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
  138 + <template v-slot:footer>
  139 + <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
  140 + </template>
  141 + </uni-list-item>
  142 + <uni-list-item title="备注">
  143 + <template v-slot:footer>
  144 + <uni-easyinput v-model="form.remarks" placeholder="请输入备注" :inputBorder="false" maxlength="2000" />
  145 + </template>
  146 + </uni-list-item>
  147 +
  148 + <view class="quality">
  149 + <image class="opCollapse" src="/static/images/title.png" />
  150 + <text class="title">具体质量要求</text>
  151 + </view>
  152 + <uni-list-item title="件重条头">
  153 + <template v-slot:footer>
  154 + <uni-easyinput v-model="form.pieceWeightHead" placeholder="请输入" :inputBorder="false" />
  155 + </template>
  156 + </uni-list-item>
  157 + <uni-list-item title="表面">
  158 + <template v-slot:footer>
  159 + <uni-easyinput v-model="form.surface" placeholder="请输入" :inputBorder="false" />
  160 + </template>
  161 + </uni-list-item>
  162 + <uni-list-item title="公差">
  163 + <template v-slot:footer>
  164 + <uni-easyinput v-model="form.tolerance" placeholder="请输入" :inputBorder="false" />
  165 + </template>
  166 + </uni-list-item>
  167 + <uni-list-item title="性能">
  168 + <template v-slot:footer>
  169 + <uni-easyinput v-model="form.performance" placeholder="请输入" :inputBorder="false" />
  170 + </template>
  171 + </uni-list-item>
  172 + <uni-list-item title="成分">
  173 + <template v-slot:footer>
  174 + <uni-easyinput v-model="form.component" placeholder="请输入" :inputBorder="false" />
  175 + </template>
  176 + </uni-list-item>
  177 + <uni-list-item title="包装">
  178 + <template v-slot:footer>
  179 + <uni-easyinput v-model="form.packaging" placeholder="请输入" :inputBorder="false" />
  180 + </template>
  181 + </uni-list-item>
  182 +
  183 + <uni-list-item :title="uploadType === 'seal' ? '双方盖章合同附件' : (uploadType === 'formal' ? '正式合同附件' : '标准合同附件')" style="margin-top: 20rpx;">
  184 + <template v-slot:footer>
  185 + <FileUpload v-model="fileInfo" />
  186 + </template>
  187 + </uni-list-item>
  188 + <uni-list-item v-if="uploadType !== 'seal'" class="select-item" :class="standardStandardizedName ? 'is-filled' : 'is-empty'" clickable
  189 + @click="openSheet('standardStandardized')" :rightText="standardStandardizedName || '请选择'" showArrow>
  190 + <template v-slot:body>
  191 + <view class="item-title"><text class="required">*</text><text>合同是否规范</text></view>
  192 + </template>
  193 + </uni-list-item>
  194 +
  195 + <view class="footer">
  196 + <div class="total">
  197 + <div class="total-text">合计</div>
  198 + <div class="total-item" style="padding: 20rpx 0;">
  199 + <div class="total-item-text">数量</div>
  200 + <div class="total-item-price">{{ (totalQuantity || 0).toFixed(2) }}kg</div>
  201 + </div>
  202 + </div>
  203 + <button class="btn submit" type="primary" @click="onSubmit">提交</button>
  204 + </view>
  205 + </uni-list>
  206 + </scroll-view>
  207 +
  208 + <SingleSelectSheet :visible.sync="sheet.visible" :title="sheet.title" :options="sheet.options" v-model="sheet.value"
  209 + @confirm="onSheetConfirm" />
  210 + <RelateSelectSheet :visible.sync="relate.visible" :title="relate.title" :source="relate.source"
  211 + :display-fields="relate.display" :multiple="relate.multiple" :row-key="relate.rowKey"
  212 + :selectedKeys.sync="relate.selectedKeys" @confirm="onRelateConfirm" />
  213 + </view>
  214 +</template>
  215 +
  216 +<script>
  217 +import SingleSelectSheet from '@/components/single-select/index.vue'
  218 +import RelateSelectSheet from '@/components/relate-select/index.vue'
  219 +import ProductRel from './productRel.vue'
  220 +import CitySelector from '@/components/city-selector/index.vue'
  221 +import FileUpload from '@/components/file-upload/index.vue'
  222 +import { getContractApi, uploadFormalContract, uploadStandardContract, uploadSignedContractFile } from '@/api/contract'
  223 +import { getDicByCodes } from '@/utils/dic'
  224 +import { formatCurrencyToChinese } from '@/utils/common'
  225 +import { workshopQueryApi } from '@/api/devManage'
  226 +import { getArea } from '@/api/credit_manage.js'
  227 +
  228 +export default {
  229 + name: 'UploadContractForeignStock',
  230 + components: { SingleSelectSheet, RelateSelectSheet, ProductRel, CitySelector, FileUpload },
  231 + data() {
  232 + return {
  233 + id: '',
  234 + uploadType: 'formal',
  235 + fileInfo: { id: '', name: '' },
  236 + standardStandardized: '',
  237 + standardStandardizedName: '',
  238 + form: {
  239 + id: '',
  240 + code: '',
  241 + supplier: '',
  242 + supplierName: '',
  243 + buyer: '',
  244 + buyerName: '',
  245 + stockUpCompanyId: '',
  246 + stockUpCompanyName: '',
  247 + workshopId: '',
  248 + workshopName: '',
  249 + region: '',
  250 + regionName: '',
  251 + deptName: '',
  252 + deptId: '',
  253 + orderDate: '',
  254 + deliveryDate: '',
  255 + designatedConsignee: '',
  256 + specialTerms: '',
  257 + specialTermsName: '',
  258 + executionStandard: '',
  259 + executionStandardName: '',
  260 + executionStandardRemarks: '',
  261 + includesPackagingFee: false,
  262 + includesPackagingFeeName: '否',
  263 + includesTransportFee: false,
  264 + includesTransportFeeName: '否',
  265 + unit: '美元、公斤、美元/公斤',
  266 + totalAmountCapital: '',
  267 + depositInfo: '',
  268 + packagingRequirements: '',
  269 + paymentTerms: '',
  270 + transportMode: '',
  271 + destinationId: [],
  272 + destinationLabel: '',
  273 + specialInstructions: '',
  274 + remarks: '',
  275 + pieceWeightHead: '',
  276 + surface: '',
  277 + tolerance: '',
  278 + performance: '',
  279 + component: '',
  280 + packaging: ''
  281 + },
  282 + supplierList: [],
  283 + specialTermsList: [],
  284 + executionStandardList: [],
  285 + yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
  286 + sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
  287 + relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
  288 + totalQuantity: 0,
  289 + totalAmountIncludingTax: 0,
  290 + productLineList: [],
  291 + newProductLineList: [],
  292 + productList: [],
  293 + regionOptions: [],
  294 + }
  295 + },
  296 + onLoad(query) {
  297 + this.id = (query && query.id) ? query.id : ''
  298 + this.uploadType = (query && query.uploadType) ? query.uploadType : 'formal'
  299 + },
  300 + created() {
  301 + this.loadSuppliers()
  302 + this.loadExtraOptions()
  303 + this.loadRegionOptions()
  304 + this.loadDetail()
  305 + this.$nextTick(() => {
  306 + if (Array.isArray(this.form.destinationId) && this.form.destinationId.length) {
  307 + this.initDestinationLabel()
  308 + }
  309 + })
  310 + },
  311 + methods: {
  312 + async loadRegionOptions() {
  313 + try {
  314 + const res = await getArea()
  315 + const list = res.data || []
  316 + this.regionOptions = (list || []).map(it => ({ label: it.name || '', value: it.id || '' }))
  317 + } catch (e) {
  318 + this.regionOptions = []
  319 + }
  320 + },
  321 + async loadDetail() {
  322 + if (!this.id) return
  323 + try {
  324 + const res = await getContractApi(this.id)
  325 + const data = res && res.data ? res.data : {}
  326 + const includesPackagingFeeName = data.includesPackagingFeeName || (data.includesPackagingFee ? '是' : '否')
  327 + const includesTransportFeeName = data.includesTransportFeeName || (data.includesTransportFee ? '是' : '否')
  328 + const m = { ...data, includesPackagingFeeName, includesTransportFeeName }
  329 + this.form = {
  330 + ...this.form,
  331 + id: m.id || '',
  332 + code: m.code || '',
  333 + supplier: m.supplier || '',
  334 + supplierName: m.supplierName || '',
  335 + buyer: m.buyer || (m.customer && m.customer.id) || '',
  336 + buyerName: m.buyerName || (m.customer && m.customer.name) || '',
  337 + stockUpCompanyId: m.stockUpCompanyId || '',
  338 + stockUpCompanyName: m.stockUpCompanyName || '',
  339 + orderDate: m.orderDate || '',
  340 + designatedConsignee: m.designatedConsignee || '',
  341 + specialTerms: m.specialTerms || '',
  342 + specialTermsName: m.specialTermsName || '',
  343 + executionStandard: m.executionStandard || '',
  344 + executionStandardName: m.executionStandardName || '',
  345 + executionStandardRemarks: m.executionStandardRemarks || '',
  346 + includesPackagingFee: !!m.includesPackagingFee,
  347 + includesPackagingFeeName,
  348 + includesTransportFee: !!m.includesTransportFee,
  349 + includesTransportFeeName,
  350 + unit: m.unit || this.form.unit,
  351 + totalAmountCapital: m.totalAmountCapital || '',
  352 + depositInfo: m.depositInfo || '',
  353 + packagingRequirements: m.packagingRequirements || '',
  354 + paymentTerms: m.paymentTerms || '',
  355 + transportMode: m.transportMode || '',
  356 + destinationId: (m.provinceId && m.cityId && m.districtId) ? [m.provinceId, m.cityId, m.districtId] : (Array.isArray(m.destinationId) ? m.destinationId : []),
  357 + destinationLabel: (m.provinceName && m.cityName && m.districtName) ? `${m.provinceName} / ${m.cityName} / ${m.districtName}` : (m.destinationLabel || ''),
  358 + specialInstructions: m.specialInstructions || '',
  359 + remarks: m.remarks || '',
  360 + pieceWeightHead: m.pieceWeightHead || '',
  361 + surface: m.surface || '',
  362 + tolerance: m.tolerance || '',
  363 + performance: m.performance || '',
  364 + component: m.component || '',
  365 + packaging: m.packaging || '',
  366 + workshopId: m.workshopId || '',
  367 + workshopName: m.workshopName || '',
  368 + region: m.region || '',
  369 + regionName: m.regionName || '',
  370 + deptName: m.deptName || '',
  371 + deptId: m.deptId || '',
  372 + }
  373 +
  374 + const fileId = (this.uploadType === 'seal') ? m.signedContractFileId : (this.uploadType === 'formal') ? m.formalFileId : m.standardFileId
  375 + const fileName = (this.uploadType === 'seal') ? m.signedContractFileName : (this.uploadType === 'formal') ? m.formalFileName : m.standardFileName
  376 + const standardized = (this.uploadType === 'formal') ? m.formalStandardized : (this.uploadType === 'standard') ? m.standardStandardized : ''
  377 + this.fileInfo = { id: fileId || '', name: fileName || '' }
  378 + this.standardStandardized = (standardized === true || standardized === false) ? standardized : ''
  379 + this.standardStandardizedName = (this.standardStandardized === true) ? '是' : (this.standardStandardized === false) ? '否' : ''
  380 +
  381 + const lines = Array.isArray(m.contractDistributorLineList) ? m.contractDistributorLineList : []
  382 + this.productLineList = lines
  383 + this.onProductsChange(lines)
  384 + } catch (e) { }
  385 + },
  386 + async initDestinationLabel() {
  387 + const comp = this.$refs.citySelectorRef
  388 + if (comp && typeof comp.getLabel === 'function') {
  389 + const label = await comp.getLabel()
  390 + this.form.destinationLabel = label || ''
  391 + }
  392 + },
  393 + openCitySelector() {
  394 + this.$refs.citySelectorRef && this.$refs.citySelectorRef.open()
  395 + },
  396 + onCityChange(payload) {
  397 + const label = payload && payload.label != null ? payload.label : ''
  398 + this.form.destinationLabel = label
  399 + },
  400 + onProductsChange(products) {
  401 + const list = Array.isArray(products) ? products : []
  402 + this.newProductLineList = list
  403 + const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
  404 + const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
  405 + this.totalQuantity = sumQ
  406 + this.totalAmountIncludingTax = sumT
  407 + this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
  408 + },
  409 + async loadSuppliers() {
  410 + try {
  411 + const results = await getDicByCodes(['SUPPLIER'])
  412 + const items = results && results.SUPPLIER && results.SUPPLIER.data ? results.SUPPLIER.data : []
  413 + this.supplierList = items.map(it => ({ label: it.name, value: it.code }))
  414 + } catch (e) { this.supplierList = [] }
  415 + },
  416 + async loadExtraOptions() {
  417 + try {
  418 + const results = await getDicByCodes(['CONDITIONS_REQUIRED', 'APPLICABLE_STANDARD', 'CONTRACT_PRODUCT'])
  419 + const c1 = results && results.CONDITIONS_REQUIRED && results.CONDITIONS_REQUIRED.data ? results.CONDITIONS_REQUIRED.data : []
  420 + const c2 = results && results.APPLICABLE_STANDARD && results.APPLICABLE_STANDARD.data ? results.APPLICABLE_STANDARD.data : []
  421 + const c3 = results && results.CONTRACT_PRODUCT && results.CONTRACT_PRODUCT.data ? results.CONTRACT_PRODUCT.data : []
  422 + this.specialTermsList = c1.map(it => ({ label: it.name, value: it.code }))
  423 + this.executionStandardList = c2.map(it => ({ label: it.name, value: it.code }))
  424 + this.productList = c3.map(it => ({ label: it.name, value: it.code }))
  425 + } catch (e) {
  426 + this.specialTermsList = []
  427 + this.executionStandardList = []
  428 + this.productList = []
  429 + }
  430 + },
  431 + displayLabel(field) {
  432 + const m = this.form
  433 + const map = { supplierName: '请选择供方', buyerName: '请选择需方', workshopName: '请选择生产厂', regionName: '请选择区域' }
  434 + const val = m[field]
  435 + return val ? String(val) : map[field]
  436 + },
  437 + async openSheet(field) {
  438 + if (field === 'standardStandardized') {
  439 + const options = this.yesNoList
  440 + const current = this.standardStandardized
  441 + const match = (options || []).find(o => String(o.value) === String(current) || String(o.label) === String(current))
  442 + this.sheet = { ...this.sheet, visible: true, title: '合同是否规范', options, field, value: match ? match.value : '' }
  443 + return
  444 + }
  445 + const setSheet = (title, options) => {
  446 + const current = this.form[field]
  447 + const match = (options || []).find(o => String(o.label) === String(current) || String(o.value) === String(current))
  448 + this.sheet = { ...this.sheet, visible: true, title, options, field, value: match ? match.value : '' }
  449 + }
  450 + if (field === 'workshopId') {
  451 + const res = await workshopQueryApi({ pageIndex: 1, pageSize: 9999 })
  452 + const _data = res.data || {}
  453 + const list = _data.datas || (Array.isArray(_data) ? _data : [])
  454 + const opts = (list || []).map(it => ({ label: it.name, value: it.id }))
  455 + setSheet('生产厂', opts)
  456 + } else if (field === 'supplier') {
  457 + setSheet('供方', this.supplierList)
  458 + } else if (field === 'specialTerms') {
  459 + setSheet('特别条款要求', this.specialTermsList)
  460 + } else if (field === 'executionStandard') {
  461 + setSheet('执行标准', this.executionStandardList)
  462 + } else if (field === 'includesPackagingFee') {
  463 + setSheet('单价中是否已包含包装费', this.yesNoList)
  464 + } else if (field === 'includesTransportFee') {
  465 + setSheet('单价中是否已包含运费', this.yesNoList)
  466 + } else if (field === 'region') {
  467 + setSheet('区域', this.regionOptions)
  468 + }
  469 + },
  470 + onSheetConfirm({ value, label }) {
  471 + const field = this.sheet.field
  472 + if (!field) return
  473 + const v = (value === undefined || value === null) ? '' : value
  474 + if (field === 'standardStandardized') {
  475 + this.standardStandardized = v
  476 + this.standardStandardizedName = label || ''
  477 + return
  478 + }
  479 + this.form[field] = v
  480 + this.form[field + 'Name'] = label || ''
  481 + },
  482 + openRelate(fieldKey) {
  483 + let config = {}
  484 + if (fieldKey === 'buyer') {
  485 + config = { title: '需方', source: 'customer', rowKey: 'id', multiple: false, display: [{ label: '名称', field: 'name' }, { label: '编号', field: 'code' }, { label: '状态', field: 'available', format: v => (v ? '启用' : '停用') }] }
  486 + } else if (fieldKey === 'stockUpCompanyId') {
  487 + config = { title: '备货单位/人(生产标准)', source: 'customer', rowKey: 'id', multiple: false, display: [{ label: '姓名', field: 'name' }, { label: '编号', field: 'code' }, { label: '状态', field: 'available', format: v => (v ? '启用' : '停用') }] }
  488 + }
  489 + const selectedKeys = this.form[fieldKey] ? [this.form[fieldKey]] : []
  490 + this.sheet.visible = false
  491 + this.relate = { ...this.relate, title: config.title, source: config.source, display: config.display, multiple: config.multiple, rowKey: config.rowKey, selectedKeys, fieldKey }
  492 + this.$nextTick(() => { this.relate.visible = true })
  493 + },
  494 + onRelateConfirm({ items }) {
  495 + const _fieldKey = this.relate.fieldKey
  496 + const first = (items && items.length > 0) ? items[0] : null
  497 + this.form[_fieldKey] = (first && first.id) ? first.id : ''
  498 + if (_fieldKey === 'stockUpCompanyId') {
  499 + this.form.stockUpCompanyName = (first && first.name) ? first.name : ''
  500 + } else {
  501 + this.form[_fieldKey + 'Name'] = (first && first.name) ? first.name : ''
  502 + }
  503 + },
  504 + validateRequired() {
  505 + const checks = [
  506 + { key: 'code', label: '编号' },
  507 + { key: 'supplier', label: '供方' },
  508 + { key: 'buyer', label: '需方' },
  509 + { key: 'stockUpCompanyId', label: '备货单位/人(生产标准)' },
  510 + { key: 'orderDate', label: '订货日期' },
  511 + { key: 'unit', label: '单位' },
  512 + { key: 'workshopId', label: '生产厂' },
  513 + { key: 'region', label: '区域' },
  514 + { key: 'specialTerms', label: '特别条款要求' },
  515 + ]
  516 + for (const it of checks) {
  517 + const val = this.form[it.key]
  518 + const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
  519 + if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
  520 + }
  521 + const list = Array.isArray(this.newProductLineList) ? this.newProductLineList : []
  522 + if (list.length === 0) {
  523 + uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
  524 + }
  525 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  526 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  527 + for (const [idx, it] of list.entries()) {
  528 + if (
  529 + strEmpty(it.productName) ||
  530 + strEmpty(it.industry) ||
  531 + strEmpty(it.quality) ||
  532 + strEmpty(it.brand) ||
  533 + numEmpty(it.quantity) ||
  534 + strEmpty(it.deliveryDate)
  535 + ) {
  536 + uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
  537 + }
  538 + }
  539 + if (this.$refs.productRel && !this.$refs.productRel.validate()) return false
  540 + return true
  541 + },
  542 + async onSubmit() {
  543 + if (!this.fileInfo.id) {
  544 + uni.showToast({ title: '请上传合同附件', icon: 'error' })
  545 + return
  546 + }
  547 + if (this.uploadType !== 'seal' && !this.standardStandardized && this.standardStandardized !== false) {
  548 + uni.showToast({ title: '请选择合同是否规范', icon: 'error' })
  549 + return
  550 + }
  551 + if (!this.validateRequired()) return
  552 + const confirmRes = await new Promise(resolve => {
  553 + uni.showModal({
  554 + title: '确认提交',
  555 + content: this.uploadType === 'seal' ? '确定提交双方盖章合同吗?' : this.uploadType === 'formal' ? '确定提交正式合同吗?' : '确定提交标准合同吗?',
  556 + confirmText: '确定',
  557 + cancelText: '取消',
  558 + success: resolve
  559 + })
  560 + })
  561 + if (!(confirmRes && confirmRes.confirm)) return
  562 + const clean = (obj) => {
  563 + const out = {}
  564 + Object.keys(obj || {}).forEach(k => {
  565 + const v = obj[k]
  566 + const isEmptyString = typeof v === 'string' && v.trim() === ''
  567 + const isUndef = v === undefined || v === null
  568 + const isNaNNumber = typeof v === 'number' && isNaN(v)
  569 + if (!(isEmptyString || isUndef || isNaNNumber)) out[k] = v
  570 + })
  571 + return out
  572 + }
  573 + const lines = (this.newProductLineList || []).map(it => clean(it))
  574 + const { destinationLabel, destinationId, ...formForSubmit } = this.form
  575 + const destination = destinationId && destinationId.length > 0 ? destinationId[destinationId.length - 1] : ''
  576 +
  577 + const payload = clean({
  578 + ...formForSubmit,
  579 + id: this.form.id,
  580 + destination,
  581 + type: 'INTL_INVENTORY_AGMT',
  582 + totalQuantity: this.totalQuantity,
  583 + totalAmountIncludingTax: this.totalAmountIncludingTax,
  584 + contractDistributorLineList: lines,
  585 + })
  586 +
  587 + let api = uploadStandardContract
  588 + if (this.uploadType === 'seal') {
  589 + api = uploadSignedContractFile
  590 + payload.signedContractFileId = this.fileInfo.id
  591 + payload.signedContractFileName = this.fileInfo.name
  592 + } else if (this.uploadType === 'formal') {
  593 + api = uploadFormalContract
  594 + payload.formalFileId = this.fileInfo.id
  595 + payload.formalFileName = this.fileInfo.name
  596 + payload.formalStandardized = this.standardStandardized
  597 + } else {
  598 + api = uploadStandardContract
  599 + payload.standardFileId = this.fileInfo.id
  600 + payload.standardFileName = this.fileInfo.name
  601 + payload.standardStandardized = this.standardStandardized
  602 + }
  603 +
  604 + try {
  605 + await api(payload)
  606 + uni.showToast({ title: '提交成功', icon: 'none' })
  607 + setTimeout(() => { uni.redirectTo({ url: '/pages/contract_foreign_stock/index' }) }, 400)
  608 + } catch (e) {
  609 + uni.showToast({ title: e.msg || '提交失败', icon: 'none' })
  610 + }
  611 + }
  612 + }
  613 +}
  614 +</script>
  615 +
  616 +<style lang="scss" scoped>
  617 +.total {
  618 + .total-text {
  619 + font-weight: 600;
  620 + font-size: 32rpx;
  621 + color: rgba(0, 0, 0, 0.9);
  622 + padding-bottom: 28rpx;
  623 + border-bottom: 2rpx solid #E7E7E7;
  624 + }
  625 +
  626 + .total-item {
  627 + display: flex;
  628 + align-items: center;
  629 + }
  630 +
  631 + .total-item-text {
  632 + font-weight: 400;
  633 + font-size: 28rpx;
  634 + color: rgba(0, 0, 0, 0.6);
  635 + line-height: 32rpx;
  636 + width: 240rpx;
  637 + padding: 12rpx 0;
  638 + }
  639 +
  640 + .total-item-price {
  641 + font-weight: 600;
  642 + font-size: 32rpx;
  643 + color: rgba(0, 0, 0, 0.9);
  644 + line-height: 32rpx;
  645 + }
  646 +
  647 + .text-red {
  648 + color: #D54941;
  649 + }
  650 +}
  651 +
  652 +.page {
  653 + display: flex;
  654 + flex-direction: column;
  655 + height: 100%;
  656 +}
  657 +
  658 +.scroll {
  659 + flex: 1;
  660 + padding: 12rpx 0 392rpx !important;
  661 +}
  662 +
  663 +.footer {
  664 + z-index: 2;
  665 + position: fixed;
  666 + left: 0;
  667 + right: 0;
  668 + bottom: 0;
  669 + padding: 32rpx;
  670 + padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
  671 + background: #fff;
  672 + box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
  673 +}
  674 +
  675 +.footer .btn {
  676 + height: 80rpx;
  677 + line-height: 80rpx;
  678 + border-radius: 12rpx;
  679 + font-size: 32rpx;
  680 +}
  681 +
  682 +.footer .submit {
  683 + background: $theme-primary;
  684 + color: #fff;
  685 +}
  686 +
  687 +.quality {
  688 + background-color: #fff;
  689 + display: flex;
  690 + align-items: center;
  691 + padding: 24rpx 32rpx;
  692 + border-bottom: 1rpx solid #f0f0f0;
  693 + margin-top: 20rpx;
  694 +
  695 + .title {
  696 + font-size: 32rpx;
  697 + color: rgba(0, 0, 0, 0.9);
  698 + font-weight: 600;
  699 + }
  700 +
  701 + .opCollapse {
  702 + color: rgba(0, 0, 0, 0.6);
  703 + width: 32rpx;
  704 + height: 28rpx;
  705 + margin-right: 16rpx;
  706 + }
  707 +}
  708 +
  709 +::v-deep .uni-list {
  710 + background: transparent;
  711 +}
  712 +
  713 +::v-deep .uni-list .uni-easyinput .uni-input-input {
  714 + color: rgba(0, 0, 0, 0.9);
  715 +}
  716 +
  717 +::v-deep .uni-list .uni-input-placeholder {
  718 + z-index: 1;
  719 +}
  720 +
  721 +::v-deep .uni-list .uni-input-input {
  722 + background-color: #ffffff;
  723 +}
  724 +
  725 +::v-deep .uni-list-item__extra-text {
  726 + font-size: 32rpx;
  727 +}
  728 +
  729 +::v-deep .uni-list-item__content-title {
  730 + font-size: 32rpx;
  731 + color: rgba(0, 0, 0, 0.9);
  732 +}
  733 +
  734 +::v-deep .uni-list-item__container {
  735 + padding: 32rpx;
  736 +}
  737 +
  738 +::v-deep .uni-list-item__container .uni-easyinput__placeholder-class {
  739 + font-size: 32rpx;
  740 + color: rgba(0, 0, 0, 0.4);
  741 +}
  742 +
  743 +::v-deep .uni-list-item__container .uni-easyinput__content {
  744 + border: none;
  745 + background-color: #ffffff !important;
  746 +}
  747 +
  748 +::v-deep .uni-list-item__container .uni-easyinput__content-input {
  749 + padding-left: 0 !important;
  750 + height: 48rpx;
  751 + line-height: 48rpx;
  752 + font-size: 32rpx;
  753 +}
  754 +
  755 +::v-deep .uni-list-item__container .item-title,
  756 +::v-deep .uni-list-item__container .uni-list-item__content {
  757 + flex: none;
  758 + min-height: 48rpx;
  759 + line-height: 48rpx;
  760 + font-size: 32rpx;
  761 + position: relative;
  762 + width: 210rpx;
  763 + margin-right: 32rpx;
  764 + color: rgba(0, 0, 0, 0.9);
  765 +}
  766 +
  767 +::v-deep .uni-list-item__container .item-title .required {
  768 + color: red;
  769 + position: absolute;
  770 + top: 50%;
  771 + transform: translateY(-50%);
  772 + left: -16rpx;
  773 +}
  774 +
  775 +::v-deep .uni-list-item.select-item.is-empty .uni-list-item__extra-text {
  776 + color: rgba(0, 0, 0, 0.4) !important;
  777 +}
  778 +
  779 +::v-deep .uni-list-item.select-item.is-filled .uni-list-item__extra-text {
  780 + color: rgba(0, 0, 0, 0.9) !important;
  781 +}
  782 +</style>
... ...
... ... @@ -392,6 +392,13 @@ export default {
392 392 uploadContract(id, type = 'formal') {
393 393 if (!id) return
394 394 this.uploadId = id
  395 + if (type === 'standard' && this.detail?.canEdit) {
  396 + const query = `?id=${encodeURIComponent(id)}&uploadType=${encodeURIComponent(type)}`
  397 + uni.navigateTo({
  398 + url: '/pages/contract_foreign_unplan/uploadStandard' + query
  399 + })
  400 + return
  401 + }
395 402 this.uploadType = type
396 403 this.$refs.uploadPopup.open()
397 404 },
... ...
  1 +<template>
  2 + <view class="page">
  3 + <scroll-view class="scroll" scroll-y>
  4 + <uni-list>
  5 + <uni-list-item title="编号">
  6 + <template v-slot:footer>
  7 + <uni-easyinput v-model="form.code" :inputBorder="false" disabled />
  8 + </template>
  9 + </uni-list-item>
  10 +
  11 + <uni-list-item class="select-item" :class="form.supplier ? 'is-filled' : 'is-empty'" clickable
  12 + @click="openSheet('supplier')" :rightText="displayLabel('supplierName')" showArrow>
  13 + <template v-slot:body>
  14 + <view class="item-title"><text class="required">*</text><text>供方</text></view>
  15 + </template>
  16 + </uni-list-item>
  17 +
  18 + <uni-list-item class="select-item" :class="form.buyer ? 'is-filled' : 'is-empty'" clickable
  19 + @click="openRelate('buyer')" :rightText="form.buyerName || '请选择需方'" showArrow>
  20 + <template v-slot:body>
  21 + <view class="item-title"><text class="required">*</text><text>需方</text></view>
  22 + </template>
  23 + </uni-list-item>
  24 +
  25 + <uni-list-item class="select-item" :class="form.stockUpCompanyId ? 'is-filled' : 'is-empty'" clickable
  26 + @click="openRelate('stockUpCompanyId')" :rightText="form.stockUpCompanyName || '请选择备货单位'" showArrow>
  27 + <template v-slot:body>
  28 + <view class="item-title"><text class="required">*</text><text>备货单位/人(生产标准)</text></view>
  29 + </template>
  30 + </uni-list-item>
  31 +
  32 + <uni-list-item class="select-item" :class="form.workshopId ? 'is-filled' : 'is-empty'" clickable
  33 + @click="openSheet('workshopId')" :rightText="form.workshopName || '请选择生产厂'" showArrow>
  34 + <template v-slot:body>
  35 + <view class="item-title"><text class="required">*</text><text>生产厂</text></view>
  36 + </template>
  37 + </uni-list-item>
  38 + <uni-list-item class="select-item" :class="form.deptName ? 'is-filled' : 'is-empty'">
  39 + <template v-slot:body>
  40 + <view class="item-title"><text class="required">*</text><text>办事处</text></view>
  41 + </template>
  42 + <template v-slot:footer>
  43 + <view class="serial-number-row">
  44 + <uni-easyinput v-model="form.deptName" :inputBorder="false" disabled />
  45 + </view>
  46 + </template>
  47 + </uni-list-item>
  48 + <uni-list-item class="select-item" :class="form.region ? 'is-filled' : 'is-empty'" clickable
  49 + @click="openSheet('region')" :rightText="displayLabel('regionName')" showArrow>
  50 + <template v-slot:body>
  51 + <view class="item-title"><text class="required">*</text><text>区域</text></view>
  52 + </template>
  53 + </uni-list-item>
  54 +
  55 + <uni-list-item title="订货日期">
  56 + <template v-slot:footer>
  57 + <uni-datetime-picker type="date" v-model="form.orderDate" />
  58 + </template>
  59 + </uni-list-item>
  60 +
  61 + <uni-list-item title="单位">
  62 + <template v-slot:footer>
  63 + <uni-easyinput v-model="form.unit" :inputBorder="false" disabled />
  64 + </template>
  65 + </uni-list-item>
  66 +
  67 + <ProductRel ref="productRel" mode="add" :deliveryDate="form.orderDate" :deliveryDateBase="form.deliveryDate"
  68 + :list="productLineList" @change="onProductsChange" :options="productList" />
  69 +
  70 + <uni-list-item title="合计金额(大写)">
  71 + <template v-slot:footer>
  72 + <uni-easyinput v-model="form.totalAmountCapital" placeholder="" :inputBorder="false" disabled />
  73 + </template>
  74 + </uni-list-item>
  75 + <uni-list-item title="交付定金、数额、时间">
  76 + <template v-slot:footer>
  77 + <uni-easyinput v-model="form.depositInfo" placeholder="请输入交付定金、数额、时间" :inputBorder="false" />
  78 + </template>
  79 + </uni-list-item>
  80 + <uni-list-item title="包装要求">
  81 + <template v-slot:footer>
  82 + <uni-easyinput v-model="form.packagingRequirements" placeholder="请输入包装要求" :inputBorder="false" />
  83 + </template>
  84 + </uni-list-item>
  85 + <uni-list-item title="付款方式、付款期限">
  86 + <template v-slot:footer>
  87 + <uni-easyinput v-model="form.paymentTerms" placeholder="请输入付款方式、付款期限" :inputBorder="false" />
  88 + </template>
  89 + </uni-list-item>
  90 + <uni-list-item title="运输方式">
  91 + <template v-slot:footer>
  92 + <uni-easyinput v-model="form.transportMode" placeholder="请输入运输方式" :inputBorder="false" />
  93 + </template>
  94 + </uni-list-item>
  95 + <uni-list-item class="select-item"
  96 + :class="(Array.isArray(form.destinationId) && form.destinationId.length) ? 'is-filled' : 'is-empty'" clickable
  97 + @click="openCitySelector" :rightText="form.destinationLabel || '请选择'" showArrow>
  98 + <template v-slot:body>
  99 + <view class="item-title"><text>目的地</text></view>
  100 + <CitySelector ref="citySelectorRef" v-model="form.destinationId" @change="onCityChange" />
  101 + </template>
  102 + </uni-list-item>
  103 +
  104 + <uni-list-item class="select-item" :class="form.includesPackagingFeeName ? 'is-filled' : 'is-empty'" clickable
  105 + @click="openSheet('includesPackagingFee')" :rightText="form.includesPackagingFeeName || '请选择'" showArrow>
  106 + <template v-slot:body>
  107 + <view class="item-title"><text>单价中是否已包含包装费</text></view>
  108 + </template>
  109 + </uni-list-item>
  110 + <uni-list-item class="select-item" :class="form.includesTransportFeeName ? 'is-filled' : 'is-empty'" clickable
  111 + @click="openSheet('includesTransportFee')" :rightText="form.includesTransportFeeName || '请选择'" showArrow>
  112 + <template v-slot:body>
  113 + <view class="item-title"><text>单价中是否已包含运费</text></view>
  114 + </template>
  115 + </uni-list-item>
  116 + <uni-list-item title="需方指定收货人">
  117 + <template v-slot:footer>
  118 + <uni-easyinput v-model="form.designatedConsignee" placeholder="请输入需方指定收货人" :inputBorder="false" />
  119 + </template>
  120 + </uni-list-item>
  121 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  122 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  123 + <template v-slot:body>
  124 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  125 + </template>
  126 + </uni-list-item>
  127 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  128 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  129 + <template v-slot:body>
  130 + <view class="item-title"><text>执行标准</text></view>
  131 + </template>
  132 + </uni-list-item>
  133 + <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
  134 + <template v-slot:footer>
  135 + <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注" :inputBorder="false" />
  136 + </template>
  137 + </uni-list-item>
  138 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
  139 + <template v-slot:footer>
  140 + <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
  141 + </template>
  142 + </uni-list-item>
  143 + <uni-list-item title="备注">
  144 + <template v-slot:footer>
  145 + <uni-easyinput v-model="form.remarks" placeholder="请输入备注" :inputBorder="false" maxlength="2000" />
  146 + </template>
  147 + </uni-list-item>
  148 +
  149 + <view class="quality">
  150 + <image class="opCollapse" src="/static/images/title.png" />
  151 + <text class="title">具体质量要求</text>
  152 + </view>
  153 + <uni-list-item title="件重条头">
  154 + <template v-slot:footer>
  155 + <uni-easyinput v-model="form.pieceWeightHead" placeholder="请输入" :inputBorder="false" />
  156 + </template>
  157 + </uni-list-item>
  158 + <uni-list-item title="表面">
  159 + <template v-slot:footer>
  160 + <uni-easyinput v-model="form.surface" placeholder="请输入" :inputBorder="false" />
  161 + </template>
  162 + </uni-list-item>
  163 + <uni-list-item title="公差">
  164 + <template v-slot:footer>
  165 + <uni-easyinput v-model="form.tolerance" placeholder="请输入" :inputBorder="false" />
  166 + </template>
  167 + </uni-list-item>
  168 + <uni-list-item title="性能">
  169 + <template v-slot:footer>
  170 + <uni-easyinput v-model="form.performance" placeholder="请输入" :inputBorder="false" />
  171 + </template>
  172 + </uni-list-item>
  173 + <uni-list-item title="成分">
  174 + <template v-slot:footer>
  175 + <uni-easyinput v-model="form.component" placeholder="请输入" :inputBorder="false" />
  176 + </template>
  177 + </uni-list-item>
  178 + <uni-list-item title="包装">
  179 + <template v-slot:footer>
  180 + <uni-easyinput v-model="form.packaging" placeholder="请输入" :inputBorder="false" />
  181 + </template>
  182 + </uni-list-item>
  183 +
  184 + <uni-list-item title="标准合同附件" style="margin-top: 20rpx;">
  185 + <template v-slot:footer>
  186 + <FileUpload v-model="fileInfo" />
  187 + </template>
  188 + </uni-list-item>
  189 + <uni-list-item class="select-item" :class="standardStandardizedName ? 'is-filled' : 'is-empty'" clickable
  190 + @click="openSheet('standardStandardized')" :rightText="standardStandardizedName || '请选择'" showArrow>
  191 + <template v-slot:body>
  192 + <view class="item-title"><text class="required">*</text><text>合同是否规范</text></view>
  193 + </template>
  194 + </uni-list-item>
  195 +
  196 + <view class="footer">
  197 + <div class="total">
  198 + <div class="total-text">合计</div>
  199 + <div class="total-item" style="padding: 20rpx 0;">
  200 + <div class="total-item-text">数量</div>
  201 + <div class="total-item-price">{{ (totalQuantity || 0).toFixed(2) }}kg</div>
  202 + </div>
  203 + </div>
  204 + <button class="btn submit" type="primary" @click="onSubmit">提交</button>
  205 + </view>
  206 + </uni-list>
  207 + </scroll-view>
  208 +
  209 + <SingleSelectSheet :visible.sync="sheet.visible" :title="sheet.title" :options="sheet.options" v-model="sheet.value"
  210 + @confirm="onSheetConfirm" />
  211 + <RelateSelectSheet :visible.sync="relate.visible" :title="relate.title" :source="relate.source"
  212 + :display-fields="relate.display" :multiple="relate.multiple" :row-key="relate.rowKey"
  213 + :selectedKeys.sync="relate.selectedKeys" @confirm="onRelateConfirm" />
  214 + </view>
  215 +</template>
  216 +
  217 +<script>
  218 +import SingleSelectSheet from '@/components/single-select/index.vue'
  219 +import RelateSelectSheet from '@/components/relate-select/index.vue'
  220 +import ProductRel from './productRel.vue'
  221 +import CitySelector from '@/components/city-selector/index.vue'
  222 +import FileUpload from '@/components/file-upload/index.vue'
  223 +import { getContractApi, uploadStandardContract } from '@/api/contract'
  224 +import { getDicByCodes } from '@/utils/dic'
  225 +import { formatCurrencyToChinese } from '@/utils/common'
  226 +import { workshopQueryApi } from '@/api/devManage'
  227 +import { getArea } from '@/api/credit_manage.js'
  228 +
  229 +export default {
  230 + name: 'UploadContractForeignUnplan',
  231 + components: { SingleSelectSheet, RelateSelectSheet, ProductRel, CitySelector, FileUpload },
  232 + data() {
  233 + return {
  234 + id: '',
  235 + uploadType: 'standard',
  236 + fileInfo: { id: '', name: '' },
  237 + standardStandardized: '',
  238 + standardStandardizedName: '',
  239 + form: {
  240 + id: '',
  241 + code: '',
  242 + supplier: '',
  243 + supplierName: '',
  244 + buyer: '',
  245 + buyerName: '',
  246 + stockUpCompanyId: '',
  247 + stockUpCompanyName: '',
  248 + workshopId: '',
  249 + workshopName: '',
  250 + region: '',
  251 + regionName: '',
  252 + deptName: '',
  253 + deptId: '',
  254 + orderDate: '',
  255 + deliveryDate: '',
  256 + designatedConsignee: '',
  257 + specialTerms: '',
  258 + specialTermsName: '',
  259 + executionStandard: '',
  260 + executionStandardName: '',
  261 + executionStandardRemarks: '',
  262 + includesPackagingFee: false,
  263 + includesPackagingFeeName: '否',
  264 + includesTransportFee: false,
  265 + includesTransportFeeName: '否',
  266 + unit: '美元、公斤、美元/公斤',
  267 + totalAmountCapital: '',
  268 + depositInfo: '',
  269 + packagingRequirements: '',
  270 + paymentTerms: '',
  271 + transportMode: '',
  272 + destinationId: [],
  273 + destinationLabel: '',
  274 + specialInstructions: '',
  275 + remarks: '',
  276 + pieceWeightHead: '',
  277 + surface: '',
  278 + tolerance: '',
  279 + performance: '',
  280 + component: '',
  281 + packaging: ''
  282 + },
  283 + supplierList: [],
  284 + specialTermsList: [],
  285 + executionStandardList: [],
  286 + yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
  287 + sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
  288 + relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
  289 + totalQuantity: 0,
  290 + totalAmountIncludingTax: 0,
  291 + productLineList: [],
  292 + newProductLineList: [],
  293 + productList: [],
  294 + regionOptions: []
  295 + }
  296 + },
  297 + onLoad(query) {
  298 + this.id = (query && query.id) ? query.id : ''
  299 + this.uploadType = (query && query.uploadType) ? query.uploadType : 'standard'
  300 + },
  301 + created() {
  302 + this.loadSuppliers()
  303 + this.loadExtraOptions()
  304 + this.loadRegionOptions()
  305 + this.loadDetail()
  306 + this.$nextTick(() => {
  307 + if (Array.isArray(this.form.destinationId) && this.form.destinationId.length) {
  308 + this.initDestinationLabel()
  309 + }
  310 + })
  311 + },
  312 + methods: {
  313 + async loadRegionOptions() {
  314 + try {
  315 + const res = await getArea()
  316 + const list = res.data || []
  317 + this.regionOptions = (list || []).map(it => ({ label: it.name || '', value: it.id || '' }))
  318 + } catch (e) {
  319 + this.regionOptions = []
  320 + }
  321 + },
  322 + async loadDetail() {
  323 + if (!this.id) return
  324 + try {
  325 + const res = await getContractApi(this.id)
  326 + const data = res && res.data ? res.data : {}
  327 + const includesPackagingFeeName = data.includesPackagingFeeName || (data.includesPackagingFee ? '是' : '否')
  328 + const includesTransportFeeName = data.includesTransportFeeName || (data.includesTransportFee ? '是' : '否')
  329 + const m = { ...data, includesPackagingFeeName, includesTransportFeeName }
  330 + this.form = {
  331 + ...this.form,
  332 + id: m.id || '',
  333 + code: m.code || '',
  334 + supplier: m.supplier || '',
  335 + supplierName: m.supplierName || '',
  336 + buyer: m.buyer || (m.customer && m.customer.id) || '',
  337 + buyerName: m.buyerName || (m.customer && m.customer.name) || '',
  338 + stockUpCompanyId: m.stockUpCompanyId || '',
  339 + stockUpCompanyName: m.stockUpCompanyName || '',
  340 + orderDate: m.orderDate || '',
  341 + designatedConsignee: m.designatedConsignee || '',
  342 + specialTerms: m.specialTerms || '',
  343 + specialTermsName: m.specialTermsName || '',
  344 + executionStandard: m.executionStandard || '',
  345 + executionStandardName: m.executionStandardName || '',
  346 + executionStandardRemarks: m.executionStandardRemarks || '',
  347 + includesPackagingFee: !!m.includesPackagingFee,
  348 + includesPackagingFeeName,
  349 + includesTransportFee: !!m.includesTransportFee,
  350 + includesTransportFeeName,
  351 + unit: m.unit || this.form.unit,
  352 + totalAmountCapital: m.totalAmountCapital || '',
  353 + depositInfo: m.depositInfo || '',
  354 + packagingRequirements: m.packagingRequirements || '',
  355 + paymentTerms: m.paymentTerms || '',
  356 + transportMode: m.transportMode || '',
  357 + destinationId: (m.provinceId && m.cityId && m.districtId) ? [m.provinceId, m.cityId, m.districtId] : (Array.isArray(m.destinationId) ? m.destinationId : []),
  358 + destinationLabel: (m.provinceName && m.cityName && m.districtName) ? `${m.provinceName} / ${m.cityName} / ${m.districtName}` : (m.destinationLabel || ''),
  359 + specialInstructions: m.specialInstructions || '',
  360 + remarks: m.remarks || '',
  361 + pieceWeightHead: m.pieceWeightHead || '',
  362 + surface: m.surface || '',
  363 + tolerance: m.tolerance || '',
  364 + performance: m.performance || '',
  365 + component: m.component || '',
  366 + packaging: m.packaging || '',
  367 + workshopId: m.workshopId || '',
  368 + workshopName: m.workshopName || '',
  369 + region: m.region || '',
  370 + regionName: m.regionName || '',
  371 + deptName: m.deptName || '',
  372 + deptId: m.deptId || ''
  373 + }
  374 + this.fileInfo = { id: m.standardFileId || '', name: m.standardFileName || '' }
  375 + this.standardStandardized = (m.standardStandardized === true || m.standardStandardized === false) ? m.standardStandardized : ''
  376 + this.standardStandardizedName = (this.standardStandardized === true) ? '是' : (this.standardStandardized === false) ? '否' : ''
  377 + const lines = Array.isArray(m.contractDistributorLineList) ? m.contractDistributorLineList : []
  378 + this.productLineList = lines
  379 + this.onProductsChange(lines)
  380 + } catch (e) { }
  381 + },
  382 + async initDestinationLabel() {
  383 + const comp = this.$refs.citySelectorRef
  384 + if (comp && typeof comp.getLabel === 'function') {
  385 + const label = await comp.getLabel()
  386 + this.form.destinationLabel = label || ''
  387 + }
  388 + },
  389 + openCitySelector() {
  390 + this.$refs.citySelectorRef && this.$refs.citySelectorRef.open()
  391 + },
  392 + onCityChange(payload) {
  393 + const label = payload && payload.label != null ? payload.label : ''
  394 + this.form.destinationLabel = label
  395 + },
  396 + onProductsChange(products) {
  397 + const list = Array.isArray(products) ? products : []
  398 + this.newProductLineList = list
  399 + const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
  400 + const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
  401 + this.totalQuantity = sumQ
  402 + this.totalAmountIncludingTax = sumT
  403 + this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
  404 + },
  405 + async loadSuppliers() {
  406 + try {
  407 + const results = await getDicByCodes(['SUPPLIER'])
  408 + const items = results && results.SUPPLIER && results.SUPPLIER.data ? results.SUPPLIER.data : []
  409 + this.supplierList = items.map(it => ({ label: it.name, value: it.code }))
  410 + } catch (e) { this.supplierList = [] }
  411 + },
  412 + async loadExtraOptions() {
  413 + try {
  414 + const results = await getDicByCodes(['CONDITIONS_REQUIRED', 'APPLICABLE_STANDARD', 'CONTRACT_PRODUCT'])
  415 + const c1 = results && results.CONDITIONS_REQUIRED && results.CONDITIONS_REQUIRED.data ? results.CONDITIONS_REQUIRED.data : []
  416 + const c2 = results && results.APPLICABLE_STANDARD && results.APPLICABLE_STANDARD.data ? results.APPLICABLE_STANDARD.data : []
  417 + const c3 = results && results.CONTRACT_PRODUCT && results.CONTRACT_PRODUCT.data ? results.CONTRACT_PRODUCT.data : []
  418 + this.specialTermsList = c1.map(it => ({ label: it.name, value: it.code }))
  419 + this.executionStandardList = c2.map(it => ({ label: it.name, value: it.code }))
  420 + this.productList = c3.map(it => ({ label: it.name, value: it.code }))
  421 + } catch (e) {
  422 + this.specialTermsList = []
  423 + this.executionStandardList = []
  424 + this.productList = []
  425 + }
  426 + },
  427 + displayLabel(field) {
  428 + const m = this.form
  429 + const map = { supplierName: '请选择供方', buyerName: '请选择需方', workshopName: '请选择生产厂', regionName: '请选择区域' }
  430 + const val = m[field]
  431 + return val ? String(val) : map[field]
  432 + },
  433 + async openSheet(field) {
  434 + if (field === 'standardStandardized') {
  435 + const options = this.yesNoList
  436 + const current = this.standardStandardized
  437 + const match = (options || []).find(o => String(o.value) === String(current) || String(o.label) === String(current))
  438 + this.sheet = { ...this.sheet, visible: true, title: '合同是否规范', options, field, value: match ? match.value : '' }
  439 + return
  440 + }
  441 + const setSheet = (title, options) => {
  442 + const current = this.form[field]
  443 + const match = (options || []).find(o => String(o.label) === String(current) || String(o.value) === String(current))
  444 + this.sheet = { ...this.sheet, visible: true, title, options, field, value: match ? match.value : '' }
  445 + }
  446 + if (field === 'workshopId') {
  447 + const res = await workshopQueryApi({ pageIndex: 1, pageSize: 9999 })
  448 + const _data = res.data || {}
  449 + const list = _data.datas || (Array.isArray(_data) ? _data : [])
  450 + const opts = (list || []).map(it => ({ label: it.name, value: it.id }))
  451 + setSheet('生产厂', opts)
  452 + } else if (field === 'supplier') {
  453 + setSheet('供方', this.supplierList)
  454 + } else if (field === 'specialTerms') {
  455 + setSheet('特别条款要求', this.specialTermsList)
  456 + } else if (field === 'executionStandard') {
  457 + setSheet('执行标准', this.executionStandardList)
  458 + } else if (field === 'includesPackagingFee') {
  459 + setSheet('单价中是否已包含包装费', this.yesNoList)
  460 + } else if (field === 'includesTransportFee') {
  461 + setSheet('单价中是否已包含运费', this.yesNoList)
  462 + } else if (field === 'region') {
  463 + setSheet('区域', this.regionOptions)
  464 + }
  465 + },
  466 + onSheetConfirm({ value, label }) {
  467 + const field = this.sheet.field
  468 + if (!field) return
  469 + const v = (value === undefined || value === null) ? '' : value
  470 + if (field === 'standardStandardized') {
  471 + this.standardStandardized = v
  472 + this.standardStandardizedName = label || ''
  473 + return
  474 + }
  475 + this.form[field] = v
  476 + this.form[field + 'Name'] = label || ''
  477 + },
  478 + openRelate(fieldKey) {
  479 + let config = {}
  480 + if (fieldKey === 'buyer') {
  481 + config = { title: '需方', source: 'customer', rowKey: 'id', multiple: false, display: [{ label: '名称', field: 'name' }, { label: '编号', field: 'code' }, { label: '状态', field: 'available', format: v => (v ? '启用' : '停用') }] }
  482 + } else if (fieldKey === 'stockUpCompanyId') {
  483 + config = { title: '备货单位/人(生产标准)', source: 'customer', rowKey: 'id', multiple: false, display: [{ label: '姓名', field: 'name' }, { label: '编号', field: 'code' }, { label: '状态', field: 'available', format: v => (v ? '启用' : '停用') }] }
  484 + }
  485 + const selectedKeys = this.form[fieldKey] ? [this.form[fieldKey]] : []
  486 + this.sheet.visible = false
  487 + this.relate = { ...this.relate, title: config.title, source: config.source, display: config.display, multiple: config.multiple, rowKey: config.rowKey, selectedKeys, fieldKey }
  488 + this.$nextTick(() => { this.relate.visible = true })
  489 + },
  490 + onRelateConfirm({ items }) {
  491 + const _fieldKey = this.relate.fieldKey
  492 + const first = (items && items.length > 0) ? items[0] : null
  493 + this.form[_fieldKey] = (first && first.id) ? first.id : ''
  494 + if (_fieldKey === 'stockUpCompanyId') {
  495 + this.form.stockUpCompanyName = (first && first.name) ? first.name : ''
  496 + } else {
  497 + this.form[_fieldKey + 'Name'] = (first && first.name) ? first.name : ''
  498 + }
  499 + },
  500 + validateRequired() {
  501 + const checks = [
  502 + { key: 'code', label: '编号' },
  503 + { key: 'supplier', label: '供方' },
  504 + { key: 'buyer', label: '需方' },
  505 + { key: 'stockUpCompanyId', label: '备货单位/人(生产标准)' },
  506 + { key: 'orderDate', label: '订货日期' },
  507 + { key: 'unit', label: '单位' },
  508 + { key: 'workshopId', label: '生产厂' },
  509 + { key: 'region', label: '区域' },
  510 + { key: 'specialTerms', label: '特别条款要求' },
  511 + ]
  512 + for (const it of checks) {
  513 + const val = this.form[it.key]
  514 + const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
  515 + if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
  516 + }
  517 + const list = Array.isArray(this.newProductLineList) ? this.newProductLineList : []
  518 + if (list.length === 0) {
  519 + uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
  520 + }
  521 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  522 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  523 + for (const [idx, it] of list.entries()) {
  524 + if (
  525 + strEmpty(it.productName) ||
  526 + strEmpty(it.industry) ||
  527 + strEmpty(it.quality) ||
  528 + strEmpty(it.brand) ||
  529 + numEmpty(it.quantity) ||
  530 + numEmpty(it.unitPrice) ||
  531 + strEmpty(it.deliveryDate)
  532 + ) {
  533 + uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
  534 + }
  535 + }
  536 + if (this.$refs.productRel && !this.$refs.productRel.validate()) return false
  537 + return true
  538 + },
  539 + async onSubmit() {
  540 + if (!this.fileInfo.id) {
  541 + uni.showToast({ title: '请上传合同附件', icon: 'error' })
  542 + return
  543 + }
  544 + if (!this.standardStandardized && this.standardStandardized !== false) {
  545 + uni.showToast({ title: '请选择合同是否规范', icon: 'error' })
  546 + return
  547 + }
  548 + if (!this.validateRequired()) return
  549 + const confirmRes = await new Promise(resolve => {
  550 + uni.showModal({ title: '确认提交', content: '确定提交标准合同吗?', confirmText: '确定', cancelText: '取消', success: resolve })
  551 + })
  552 + if (!(confirmRes && confirmRes.confirm)) return
  553 + const clean = (obj) => {
  554 + const out = {}
  555 + Object.keys(obj || {}).forEach(k => {
  556 + const v = obj[k]
  557 + const isEmptyString = typeof v === 'string' && v.trim() === ''
  558 + const isUndef = v === undefined || v === null
  559 + const isNaNNumber = typeof v === 'number' && isNaN(v)
  560 + if (!(isEmptyString || isUndef || isNaNNumber)) out[k] = v
  561 + })
  562 + return out
  563 + }
  564 + const lines = (this.newProductLineList || []).map(it => clean(it))
  565 + const { destinationLabel, destinationId, ...formForSubmit } = this.form
  566 + const destination = destinationId && destinationId.length > 0 ? destinationId[destinationId.length - 1] : ''
  567 + const payload = clean({
  568 + ...formForSubmit,
  569 + id: this.form.id,
  570 + destination,
  571 + type: 'INTL_OPEN_SPEC_AGMT',
  572 + totalQuantity: this.totalQuantity,
  573 + totalAmountIncludingTax: this.totalAmountIncludingTax,
  574 + contractDistributorLineList: lines,
  575 + standardFileId: this.fileInfo.id,
  576 + standardFileName: this.fileInfo.name,
  577 + standardStandardized: this.standardStandardized,
  578 + })
  579 + try {
  580 + await uploadStandardContract(payload)
  581 + uni.showToast({ title: '提交成功', icon: 'none' })
  582 + setTimeout(() => { uni.redirectTo({ url: '/pages/contract_foreign_unplan/index' }) }, 400)
  583 + } catch (e) {
  584 + uni.showToast({ title: e.msg || '提交失败', icon: 'none' })
  585 + }
  586 + }
  587 + }
  588 +}
  589 +</script>
  590 +
  591 +<style lang="scss" scoped>
  592 +.total {
  593 + .total-text {
  594 + font-weight: 600;
  595 + font-size: 32rpx;
  596 + color: rgba(0, 0, 0, 0.9);
  597 + padding-bottom: 28rpx;
  598 + border-bottom: 2rpx solid #E7E7E7;
  599 + }
  600 +
  601 + .total-item {
  602 + display: flex;
  603 + align-items: center;
  604 + }
  605 +
  606 + .total-item-text {
  607 + font-weight: 400;
  608 + font-size: 28rpx;
  609 + color: rgba(0, 0, 0, 0.6);
  610 + line-height: 32rpx;
  611 + width: 240rpx;
  612 + padding: 12rpx 0;
  613 + }
  614 +
  615 + .total-item-price {
  616 + font-weight: 600;
  617 + font-size: 32rpx;
  618 + color: rgba(0, 0, 0, 0.9);
  619 + line-height: 32rpx;
  620 + }
  621 +
  622 + .text-red {
  623 + color: #D54941;
  624 + }
  625 +}
  626 +
  627 +.page {
  628 + display: flex;
  629 + flex-direction: column;
  630 + height: 100%;
  631 +}
  632 +
  633 +.scroll {
  634 + flex: 1;
  635 + padding: 12rpx 0 392rpx !important;
  636 +}
  637 +
  638 +.footer {
  639 + z-index: 2;
  640 + position: fixed;
  641 + left: 0;
  642 + right: 0;
  643 + bottom: 0;
  644 + padding: 32rpx;
  645 + padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
  646 + background: #fff;
  647 + box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
  648 +}
  649 +
  650 +.footer .btn {
  651 + height: 80rpx;
  652 + line-height: 80rpx;
  653 + border-radius: 12rpx;
  654 + font-size: 32rpx;
  655 +}
  656 +
  657 +.footer .submit {
  658 + background: $theme-primary;
  659 + color: #fff;
  660 +}
  661 +
  662 +.quality {
  663 + background-color: #fff;
  664 + display: flex;
  665 + align-items: center;
  666 + padding: 24rpx 32rpx;
  667 + border-bottom: 1rpx solid #f0f0f0;
  668 + margin-top: 20rpx;
  669 +
  670 + .title {
  671 + font-size: 32rpx;
  672 + color: rgba(0, 0, 0, 0.9);
  673 + font-weight: 600;
  674 + }
  675 +
  676 + .opCollapse {
  677 + color: rgba(0, 0, 0, 0.6);
  678 + width: 32rpx;
  679 + height: 28rpx;
  680 + margin-right: 16rpx;
  681 + }
  682 +}
  683 +
  684 +::v-deep .uni-list {
  685 + background: transparent;
  686 +}
  687 +
  688 +::v-deep .uni-list .uni-easyinput .uni-input-input {
  689 + color: rgba(0, 0, 0, 0.9);
  690 +}
  691 +
  692 +::v-deep .uni-list .uni-input-placeholder {
  693 + z-index: 1;
  694 +}
  695 +
  696 +::v-deep .uni-list .uni-input-input {
  697 + background-color: #ffffff;
  698 +}
  699 +
  700 +::v-deep .uni-list-item__extra-text {
  701 + font-size: 32rpx;
  702 +}
  703 +
  704 +::v-deep .uni-list-item__content-title {
  705 + font-size: 32rpx;
  706 + color: rgba(0, 0, 0, 0.9);
  707 +}
  708 +
  709 +::v-deep .uni-list-item__container {
  710 + padding: 32rpx;
  711 +}
  712 +
  713 +::v-deep .uni-list-item__container .uni-easyinput__placeholder-class {
  714 + font-size: 32rpx;
  715 + color: rgba(0, 0, 0, 0.4);
  716 +}
  717 +
  718 +::v-deep .uni-list-item__container .uni-easyinput__content {
  719 + border: none;
  720 + background-color: #ffffff !important;
  721 +}
  722 +
  723 +::v-deep .uni-list-item__container .uni-easyinput__content-input {
  724 + padding-left: 0 !important;
  725 + height: 48rpx;
  726 + line-height: 48rpx;
  727 + font-size: 32rpx;
  728 +}
  729 +
  730 +::v-deep .uni-list-item__container .item-title,
  731 +::v-deep .uni-list-item__container .uni-list-item__content {
  732 + flex: none;
  733 + min-height: 48rpx;
  734 + line-height: 48rpx;
  735 + font-size: 32rpx;
  736 + position: relative;
  737 + width: 210rpx;
  738 + margin-right: 32rpx;
  739 + color: rgba(0, 0, 0, 0.9);
  740 +}
  741 +
  742 +::v-deep .uni-list-item__container .item-title .required {
  743 + color: red;
  744 + position: absolute;
  745 + top: 50%;
  746 + transform: translateY(-50%);
  747 + left: -16rpx;
  748 +}
  749 +
  750 +::v-deep .uni-list-item.select-item.is-empty .uni-list-item__extra-text {
  751 + color: rgba(0, 0, 0, 0.4) !important;
  752 +}
  753 +
  754 +::v-deep .uni-list-item.select-item.is-filled .uni-list-item__extra-text {
  755 + color: rgba(0, 0, 0, 0.9) !important;
  756 +}
  757 +</style>
... ...
... ... @@ -351,9 +351,16 @@ export default {
351 351 url: '/pages/contract_stock/modify' + query
352 352 })
353 353 },
354   - uploadContract(id, type = 'formal'){
  354 + uploadContract(id, type = 'formal') {
355 355 if (!id) return
356 356 this.uploadId = id
  357 + if ((type === 'uploadParent' || type === 'upload') && this.detail?.canEdit) {
  358 + const query = `?id=${encodeURIComponent(id)}&uploadType=${encodeURIComponent(type)}`
  359 + uni.navigateTo({
  360 + url: '/pages/contract_stock/uploadStandard' + query
  361 + })
  362 + return
  363 + }
357 364 this.uploadType = type
358 365 this.$refs.uploadPopup.open()
359 366 },
... ... @@ -434,8 +441,8 @@ export default {
434 441 if (e === 'edit') return this.onEdit(btn && btn.params)
435 442 if (e === 'delete') return this.onDelete(btn && btn.params)
436 443 if (e === 'lock') return this.onLock()
437   - if (e === 'upload') return this.uploadContract(this.detail.id || '')
438   - if (e === 'uploadParent') return this.uploadContract(this.detail.parentId || '')
  444 + if (e === 'upload') return this.uploadContract(this.detail.id || '', 'upload')
  445 + if (e === 'uploadParent') return this.uploadContract(this.detail.parentId || '', 'uploadParent')
439 446 if (e === 'uploadStandard') return this.uploadContract(this.detail.id || '', 'standard')
440 447 if (e === 'audit1') return this.onAudit(this.detail.id || '', 'FORMAL_CONTRACT')
441 448 if (e === 'audit2') return this.onAudit(this.detail.parentId || '', 'FORMAL_CONTRACT')
... ...
  1 +<template>
  2 + <view class="page">
  3 + <scroll-view class="scroll" scroll-y>
  4 + <uni-list>
  5 + <uni-list-item title="编号">
  6 + <template v-slot:footer>
  7 + <uni-easyinput v-model="form.code" :inputBorder="false" disabled />
  8 + </template>
  9 + </uni-list-item>
  10 +
  11 + <uni-list-item class="select-item" :class="form.supplier ? 'is-filled' : 'is-empty'" clickable
  12 + @click="openSheet('supplier')" :rightText="displayLabel('supplierName')" showArrow>
  13 + <template v-slot:body>
  14 + <view class="item-title"><text class="required">*</text><text>供方</text></view>
  15 + </template>
  16 + </uni-list-item>
  17 +
  18 + <uni-list-item class="select-item" :class="form.buyer ? 'is-filled' : 'is-empty'" clickable
  19 + @click="openRelate('buyer')" :rightText="form.buyerName || '请选择需方'" showArrow>
  20 + <template v-slot:body>
  21 + <view class="item-title"><text class="required">*</text><text>需方</text></view>
  22 + </template>
  23 + </uni-list-item>
  24 +
  25 + <uni-list-item class="select-item" :class="form.stockUpCompanyId ? 'is-filled' : 'is-empty'" clickable
  26 + @click="openRelate('stockUpCompanyId')" :rightText="form.stockUpCompanyName || '请选择备货单位'" showArrow>
  27 + <template v-slot:body>
  28 + <view class="item-title"><text class="required">*</text><text>备货单位/人(生产标准)</text></view>
  29 + </template>
  30 + </uni-list-item>
  31 +
  32 + <uni-list-item class="select-item" :class="form.workshopId ? 'is-filled' : 'is-empty'" clickable
  33 + @click="openSheet('workshopId')" :rightText="form.workshopName || '请选择生产厂'" showArrow>
  34 + <template v-slot:body>
  35 + <view class="item-title"><text class="required">*</text><text>生产厂</text></view>
  36 + </template>
  37 + </uni-list-item>
  38 +
  39 + <uni-list-item title="订货日期">
  40 + <template v-slot:footer>
  41 + <uni-datetime-picker type="date" v-model="form.orderDate" />
  42 + </template>
  43 + </uni-list-item>
  44 +
  45 + <uni-list-item title="单位">
  46 + <template v-slot:footer>
  47 + <uni-easyinput v-model="form.unit" :inputBorder="false" disabled />
  48 + </template>
  49 + </uni-list-item>
  50 + <uni-list-item title="办事处">
  51 + <template v-slot:footer>
  52 + <uni-easyinput v-model="form.deptName" :inputBorder="false" disabled placeholder="自动获取" />
  53 + </template>
  54 + </uni-list-item>
  55 + <uni-list-item class="select-item" :class="form.region ? 'is-filled' : 'is-empty'" clickable
  56 + @click="openSheet('region')" :rightText="displayLabel('regionName')" showArrow>
  57 + <template v-slot:body>
  58 + <view class="item-title"><text class="required">*</text><text>区域</text></view>
  59 + </template>
  60 + </uni-list-item>
  61 +
  62 + <ProductRel ref="productRel" mode="add" :deliveryDate="form.orderDate" :deliveryDateBase="form.deliveryDate"
  63 + :list="productLineList" @change="onProductsChange" :options="productList" />
  64 +
  65 + <uni-list-item title="合计人民币金额(大写)">
  66 + <template v-slot:footer>
  67 + <uni-easyinput v-model="form.totalAmountCapital" placeholder="" :inputBorder="false" disabled />
  68 + </template>
  69 + </uni-list-item>
  70 + <uni-list-item title="交付定金、数额、时间">
  71 + <template v-slot:footer>
  72 + <uni-easyinput v-model="form.depositInfo" placeholder="请输入交付定金、数额、时间" :inputBorder="false" />
  73 + </template>
  74 + </uni-list-item>
  75 + <uni-list-item title="包装要求">
  76 + <template v-slot:footer>
  77 + <uni-easyinput v-model="form.packagingRequirements" placeholder="请输入包装要求" :inputBorder="false" />
  78 + </template>
  79 + </uni-list-item>
  80 + <uni-list-item title="付款方式、付款期限">
  81 + <template v-slot:footer>
  82 + <uni-easyinput v-model="form.paymentTerms" placeholder="请输入付款方式、付款期限" :inputBorder="false" />
  83 + </template>
  84 + </uni-list-item>
  85 + <uni-list-item title="运输方式">
  86 + <template v-slot:footer>
  87 + <uni-easyinput v-model="form.transportMode" placeholder="请输入运输方式" :inputBorder="false" />
  88 + </template>
  89 + </uni-list-item>
  90 + <uni-list-item class="select-item" :class="(Array.isArray(form.destinationId) && form.destinationId.length) ? 'is-filled' : 'is-empty'" clickable
  91 + @click="openCitySelector" :rightText="form.destinationLabel || '请选择'" showArrow>
  92 + <template v-slot:body>
  93 + <view class="item-title"><text>目的地</text></view>
  94 + <CitySelector ref="citySelectorRef" v-model="form.destinationId" @change="onCityChange" />
  95 + </template>
  96 + </uni-list-item>
  97 +
  98 + <uni-list-item class="select-item" :class="form.includesPackagingFeeName ? 'is-filled' : 'is-empty'" clickable
  99 + @click="openSheet('includesPackagingFee')" :rightText="form.includesPackagingFeeName || '请选择'" showArrow>
  100 + <template v-slot:body>
  101 + <view class="item-title"><text>单价中是否已包含包装费</text></view>
  102 + </template>
  103 + </uni-list-item>
  104 + <uni-list-item class="select-item" :class="form.includesTransportFeeName ? 'is-filled' : 'is-empty'" clickable
  105 + @click="openSheet('includesTransportFee')" :rightText="form.includesTransportFeeName || '请选择'" showArrow>
  106 + <template v-slot:body>
  107 + <view class="item-title"><text>单价中是否已包含运费</text></view>
  108 + </template>
  109 + </uni-list-item>
  110 + <uni-list-item title="需方指定收货人">
  111 + <template v-slot:footer>
  112 + <uni-easyinput v-model="form.designatedConsignee" placeholder="请输入需方指定收货人" :inputBorder="false" />
  113 + </template>
  114 + </uni-list-item>
  115 +
  116 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  117 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  118 + <template v-slot:body>
  119 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  120 + </template>
  121 + </uni-list-item>
  122 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  123 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  124 + <template v-slot:body>
  125 + <view class="item-title"><text>执行标准</text></view>
  126 + </template>
  127 + </uni-list-item>
  128 + <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
  129 + <template v-slot:footer>
  130 + <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注" :inputBorder="false" />
  131 + </template>
  132 + </uni-list-item>
  133 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
  134 + <template v-slot:footer>
  135 + <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
  136 + </template>
  137 + </uni-list-item>
  138 + <uni-list-item title="备注">
  139 + <template v-slot:footer>
  140 + <uni-easyinput v-model="form.remarks" placeholder="请输入备注" :inputBorder="false" maxlength="2000" />
  141 + </template>
  142 + </uni-list-item>
  143 +
  144 + <view class="quality">
  145 + <image class="opCollapse" src="/static/images/title.png" />
  146 + <text class="title">具体质量要求</text>
  147 + </view>
  148 + <uni-list-item title="件重条头">
  149 + <template v-slot:footer>
  150 + <uni-easyinput v-model="form.pieceWeightHead" placeholder="请输入" :inputBorder="false" />
  151 + </template>
  152 + </uni-list-item>
  153 + <uni-list-item title="表面">
  154 + <template v-slot:footer>
  155 + <uni-easyinput v-model="form.surface" placeholder="请输入" :inputBorder="false" />
  156 + </template>
  157 + </uni-list-item>
  158 + <uni-list-item title="公差">
  159 + <template v-slot:footer>
  160 + <uni-easyinput v-model="form.tolerance" placeholder="请输入" :inputBorder="false" />
  161 + </template>
  162 + </uni-list-item>
  163 + <uni-list-item title="性能">
  164 + <template v-slot:footer>
  165 + <uni-easyinput v-model="form.performance" placeholder="请输入" :inputBorder="false" />
  166 + </template>
  167 + </uni-list-item>
  168 + <uni-list-item title="成分">
  169 + <template v-slot:footer>
  170 + <uni-easyinput v-model="form.component" placeholder="请输入" :inputBorder="false" />
  171 + </template>
  172 + </uni-list-item>
  173 + <uni-list-item title="包装">
  174 + <template v-slot:footer>
  175 + <uni-easyinput v-model="form.packaging" placeholder="请输入" :inputBorder="false" />
  176 + </template>
  177 + </uni-list-item>
  178 +
  179 + <uni-list-item :title="uploadType === 'formal' ? '正式合同附件' : '标准合同附件'" style="margin-top: 20rpx;">
  180 + <template v-slot:footer>
  181 + <FileUpload v-model="fileInfo" />
  182 + </template>
  183 + </uni-list-item>
  184 + <uni-list-item class="select-item" :class="standardStandardizedName ? 'is-filled' : 'is-empty'" clickable
  185 + @click="openSheet('standardStandardized')" :rightText="standardStandardizedName || '请选择'" showArrow>
  186 + <template v-slot:body>
  187 + <view class="item-title"><text class="required">*</text><text>合同是否规范</text></view>
  188 + </template>
  189 + </uni-list-item>
  190 +
  191 + <view class="footer">
  192 + <div class="total">
  193 + <div class="total-text">合计</div>
  194 + <div class="total-item" style="padding: 20rpx 0;">
  195 + <div class="total-item-text">数量</div>
  196 + <div class="total-item-price">{{ (totalQuantity || 0).toFixed(2) }}kg</div>
  197 + </div>
  198 + </div>
  199 + <button class="btn submit" type="primary" @click="onSubmit">提交</button>
  200 + </view>
  201 + </uni-list>
  202 + </scroll-view>
  203 +
  204 + <SingleSelectSheet :visible.sync="sheet.visible" :title="sheet.title" :options="sheet.options" v-model="sheet.value"
  205 + @confirm="onSheetConfirm" />
  206 + <RelateSelectSheet :visible.sync="relate.visible" :title="relate.title" :source="relate.source"
  207 + :display-fields="relate.display" :multiple="relate.multiple" :row-key="relate.rowKey"
  208 + :selectedKeys.sync="relate.selectedKeys" @confirm="onRelateConfirm" />
  209 + </view>
  210 +</template>
  211 +
  212 +<script>
  213 +import SingleSelectSheet from '@/components/single-select/index.vue'
  214 +import RelateSelectSheet from '@/components/relate-select/index.vue'
  215 +import ProductRel from './productRel.vue'
  216 +import CitySelector from '@/components/city-selector/index.vue'
  217 +import FileUpload from '@/components/file-upload/index.vue'
  218 +import { getContractApi, uploadFormalContract, uploadStandardContract } from '@/api/contract'
  219 +import { getDicByCodes } from '@/utils/dic'
  220 +import { formatCurrencyToChinese } from '@/utils/common'
  221 +import { workshopQueryApi } from '@/api/devManage'
  222 +import { getArea } from '@/api/credit_manage.js'
  223 +
  224 +export default {
  225 + name: 'UploadContractStock',
  226 + components: { SingleSelectSheet, RelateSelectSheet, ProductRel, CitySelector, FileUpload },
  227 + data() {
  228 + return {
  229 + id: '',
  230 + uploadType: 'formal',
  231 + fileInfo: { id: '', name: '' },
  232 + standardStandardized: '',
  233 + standardStandardizedName: '',
  234 + form: {
  235 + id: '',
  236 + code: '',
  237 + supplier: '',
  238 + supplierName: '',
  239 + buyer: '',
  240 + buyerName: '',
  241 + stockUpCompanyId: '',
  242 + stockUpCompanyName: '',
  243 + workshopId: '',
  244 + workshopName: '',
  245 + deptName: '',
  246 + deptId: '',
  247 + region: '',
  248 + regionName: '',
  249 + orderDate: '',
  250 + deliveryDate: '',
  251 + designatedConsignee: '',
  252 + specialTerms: '',
  253 + specialTermsName: '',
  254 + executionStandard: '',
  255 + executionStandardName: '',
  256 + executionStandardRemarks: '',
  257 + includesPackagingFee: false,
  258 + includesPackagingFeeName: '否',
  259 + includesTransportFee: false,
  260 + includesTransportFeeName: '否',
  261 + unit: '元、公斤、元/公斤',
  262 + totalAmountCapital: '',
  263 + depositInfo: '',
  264 + packagingRequirements: '',
  265 + paymentTerms: '',
  266 + transportMode: '',
  267 + destinationId: [],
  268 + destinationLabel: '',
  269 + specialInstructions: '',
  270 + remarks: '',
  271 + pieceWeightHead: '',
  272 + surface: '',
  273 + tolerance: '',
  274 + performance: '',
  275 + component: '',
  276 + packaging: ''
  277 + },
  278 + supplierList: [],
  279 + specialTermsList: [],
  280 + executionStandardList: [],
  281 + yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
  282 + sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
  283 + relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
  284 + totalQuantity: 0,
  285 + totalAmountExcludingTax: 0,
  286 + totalAmountIncludingTax: 0,
  287 + productLineList: [],
  288 + newProductLineList: [],
  289 + productList: [],
  290 + regionOptions: [],
  291 + }
  292 + },
  293 + onLoad(query) {
  294 + this.id = (query && query.id) ? query.id : ''
  295 + this.uploadType = (query && query.uploadType) ? query.uploadType : 'formal'
  296 + },
  297 + created() {
  298 + this.loadSuppliers()
  299 + this.loadExtraOptions()
  300 + this.loadDetail()
  301 + this.loadRegionOptions()
  302 + this.$nextTick(() => {
  303 + if (Array.isArray(this.form.destinationId) && this.form.destinationId.length) {
  304 + this.initDestinationLabel()
  305 + }
  306 + })
  307 + },
  308 + methods: {
  309 + async loadRegionOptions() {
  310 + try {
  311 + const res = await getArea()
  312 + const list = res.data || []
  313 + this.regionOptions = (list || []).map(it => ({ label: it.name || '', value: it.id || '' }))
  314 + } catch (e) {
  315 + this.regionOptions = []
  316 + }
  317 + },
  318 + async loadDetail() {
  319 + if (!this.id) return
  320 + try {
  321 + const res = await getContractApi(this.id)
  322 + const data = res && res.data ? res.data : {}
  323 + const includesPackagingFeeName = data.includesPackagingFeeName || (data.includesPackagingFee ? '是' : '否')
  324 + const includesTransportFeeName = data.includesTransportFeeName || (data.includesTransportFee ? '是' : '否')
  325 + const m = { ...data, includesPackagingFeeName, includesTransportFeeName }
  326 + this.form = {
  327 + ...this.form,
  328 + id: m.id || '',
  329 + code: m.code || '',
  330 + supplier: m.supplier || '',
  331 + supplierName: m.supplierName || '',
  332 + buyer: m.buyer || (m.customer && m.customer.id) || '',
  333 + buyerName: m.buyerName || (m.customer && m.customer.name) || '',
  334 + stockUpCompanyId: m.stockUpCompanyId || '',
  335 + stockUpCompanyName: m.stockUpCompanyName || '',
  336 + deptName: m.deptName || '',
  337 + deptId: m.deptId || '',
  338 + region: m.region || '',
  339 + regionName: m.regionName || '',
  340 + orderDate: m.orderDate || '',
  341 + designatedConsignee: m.designatedConsignee || '',
  342 + specialTerms: m.specialTerms || '',
  343 + specialTermsName: m.specialTermsName || '',
  344 + executionStandard: m.executionStandard || '',
  345 + executionStandardName: m.executionStandardName || '',
  346 + executionStandardRemarks: m.executionStandardRemarks || '',
  347 + includesPackagingFee: !!m.includesPackagingFee,
  348 + includesPackagingFeeName,
  349 + includesTransportFee: !!m.includesTransportFee,
  350 + includesTransportFeeName,
  351 + unit: m.unit || this.form.unit,
  352 + totalAmountCapital: m.totalAmountCapital || '',
  353 + depositInfo: m.depositInfo || '',
  354 + packagingRequirements: m.packagingRequirements || '',
  355 + paymentTerms: m.paymentTerms || '',
  356 + transportMode: m.transportMode || '',
  357 + destinationId: (m.provinceId && m.cityId && m.districtId) ? [m.provinceId, m.cityId, m.districtId] : (Array.isArray(m.destinationId) ? m.destinationId : []),
  358 + destinationLabel: (m.provinceName && m.cityName && m.districtName) ? `${m.provinceName} / ${m.cityName} / ${m.districtName}` : (m.destinationLabel || ''),
  359 + specialInstructions: m.specialInstructions || '',
  360 + remarks: m.remarks || '',
  361 + pieceWeightHead: m.pieceWeightHead || '',
  362 + surface: m.surface || '',
  363 + tolerance: m.tolerance || '',
  364 + performance: m.performance || '',
  365 + component: m.component || '',
  366 + packaging: m.packaging || '',
  367 + workshopId: m.workshopId || '',
  368 + workshopName: m.workshopName || '',
  369 + }
  370 + const fileId = this.uploadType === 'formal' ? m.formalFileId : m.standardFileId
  371 + const fileName = this.uploadType === 'formal' ? m.formalFileName : m.standardFileName
  372 + const standardized = this.uploadType === 'formal' ? m.formalStandardized : m.standardStandardized
  373 + this.fileInfo = { id: fileId || '', name: fileName || '' }
  374 + this.standardStandardized = (standardized === true || standardized === false) ? standardized : ''
  375 + this.standardStandardizedName = (this.standardStandardized === true) ? '是' : (this.standardStandardized === false) ? '否' : ''
  376 + const lines = Array.isArray(m.contractDistributorLineList) ? m.contractDistributorLineList : []
  377 + this.productLineList = lines
  378 + this.onProductsChange(lines)
  379 + } catch (e) { }
  380 + },
  381 + async initDestinationLabel() {
  382 + const comp = this.$refs.citySelectorRef
  383 + if (comp && typeof comp.getLabel === 'function') {
  384 + const label = await comp.getLabel()
  385 + this.form.destinationLabel = label || ''
  386 + }
  387 + },
  388 + openCitySelector() {
  389 + this.$refs.citySelectorRef && this.$refs.citySelectorRef.open()
  390 + },
  391 + onCityChange(payload) {
  392 + const label = payload && payload.label != null ? payload.label : ''
  393 + this.form.destinationLabel = label
  394 + },
  395 + onProductsChange(products) {
  396 + const list = Array.isArray(products) ? products : []
  397 + this.newProductLineList = list
  398 + const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
  399 + const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
  400 + const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
  401 + this.totalQuantity = sumQ
  402 + this.totalAmountExcludingTax = sumE
  403 + this.totalAmountIncludingTax = sumT
  404 + this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
  405 + },
  406 + async loadSuppliers() {
  407 + try {
  408 + const results = await getDicByCodes(['SUPPLIER'])
  409 + const items = results && results.SUPPLIER && results.SUPPLIER.data ? results.SUPPLIER.data : []
  410 + this.supplierList = items.map(it => ({ label: it.name, value: it.code }))
  411 + } catch (e) { this.supplierList = [] }
  412 + },
  413 + async loadExtraOptions() {
  414 + try {
  415 + const results = await getDicByCodes(['CONDITIONS_REQUIRED', 'APPLICABLE_STANDARD', 'CONTRACT_PRODUCT'])
  416 + const c1 = results && results.CONDITIONS_REQUIRED && results.CONDITIONS_REQUIRED.data ? results.CONDITIONS_REQUIRED.data : []
  417 + const c2 = results && results.APPLICABLE_STANDARD && results.APPLICABLE_STANDARD.data ? results.APPLICABLE_STANDARD.data : []
  418 + const c3 = results && results.CONTRACT_PRODUCT && results.CONTRACT_PRODUCT.data ? results.CONTRACT_PRODUCT.data : []
  419 + this.specialTermsList = c1.map(it => ({ label: it.name, value: it.code }))
  420 + this.executionStandardList = c2.map(it => ({ label: it.name, value: it.code }))
  421 + this.productList = c3.map(it => ({ label: it.name, value: it.code }))
  422 + } catch (e) {
  423 + this.specialTermsList = []
  424 + this.executionStandardList = []
  425 + this.productList = []
  426 + }
  427 + },
  428 + displayLabel(field) {
  429 + const m = this.form
  430 + const map = { supplierName: '请选择供方', buyerName: '请选择需方', workshopName: '请选择生产厂', regionName: '请选择区域' }
  431 + const val = m[field]
  432 + return val ? String(val) : map[field]
  433 + },
  434 + async openSheet(field) {
  435 + if (field === 'standardStandardized') {
  436 + const options = this.yesNoList
  437 + const current = this.standardStandardized
  438 + const match = (options || []).find(o => String(o.value) === String(current) || String(o.label) === String(current))
  439 + this.sheet = { ...this.sheet, visible: true, title: '合同是否规范', options, field, value: match ? match.value : '' }
  440 + return
  441 + }
  442 + const setSheet = (title, options) => {
  443 + const current = this.form[field]
  444 + const match = (options || []).find(o => String(o.label) === String(current) || String(o.value) === String(current))
  445 + this.sheet = { ...this.sheet, visible: true, title, options, field, value: match ? match.value : '' }
  446 + }
  447 + if (field === 'workshopId') {
  448 + const res = await workshopQueryApi({ pageIndex: 1, pageSize: 9999 })
  449 + const _data = res.data || {}
  450 + const list = _data.datas || (Array.isArray(_data) ? _data : [])
  451 + const opts = (list || []).map(it => ({
  452 + label: it.name,
  453 + value: it.id
  454 + }))
  455 + setSheet('生产厂', opts)
  456 + } else if (field === 'supplier') {
  457 + setSheet('供方', this.supplierList)
  458 + } else if (field === 'specialTerms') {
  459 + setSheet('特别条款要求', this.specialTermsList)
  460 + } else if (field === 'executionStandard') {
  461 + setSheet('执行标准', this.executionStandardList)
  462 + } else if (field === 'includesPackagingFee') {
  463 + setSheet('单价中是否已包含包装费', this.yesNoList)
  464 + } else if (field === 'includesTransportFee') {
  465 + setSheet('单价中是否已包含运费', this.yesNoList)
  466 + } else if (field === 'region') {
  467 + setSheet('区域', this.regionOptions)
  468 + }
  469 + },
  470 + onSheetConfirm({ value, label }) {
  471 + const field = this.sheet.field
  472 + if (!field) return
  473 + const v = (value === undefined || value === null) ? '' : value
  474 + if (field === 'standardStandardized') {
  475 + this.standardStandardized = v
  476 + this.standardStandardizedName = label || ''
  477 + return
  478 + }
  479 + this.form[field] = v
  480 + this.form[field + 'Name'] = label || ''
  481 + },
  482 + openRelate(fieldKey) {
  483 + let config = {}
  484 + if (fieldKey === 'buyer') {
  485 + config = { title: '需方', source: 'customer', rowKey: 'id', multiple: false, display: [{ label: '名称', field: 'name' }, { label: '编号', field: 'code' }, { label: '状态', field: 'available', format: v => (v ? '启用' : '停用') }] }
  486 + } else if (fieldKey === 'stockUpCompanyId') {
  487 + config = { title: '备货单位/人(生产标准)', source: 'customer', rowKey: 'id', multiple: false, display: [{ label: '姓名', field: 'name' }, { label: '编号', field: 'code' }, { label: '状态', field: 'available', format: v => (v ? '启用' : '停用') }] }
  488 + }
  489 + const selectedKeys = this.form[fieldKey] ? [this.form[fieldKey]] : []
  490 + this.sheet.visible = false
  491 + this.relate = { ...this.relate, title: config.title, source: config.source, display: config.display, multiple: config.multiple, rowKey: config.rowKey, selectedKeys, fieldKey }
  492 + this.$nextTick(() => { this.relate.visible = true })
  493 + },
  494 + onRelateConfirm({ items }) {
  495 + const _fieldKey = this.relate.fieldKey
  496 + const first = (items && items.length > 0) ? items[0] : null
  497 + this.form[_fieldKey] = (first && first.id) ? first.id : ''
  498 + if (_fieldKey === 'stockUpCompanyId') {
  499 + this.form.stockUpCompanyName = (first && first.name) ? first.name : ''
  500 + } else {
  501 + this.form[_fieldKey + 'Name'] = (first && first.name) ? first.name : ''
  502 + }
  503 + },
  504 + validateRequired() {
  505 + const checks = [
  506 + { key: 'code', label: '编号' },
  507 + { key: 'supplier', label: '供方' },
  508 + { key: 'buyer', label: '需方' },
  509 + { key: 'orderDate', label: '订货日期' },
  510 + { key: 'unit', label: '单位' },
  511 + { key: 'workshopId', label: '生产厂' },
  512 + { key: 'specialTerms', label: '特别条款要求' },
  513 + ]
  514 + for (const it of checks) {
  515 + const val = this.form[it.key]
  516 + const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
  517 + if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
  518 + }
  519 + if (!this.$refs.productRel.validate()) return false
  520 + const list = Array.isArray(this.newProductLineList) ? this.newProductLineList : []
  521 + if (list.length === 0) {
  522 + uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
  523 + }
  524 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  525 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  526 + for (const [idx, it] of list.entries()) {
  527 + if (
  528 + strEmpty(it.productName) ||
  529 + strEmpty(it.industry) ||
  530 + strEmpty(it.quality) ||
  531 + strEmpty(it.brand) ||
  532 + numEmpty(it.quantity) ||
  533 + strEmpty(it.deliveryDate)
  534 + ) {
  535 + uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
  536 + }
  537 + }
  538 + return true
  539 + },
  540 + async onSubmit() {
  541 + if (!this.fileInfo.id) {
  542 + uni.showToast({ title: '请上传合同附件', icon: 'error' })
  543 + return
  544 + }
  545 + if (!this.standardStandardized && this.standardStandardized !== false) {
  546 + uni.showToast({ title: '请选择合同是否规范', icon: 'error' })
  547 + return
  548 + }
  549 + if (!this.validateRequired()) return
  550 + const confirmRes = await new Promise(resolve => {
  551 + uni.showModal({
  552 + title: '确认提交',
  553 + content: this.uploadType === 'formal' ? '确定提交正式合同吗?' : '确定提交标准合同吗?',
  554 + confirmText: '确定',
  555 + cancelText: '取消',
  556 + success: resolve
  557 + })
  558 + })
  559 + if (!(confirmRes && confirmRes.confirm)) return
  560 + const clean = (obj) => {
  561 + const out = {}
  562 + Object.keys(obj || {}).forEach(k => {
  563 + const v = obj[k]
  564 + const isEmptyString = typeof v === 'string' && v.trim() === ''
  565 + const isUndef = v === undefined || v === null
  566 + const isNaNNumber = typeof v === 'number' && isNaN(v)
  567 + if (!(isEmptyString || isUndef || isNaNNumber)) out[k] = v
  568 + })
  569 + return out
  570 + }
  571 + const lines = (this.newProductLineList || []).map(it => clean(it))
  572 + const { destinationLabel, destinationId, ...formForSubmit } = this.form
  573 + const destination = destinationId && destinationId.length > 0 ? destinationId[destinationId.length - 1] : ''
  574 + const fileIdKey = this.uploadType === 'formal' ? 'formalFileId' : 'standardFileId'
  575 + const fileNameKey = this.uploadType === 'formal' ? 'formalFileName' : 'standardFileName'
  576 + const standardizedKey = this.uploadType === 'formal' ? 'formalStandardized' : 'standardStandardized'
  577 + const payload = clean({
  578 + ...formForSubmit,
  579 + id: this.form.id,
  580 + destination,
  581 + type: 'DIST_STOCK_CONTRACT',
  582 + totalQuantity: this.totalQuantity,
  583 + totalAmountExcludingTax: this.totalAmountExcludingTax,
  584 + totalAmountIncludingTax: this.totalAmountIncludingTax,
  585 + contractDistributorLineList: lines,
  586 + [fileIdKey]: this.fileInfo.id,
  587 + [fileNameKey]: this.fileInfo.name,
  588 + [standardizedKey]: this.standardStandardized,
  589 + })
  590 + const api = this.uploadType === 'formal' ? uploadFormalContract : uploadStandardContract
  591 + try {
  592 + await api(payload)
  593 + uni.showToast({ title: '提交成功', icon: 'none' })
  594 + setTimeout(() => { uni.redirectTo({ url: '/pages/contract_stock/index' }) }, 400)
  595 + } catch (e) {
  596 + uni.showToast({ title: e.msg || '提交失败', icon: 'none' })
  597 + }
  598 + }
  599 + }
  600 +}
  601 +</script>
  602 +
  603 +<style lang="scss" scoped>
  604 +.total {
  605 + .total-text {
  606 + font-weight: 600;
  607 + font-size: 32rpx;
  608 + color: rgba(0, 0, 0, 0.9);
  609 + padding-bottom: 28rpx;
  610 + border-bottom: 2rpx solid #E7E7E7;
  611 + }
  612 +
  613 + .total-item {
  614 + display: flex;
  615 + align-items: center;
  616 + }
  617 +
  618 + .total-item-text {
  619 + font-weight: 400;
  620 + font-size: 28rpx;
  621 + color: rgba(0, 0, 0, 0.6);
  622 + line-height: 32rpx;
  623 + width: 240rpx;
  624 + padding: 12rpx 0;
  625 + }
  626 +
  627 + .total-item-price {
  628 + font-weight: 600;
  629 + font-size: 32rpx;
  630 + color: rgba(0, 0, 0, 0.9);
  631 + line-height: 32rpx;
  632 + }
  633 +
  634 + .text-red {
  635 + color: #D54941;
  636 + }
  637 +}
  638 +
  639 +.page {
  640 + display: flex;
  641 + flex-direction: column;
  642 + height: 100%;
  643 +}
  644 +
  645 +.scroll {
  646 + flex: 1;
  647 + padding: 12rpx 0 392rpx !important;
  648 +}
  649 +
  650 +.footer {
  651 + z-index: 2;
  652 + position: fixed;
  653 + left: 0;
  654 + right: 0;
  655 + bottom: 0;
  656 + padding: 32rpx;
  657 + padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
  658 + background: #fff;
  659 + box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
  660 +}
  661 +
  662 +.footer .btn {
  663 + height: 80rpx;
  664 + line-height: 80rpx;
  665 + border-radius: 12rpx;
  666 + font-size: 32rpx;
  667 +}
  668 +
  669 +.footer .submit {
  670 + background: $theme-primary;
  671 + color: #fff;
  672 +}
  673 +
  674 +.quality {
  675 + background-color: #fff;
  676 + display: flex;
  677 + align-items: center;
  678 + padding: 24rpx 32rpx;
  679 + border-bottom: 1rpx solid #f0f0f0;
  680 + margin-top: 20rpx;
  681 +
  682 + .title {
  683 + font-size: 32rpx;
  684 + color: rgba(0, 0, 0, 0.9);
  685 + font-weight: 600;
  686 + }
  687 +
  688 + .opCollapse {
  689 + color: rgba(0, 0, 0, 0.6);
  690 + width: 32rpx;
  691 + height: 28rpx;
  692 + margin-right: 16rpx;
  693 + }
  694 +}
  695 +
  696 +::v-deep .uni-list {
  697 + background: transparent;
  698 +}
  699 +
  700 +::v-deep .uni-list .uni-easyinput .uni-input-input {
  701 + color: rgba(0, 0, 0, 0.9);
  702 +}
  703 +
  704 +::v-deep .uni-list .uni-input-placeholder {
  705 + z-index: 1;
  706 +}
  707 +
  708 +::v-deep .uni-list .uni-input-input {
  709 + background-color: #ffffff;
  710 +}
  711 +
  712 +::v-deep .uni-list-item__extra-text {
  713 + font-size: 32rpx;
  714 +}
  715 +
  716 +::v-deep .uni-list-item__content-title {
  717 + font-size: 32rpx;
  718 + color: rgba(0, 0, 0, 0.9);
  719 +}
  720 +
  721 +::v-deep .uni-list-item__container {
  722 + padding: 32rpx;
  723 +}
  724 +
  725 +::v-deep .uni-list-item__container .uni-easyinput__placeholder-class {
  726 + font-size: 32rpx;
  727 + color: rgba(0, 0, 0, 0.4);
  728 +}
  729 +
  730 +::v-deep .uni-list-item__container .uni-easyinput__content {
  731 + border: none;
  732 + background-color: #ffffff !important;
  733 +}
  734 +
  735 +::v-deep .uni-list-item__container .uni-easyinput__content-input {
  736 + padding-left: 0 !important;
  737 + height: 48rpx;
  738 + line-height: 48rpx;
  739 + font-size: 32rpx;
  740 +}
  741 +
  742 +::v-deep .uni-list-item__container .item-title,
  743 +::v-deep .uni-list-item__container .uni-list-item__content {
  744 + flex: none;
  745 + min-height: 48rpx;
  746 + line-height: 48rpx;
  747 + font-size: 32rpx;
  748 + position: relative;
  749 + width: 210rpx;
  750 + margin-right: 32rpx;
  751 + color: rgba(0, 0, 0, 0.9);
  752 +}
  753 +
  754 +::v-deep .uni-list-item__container .item-title .required {
  755 + color: red;
  756 + position: absolute;
  757 + top: 50%;
  758 + transform: translateY(-50%);
  759 + left: -16rpx;
  760 +}
  761 +
  762 +::v-deep .uni-list-item.select-item.is-empty .uni-list-item__extra-text {
  763 + color: rgba(0, 0, 0, 0.4) !important;
  764 +}
  765 +
  766 +::v-deep .uni-list-item.select-item.is-filled .uni-list-item__extra-text {
  767 + color: rgba(0, 0, 0, 0.9) !important;
  768 +}
  769 +</style>
... ...
... ... @@ -372,6 +372,13 @@ export default {
372 372 uploadContract(id, type = 'formal') {
373 373 if (!id) return
374 374 this.uploadId = id
  375 + if (type === 'standard' && this.detail?.canEdit) {
  376 + const query = `?id=${encodeURIComponent(id)}&uploadType=${encodeURIComponent(type)}`
  377 + uni.navigateTo({
  378 + url: '/pages/contract_unplan/uploadStandard' + query
  379 + })
  380 + return
  381 + }
375 382 this.uploadType = type
376 383 this.$refs.uploadPopup.open()
377 384 },
... ...
  1 +<template>
  2 + <view class="page">
  3 + <scroll-view class="scroll" scroll-y>
  4 + <uni-list>
  5 + <uni-list-item title="编号">
  6 + <template v-slot:footer>
  7 + <uni-easyinput v-model="form.code" :inputBorder="false" disabled />
  8 + </template>
  9 + </uni-list-item>
  10 +
  11 + <uni-list-item class="select-item" :class="form.supplier ? 'is-filled' : 'is-empty'" clickable
  12 + @click="openSheet('supplier')" :rightText="displayLabel('supplierName')" showArrow>
  13 + <template v-slot:body>
  14 + <view class="item-title"><text class="required">*</text><text>供方</text></view>
  15 + </template>
  16 + </uni-list-item>
  17 +
  18 + <uni-list-item class="select-item" :class="form.buyer ? 'is-filled' : 'is-empty'" clickable
  19 + @click="openRelate('buyer')" :rightText="form.buyerName || '请选择需方'" showArrow>
  20 + <template v-slot:body>
  21 + <view class="item-title"><text class="required">*</text><text>需方</text></view>
  22 + </template>
  23 + </uni-list-item>
  24 +
  25 + <uni-list-item class="select-item" :class="form.stockUpCompanyId ? 'is-filled' : 'is-empty'" clickable
  26 + @click="openRelate('stockUpCompanyId')" :rightText="form.stockUpCompanyName || '请选择备货单位'" showArrow>
  27 + <template v-slot:body>
  28 + <view class="item-title"><text class="required">*</text><text>备货单位/人(生产标准)</text></view>
  29 + </template>
  30 + </uni-list-item>
  31 +
  32 + <uni-list-item class="select-item" :class="form.workshopId ? 'is-filled' : 'is-empty'" clickable
  33 + @click="openSheet('workshopId')" :rightText="form.workshopName || '请选择生产厂'" showArrow>
  34 + <template v-slot:body>
  35 + <view class="item-title"><text class="required">*</text><text>生产厂</text></view>
  36 + </template>
  37 + </uni-list-item>
  38 +
  39 + <uni-list-item title="订货日期">
  40 + <template v-slot:footer>
  41 + <uni-datetime-picker type="date" v-model="form.orderDate" />
  42 + </template>
  43 + </uni-list-item>
  44 +
  45 + <uni-list-item title="单位">
  46 + <template v-slot:footer>
  47 + <uni-easyinput v-model="form.unit" :inputBorder="false" disabled />
  48 + </template>
  49 + </uni-list-item>
  50 + <uni-list-item title="办事处">
  51 + <template v-slot:footer>
  52 + <uni-easyinput v-model="form.deptName" :inputBorder="false" disabled placeholder="自动获取" />
  53 + </template>
  54 + </uni-list-item>
  55 + <uni-list-item class="select-item" :class="form.region ? 'is-filled' : 'is-empty'" clickable
  56 + @click="openSheet('region')" :rightText="displayLabel('regionName')" showArrow>
  57 + <template v-slot:body>
  58 + <view class="item-title"><text class="required">*</text><text>区域</text></view>
  59 + </template>
  60 + </uni-list-item>
  61 +
  62 + <ProductRel ref="productRel" mode="add" :deliveryDate="form.orderDate" :deliveryDateBase="form.deliveryDate"
  63 + :list="productLineList" @change="onProductsChange" :options="productList" />
  64 +
  65 + <uni-list-item title="合计人民币金额(大写)">
  66 + <template v-slot:footer>
  67 + <uni-easyinput v-model="form.totalAmountCapital" placeholder="" :inputBorder="false" disabled />
  68 + </template>
  69 + </uni-list-item>
  70 + <uni-list-item title="交付定金、数额、时间">
  71 + <template v-slot:footer>
  72 + <uni-easyinput v-model="form.depositInfo" placeholder="请输入交付定金、数额、时间" :inputBorder="false" />
  73 + </template>
  74 + </uni-list-item>
  75 + <uni-list-item title="包装要求">
  76 + <template v-slot:footer>
  77 + <uni-easyinput v-model="form.packagingRequirements" placeholder="请输入包装要求" :inputBorder="false" />
  78 + </template>
  79 + </uni-list-item>
  80 + <uni-list-item title="付款方式、付款期限">
  81 + <template v-slot:footer>
  82 + <uni-easyinput v-model="form.paymentTerms" placeholder="请输入付款方式、付款期限" :inputBorder="false" />
  83 + </template>
  84 + </uni-list-item>
  85 + <uni-list-item title="运输方式">
  86 + <template v-slot:footer>
  87 + <uni-easyinput v-model="form.transportMode" placeholder="请输入运输方式" :inputBorder="false" />
  88 + </template>
  89 + </uni-list-item>
  90 + <uni-list-item class="select-item"
  91 + :class="(Array.isArray(form.destinationId) && form.destinationId.length) ? 'is-filled' : 'is-empty'" clickable
  92 + @click="openCitySelector" :rightText="form.destinationLabel || '请选择'" showArrow>
  93 + <template v-slot:body>
  94 + <view class="item-title"><text>目的地</text></view>
  95 + <CitySelector ref="citySelectorRef" v-model="form.destinationId" @change="onCityChange" />
  96 + </template>
  97 + </uni-list-item>
  98 +
  99 + <uni-list-item class="select-item" :class="form.includesPackagingFeeName ? 'is-filled' : 'is-empty'" clickable
  100 + @click="openSheet('includesPackagingFee')" :rightText="form.includesPackagingFeeName || '请选择'" showArrow>
  101 + <template v-slot:body>
  102 + <view class="item-title"><text>单价中是否已包含包装费</text></view>
  103 + </template>
  104 + </uni-list-item>
  105 + <uni-list-item class="select-item" :class="form.includesTransportFeeName ? 'is-filled' : 'is-empty'" clickable
  106 + @click="openSheet('includesTransportFee')" :rightText="form.includesTransportFeeName || '请选择'" showArrow>
  107 + <template v-slot:body>
  108 + <view class="item-title"><text>单价中是否已包含运费</text></view>
  109 + </template>
  110 + </uni-list-item>
  111 + <uni-list-item title="需方指定收货人">
  112 + <template v-slot:footer>
  113 + <uni-easyinput v-model="form.designatedConsignee" placeholder="请输入需方指定收货人" :inputBorder="false" />
  114 + </template>
  115 + </uni-list-item>
  116 +
  117 + <uni-list-item class="select-item" :class="form.specialTermsName ? 'is-filled' : 'is-empty'" clickable
  118 + @click="openSheet('specialTerms')" :rightText="form.specialTermsName || '请选择'" showArrow>
  119 + <template v-slot:body>
  120 + <view class="item-title"><text class="required">*</text><text>特别条款要求</text></view>
  121 + </template>
  122 + </uni-list-item>
  123 + <uni-list-item class="select-item" :class="form.executionStandardName ? 'is-filled' : 'is-empty'" clickable
  124 + @click="openSheet('executionStandard')" :rightText="form.executionStandardName || '请选择'" showArrow>
  125 + <template v-slot:body>
  126 + <view class="item-title"><text>执行标准</text></view>
  127 + </template>
  128 + </uni-list-item>
  129 + <uni-list-item v-if="form.executionStandard === 'OTHER'" title="其他">
  130 + <template v-slot:footer>
  131 + <uni-easyinput v-model="form.executionStandardRemarks" placeholder="请输入其他标准备注" :inputBorder="false" />
  132 + </template>
  133 + </uni-list-item>
  134 + <uni-list-item title="特别说明" style="margin-top: 20rpx;">
  135 + <template v-slot:footer>
  136 + <uni-easyinput v-model="form.specialInstructions" placeholder="请输入特别说明" :inputBorder="false" />
  137 + </template>
  138 + </uni-list-item>
  139 + <uni-list-item title="备注">
  140 + <template v-slot:footer>
  141 + <uni-easyinput v-model="form.remarks" placeholder="请输入备注" :inputBorder="false" maxlength="2000" />
  142 + </template>
  143 + </uni-list-item>
  144 +
  145 + <view class="quality">
  146 + <image class="opCollapse" src="/static/images/title.png" />
  147 + <text class="title">具体质量要求</text>
  148 + </view>
  149 + <uni-list-item title="件重条头">
  150 + <template v-slot:footer>
  151 + <uni-easyinput v-model="form.pieceWeightHead" placeholder="请输入" :inputBorder="false" />
  152 + </template>
  153 + </uni-list-item>
  154 + <uni-list-item title="表面">
  155 + <template v-slot:footer>
  156 + <uni-easyinput v-model="form.surface" placeholder="请输入" :inputBorder="false" />
  157 + </template>
  158 + </uni-list-item>
  159 + <uni-list-item title="公差">
  160 + <template v-slot:footer>
  161 + <uni-easyinput v-model="form.tolerance" placeholder="请输入" :inputBorder="false" />
  162 + </template>
  163 + </uni-list-item>
  164 + <uni-list-item title="性能">
  165 + <template v-slot:footer>
  166 + <uni-easyinput v-model="form.performance" placeholder="请输入" :inputBorder="false" />
  167 + </template>
  168 + </uni-list-item>
  169 + <uni-list-item title="成分">
  170 + <template v-slot:footer>
  171 + <uni-easyinput v-model="form.component" placeholder="请输入" :inputBorder="false" />
  172 + </template>
  173 + </uni-list-item>
  174 + <uni-list-item title="包装">
  175 + <template v-slot:footer>
  176 + <uni-easyinput v-model="form.packaging" placeholder="请输入" :inputBorder="false" />
  177 + </template>
  178 + </uni-list-item>
  179 +
  180 + <uni-list-item :title="uploadType === 'formal' ? '正式合同附件' : '标准合同附件'" style="margin-top: 20rpx;">
  181 + <template v-slot:footer>
  182 + <FileUpload v-model="fileInfo" />
  183 + </template>
  184 + </uni-list-item>
  185 + <uni-list-item class="select-item" :class="standardStandardizedName ? 'is-filled' : 'is-empty'" clickable
  186 + @click="openSheet('standardStandardized')" :rightText="standardStandardizedName || '请选择'" showArrow>
  187 + <template v-slot:body>
  188 + <view class="item-title"><text class="required">*</text><text>合同是否规范</text></view>
  189 + </template>
  190 + </uni-list-item>
  191 +
  192 + <view class="footer">
  193 + <div class="total">
  194 + <div class="total-text">合计</div>
  195 + <div class="total-item" style="padding: 20rpx 0;">
  196 + <div class="total-item-text">数量</div>
  197 + <div class="total-item-price">{{ (totalQuantity || 0).toFixed(2) }}kg</div>
  198 + </div>
  199 + </div>
  200 + <button class="btn submit" type="primary" @click="onSubmit">提交</button>
  201 + </view>
  202 + </uni-list>
  203 + </scroll-view>
  204 +
  205 + <SingleSelectSheet :visible.sync="sheet.visible" :title="sheet.title" :options="sheet.options" v-model="sheet.value"
  206 + @confirm="onSheetConfirm" />
  207 + <RelateSelectSheet :visible.sync="relate.visible" :title="relate.title" :source="relate.source"
  208 + :display-fields="relate.display" :multiple="relate.multiple" :row-key="relate.rowKey"
  209 + :selectedKeys.sync="relate.selectedKeys" @confirm="onRelateConfirm" />
  210 + </view>
  211 +</template>
  212 +
  213 +<script>
  214 +import SingleSelectSheet from '@/components/single-select/index.vue'
  215 +import RelateSelectSheet from '@/components/relate-select/index.vue'
  216 +import ProductRel from './productRel.vue'
  217 +import CitySelector from '@/components/city-selector/index.vue'
  218 +import FileUpload from '@/components/file-upload/index.vue'
  219 +import { getContractApi, uploadFormalContract, uploadStandardContract } from '@/api/contract'
  220 +import { getDicByCodes } from '@/utils/dic'
  221 +import { formatCurrencyToChinese } from '@/utils/common'
  222 +import { workshopQueryApi } from '@/api/devManage'
  223 +import { getArea } from '@/api/credit_manage.js'
  224 +
  225 +export default {
  226 + name: 'UploadContractUnplan',
  227 + components: { SingleSelectSheet, RelateSelectSheet, ProductRel, CitySelector, FileUpload },
  228 + data() {
  229 + return {
  230 + id: '',
  231 + uploadType: 'formal',
  232 + fileInfo: { id: '', name: '' },
  233 + standardStandardized: '',
  234 + standardStandardizedName: '',
  235 + form: {
  236 + id: '',
  237 + code: '',
  238 + supplier: '',
  239 + supplierName: '',
  240 + buyer: '',
  241 + buyerName: '',
  242 + stockUpCompanyId: '',
  243 + stockUpCompanyName: '',
  244 + workshopId: '',
  245 + workshopName: '',
  246 + deptName: '',
  247 + deptId: '',
  248 + region: '',
  249 + regionName: '',
  250 + orderDate: '',
  251 + deliveryDate: '',
  252 + designatedConsignee: '',
  253 + specialTerms: '',
  254 + specialTermsName: '',
  255 + executionStandard: '',
  256 + executionStandardName: '',
  257 + executionStandardRemarks: '',
  258 + includesPackagingFee: false,
  259 + includesPackagingFeeName: '否',
  260 + includesTransportFee: false,
  261 + includesTransportFeeName: '否',
  262 + unit: '元、公斤、元/公斤',
  263 + totalAmountCapital: '',
  264 + depositInfo: '',
  265 + packagingRequirements: '',
  266 + paymentTerms: '',
  267 + transportMode: '',
  268 + destinationId: [],
  269 + destinationLabel: '',
  270 + specialInstructions: '',
  271 + remarks: '',
  272 + pieceWeightHead: '',
  273 + surface: '',
  274 + tolerance: '',
  275 + performance: '',
  276 + component: '',
  277 + packaging: ''
  278 + },
  279 + supplierList: [],
  280 + specialTermsList: [],
  281 + executionStandardList: [],
  282 + yesNoList: [{ label: '是', value: true }, { label: '否', value: false }],
  283 + sheet: { visible: false, title: '请选择', field: '', options: [], value: '' },
  284 + relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
  285 + totalQuantity: 0,
  286 + totalAmountExcludingTax: 0,
  287 + totalAmountIncludingTax: 0,
  288 + productLineList: [],
  289 + newProductLineList: [],
  290 + productList: [],
  291 + regionOptions: [],
  292 + }
  293 + },
  294 + onLoad(query) {
  295 + this.id = (query && query.id) ? query.id : ''
  296 + this.uploadType = (query && query.uploadType) ? query.uploadType : 'formal'
  297 + },
  298 + created() {
  299 + this.loadSuppliers()
  300 + this.loadExtraOptions()
  301 + this.loadDetail()
  302 + this.loadRegionOptions()
  303 + this.$nextTick(() => {
  304 + if (Array.isArray(this.form.destinationId) && this.form.destinationId.length) {
  305 + this.initDestinationLabel()
  306 + }
  307 + })
  308 + },
  309 + methods: {
  310 + async loadRegionOptions() {
  311 + try {
  312 + const res = await getArea()
  313 + const list = res.data || []
  314 + this.regionOptions = (list || []).map(it => ({ label: it.name || '', value: it.id || '' }))
  315 + } catch (e) {
  316 + this.regionOptions = []
  317 + }
  318 + },
  319 + async loadDetail() {
  320 + if (!this.id) return
  321 + try {
  322 + const res = await getContractApi(this.id)
  323 + const data = res && res.data ? res.data : {}
  324 + const includesPackagingFeeName = data.includesPackagingFeeName || (data.includesPackagingFee ? '是' : '否')
  325 + const includesTransportFeeName = data.includesTransportFeeName || (data.includesTransportFee ? '是' : '否')
  326 + const m = { ...data, includesPackagingFeeName, includesTransportFeeName }
  327 + this.form = {
  328 + ...this.form,
  329 + id: m.id || '',
  330 + code: m.code || '',
  331 + supplier: m.supplier || '',
  332 + supplierName: m.supplierName || '',
  333 + buyer: m.buyer || (m.customer && m.customer.id) || '',
  334 + buyerName: m.buyerName || (m.customer && m.customer.name) || '',
  335 + stockUpCompanyId: m.stockUpCompanyId || '',
  336 + stockUpCompanyName: m.stockUpCompanyName || '',
  337 + deptName: m.deptName || '',
  338 + deptId: m.deptId || '',
  339 + region: m.region || '',
  340 + regionName: m.regionName || '',
  341 + orderDate: m.orderDate || '',
  342 + designatedConsignee: m.designatedConsignee || '',
  343 + specialTerms: m.specialTerms || '',
  344 + specialTermsName: m.specialTermsName || '',
  345 + executionStandard: m.executionStandard || '',
  346 + executionStandardName: m.executionStandardName || '',
  347 + executionStandardRemarks: m.executionStandardRemarks || '',
  348 + includesPackagingFee: !!m.includesPackagingFee,
  349 + includesPackagingFeeName,
  350 + includesTransportFee: !!m.includesTransportFee,
  351 + includesTransportFeeName,
  352 + unit: m.unit || this.form.unit,
  353 + totalAmountCapital: m.totalAmountCapital || '',
  354 + depositInfo: m.depositInfo || '',
  355 + packagingRequirements: m.packagingRequirements || '',
  356 + paymentTerms: m.paymentTerms || '',
  357 + transportMode: m.transportMode || '',
  358 + destinationId: (m.provinceId && m.cityId && m.districtId) ? [m.provinceId, m.cityId, m.districtId] : (Array.isArray(m.destinationId) ? m.destinationId : []),
  359 + destinationLabel: (m.provinceName && m.cityName && m.districtName) ? `${m.provinceName} / ${m.cityName} / ${m.districtName}` : (m.destinationLabel || ''),
  360 + specialInstructions: m.specialInstructions || '',
  361 + remarks: m.remarks || '',
  362 + pieceWeightHead: m.pieceWeightHead || '',
  363 + surface: m.surface || '',
  364 + tolerance: m.tolerance || '',
  365 + performance: m.performance || '',
  366 + component: m.component || '',
  367 + packaging: m.packaging || '',
  368 + workshopId: m.workshopId || '',
  369 + workshopName: m.workshopName || '',
  370 + }
  371 + const fileId = this.uploadType === 'formal' ? m.formalFileId : m.standardFileId
  372 + const fileName = this.uploadType === 'formal' ? m.formalFileName : m.standardFileName
  373 + const standardized = this.uploadType === 'formal' ? m.formalStandardized : m.standardStandardized
  374 + this.fileInfo = { id: fileId || '', name: fileName || '' }
  375 + this.standardStandardized = (standardized === true || standardized === false) ? standardized : ''
  376 + this.standardStandardizedName = (this.standardStandardized === true) ? '是' : (this.standardStandardized === false) ? '否' : ''
  377 + const lines = Array.isArray(m.contractDistributorLineList) ? m.contractDistributorLineList : []
  378 + this.productLineList = lines
  379 + this.onProductsChange(lines)
  380 + } catch (e) { }
  381 + },
  382 + async initDestinationLabel() {
  383 + const comp = this.$refs.citySelectorRef
  384 + if (comp && typeof comp.getLabel === 'function') {
  385 + const label = await comp.getLabel()
  386 + this.form.destinationLabel = label || ''
  387 + }
  388 + },
  389 + openCitySelector() {
  390 + this.$refs.citySelectorRef && this.$refs.citySelectorRef.open()
  391 + },
  392 + onCityChange(payload) {
  393 + const label = payload && payload.label != null ? payload.label : ''
  394 + this.form.destinationLabel = label
  395 + },
  396 + onProductsChange(products) {
  397 + const list = Array.isArray(products) ? products : []
  398 + this.newProductLineList = list
  399 + const sumQ = list.reduce((acc, it) => acc + (parseFloat(it.quantity) || 0), 0)
  400 + const sumE = list.reduce((acc, it) => acc + (parseFloat(it.amountExcludingTax) || 0), 0)
  401 + const sumT = list.reduce((acc, it) => acc + (parseFloat(it.totalAmount) || 0), 0)
  402 + this.totalQuantity = sumQ
  403 + this.totalAmountExcludingTax = sumE
  404 + this.totalAmountIncludingTax = sumT
  405 + this.form.totalAmountCapital = formatCurrencyToChinese(sumT)
  406 + },
  407 + async loadSuppliers() {
  408 + try {
  409 + const results = await getDicByCodes(['SUPPLIER'])
  410 + const items = results && results.SUPPLIER && results.SUPPLIER.data ? results.SUPPLIER.data : []
  411 + this.supplierList = items.map(it => ({ label: it.name, value: it.code }))
  412 + } catch (e) { this.supplierList = [] }
  413 + },
  414 + async loadExtraOptions() {
  415 + try {
  416 + const results = await getDicByCodes(['CONDITIONS_REQUIRED', 'APPLICABLE_STANDARD', 'CONTRACT_PRODUCT'])
  417 + const c1 = results && results.CONDITIONS_REQUIRED && results.CONDITIONS_REQUIRED.data ? results.CONDITIONS_REQUIRED.data : []
  418 + const c2 = results && results.APPLICABLE_STANDARD && results.APPLICABLE_STANDARD.data ? results.APPLICABLE_STANDARD.data : []
  419 + const c3 = results && results.CONTRACT_PRODUCT && results.CONTRACT_PRODUCT.data ? results.CONTRACT_PRODUCT.data : []
  420 + this.specialTermsList = c1.map(it => ({ label: it.name, value: it.code }))
  421 + this.executionStandardList = c2.map(it => ({ label: it.name, value: it.code }))
  422 + this.productList = c3.map(it => ({ label: it.name, value: it.code }))
  423 + } catch (e) {
  424 + this.specialTermsList = []
  425 + this.executionStandardList = []
  426 + this.productList = []
  427 + }
  428 + },
  429 + displayLabel(field) {
  430 + const m = this.form
  431 + const map = { supplierName: '请选择供方', buyerName: '请选择需方', workshopName: '请选择生产厂', regionName: '请选择区域' }
  432 + const val = m[field]
  433 + return val ? String(val) : map[field]
  434 + },
  435 + async openSheet(field) {
  436 + if (field === 'standardStandardized') {
  437 + const options = this.yesNoList
  438 + const current = this.standardStandardized
  439 + const match = (options || []).find(o => String(o.value) === String(current) || String(o.label) === String(current))
  440 + this.sheet = { ...this.sheet, visible: true, title: '合同是否规范', options, field, value: match ? match.value : '' }
  441 + return
  442 + }
  443 + const setSheet = (title, options) => {
  444 + const current = this.form[field]
  445 + const match = (options || []).find(o => String(o.label) === String(current) || String(o.value) === String(current))
  446 + this.sheet = { ...this.sheet, visible: true, title, options, field, value: match ? match.value : '' }
  447 + }
  448 + if (field === 'workshopId') {
  449 + const res = await workshopQueryApi({ pageIndex: 1, pageSize: 9999 })
  450 + const _data = res.data || {}
  451 + const list = _data.datas || (Array.isArray(_data) ? _data : [])
  452 + const opts = (list || []).map(it => ({ label: it.name, value: it.id }))
  453 + setSheet('生产厂', opts)
  454 + } else if (field === 'supplier') {
  455 + setSheet('供方', this.supplierList)
  456 + } else if (field === 'specialTerms') {
  457 + setSheet('特别条款要求', this.specialTermsList)
  458 + } else if (field === 'executionStandard') {
  459 + setSheet('执行标准', this.executionStandardList)
  460 + } else if (field === 'includesPackagingFee') {
  461 + setSheet('单价中是否已包含包装费', this.yesNoList)
  462 + } else if (field === 'includesTransportFee') {
  463 + setSheet('单价中是否已包含运费', this.yesNoList)
  464 + } else if (field === 'region') {
  465 + setSheet('区域', this.regionOptions)
  466 + }
  467 + },
  468 + onSheetConfirm({ value, label }) {
  469 + const field = this.sheet.field
  470 + if (!field) return
  471 + const v = (value === undefined || value === null) ? '' : value
  472 + if (field === 'standardStandardized') {
  473 + this.standardStandardized = v
  474 + this.standardStandardizedName = label || ''
  475 + return
  476 + }
  477 + this.form[field] = v
  478 + this.form[field + 'Name'] = label || ''
  479 + },
  480 + openRelate(fieldKey) {
  481 + let config = {}
  482 + if (fieldKey === 'buyer') {
  483 + config = { title: '需方', source: 'customer', rowKey: 'id', multiple: false, display: [{ label: '名称', field: 'name' }, { label: '编号', field: 'code' }, { label: '状态', field: 'available', format: v => (v ? '启用' : '停用') }] }
  484 + } else if (fieldKey === 'stockUpCompanyId') {
  485 + config = { title: '备货单位/人(生产标准)', source: 'customer', rowKey: 'id', multiple: false, display: [{ label: '姓名', field: 'name' }, { label: '编号', field: 'code' }, { label: '状态', field: 'available', format: v => (v ? '启用' : '停用') }] }
  486 + }
  487 + const selectedKeys = this.form[fieldKey] ? [this.form[fieldKey]] : []
  488 + this.sheet.visible = false
  489 + this.relate = { ...this.relate, title: config.title, source: config.source, display: config.display, multiple: config.multiple, rowKey: config.rowKey, selectedKeys, fieldKey }
  490 + this.$nextTick(() => { this.relate.visible = true })
  491 + },
  492 + onRelateConfirm({ items }) {
  493 + const _fieldKey = this.relate.fieldKey
  494 + const first = (items && items.length > 0) ? items[0] : null
  495 + this.form[_fieldKey] = (first && first.id) ? first.id : ''
  496 + if (_fieldKey === 'stockUpCompanyId') {
  497 + this.form.stockUpCompanyName = (first && first.name) ? first.name : ''
  498 + } else {
  499 + this.form[_fieldKey + 'Name'] = (first && first.name) ? first.name : ''
  500 + }
  501 + },
  502 + validateRequired() {
  503 + const checks = [
  504 + { key: 'code', label: '编号' },
  505 + { key: 'supplier', label: '供方' },
  506 + { key: 'buyer', label: '需方' },
  507 + { key: 'orderDate', label: '订货日期' },
  508 + { key: 'unit', label: '单位' },
  509 + { key: 'workshopId', label: '生产厂' },
  510 + { key: 'specialTerms', label: '特别条款要求' },
  511 + ]
  512 + for (const it of checks) {
  513 + const val = this.form[it.key]
  514 + const empty = (val === undefined || val === null || (typeof val === 'string' && val.trim() === '') || (typeof val === 'number' && isNaN(val)))
  515 + if (empty) { uni.showToast({ title: `请先选择${it.label}`, icon: 'none' }); return false }
  516 + }
  517 + if (this.$refs.productRel && !this.$refs.productRel.validate()) return false
  518 + const list = Array.isArray(this.newProductLineList) ? this.newProductLineList : []
  519 + if (list.length === 0) {
  520 + uni.showToast({ title: '请至少添加一条产品明细', icon: 'none' }); return false
  521 + }
  522 + const strEmpty = (v) => (v === undefined || v === null || (typeof v === 'string' && v.trim() === ''))
  523 + const numEmpty = (v) => (v === undefined || v === null || v === '' || (typeof v === 'number' && isNaN(v)))
  524 + for (const [idx, it] of list.entries()) {
  525 + if (
  526 + strEmpty(it.productName) ||
  527 + strEmpty(it.industry) ||
  528 + strEmpty(it.quality) ||
  529 + strEmpty(it.brand) ||
  530 + numEmpty(it.quantity) ||
  531 + strEmpty(it.unitPrice) ||
  532 + strEmpty(it.deliveryDate)
  533 + ) {
  534 + uni.showToast({ title: `第${idx + 1}条明细未完整填写`, icon: 'none' }); return false
  535 + }
  536 + }
  537 + return true
  538 + },
  539 + async onSubmit() {
  540 + if (!this.fileInfo.id) {
  541 + uni.showToast({ title: '请上传合同附件', icon: 'error' })
  542 + return
  543 + }
  544 + if (!this.standardStandardized && this.standardStandardized !== false) {
  545 + uni.showToast({ title: '请选择合同是否规范', icon: 'error' })
  546 + return
  547 + }
  548 + if (!this.validateRequired()) return
  549 + const confirmRes = await new Promise(resolve => {
  550 + uni.showModal({
  551 + title: '确认提交',
  552 + content: this.uploadType === 'formal' ? '确定提交正式合同吗?' : '确定提交标准合同吗?',
  553 + confirmText: '确定',
  554 + cancelText: '取消',
  555 + success: resolve
  556 + })
  557 + })
  558 + if (!(confirmRes && confirmRes.confirm)) return
  559 + const clean = (obj) => {
  560 + const out = {}
  561 + Object.keys(obj || {}).forEach(k => {
  562 + const v = obj[k]
  563 + const isEmptyString = typeof v === 'string' && v.trim() === ''
  564 + const isUndef = v === undefined || v === null
  565 + const isNaNNumber = typeof v === 'number' && isNaN(v)
  566 + if (!(isEmptyString || isUndef || isNaNNumber)) out[k] = v
  567 + })
  568 + return out
  569 + }
  570 + const lines = (this.newProductLineList || []).map(it => clean(it))
  571 + const { destinationLabel, destinationId, ...formForSubmit } = this.form
  572 + const destination = destinationId && destinationId.length > 0 ? destinationId[destinationId.length - 1] : ''
  573 + const fileIdKey = this.uploadType === 'formal' ? 'formalFileId' : 'standardFileId'
  574 + const fileNameKey = this.uploadType === 'formal' ? 'formalFileName' : 'standardFileName'
  575 + const standardizedKey = this.uploadType === 'formal' ? 'formalStandardized' : 'standardStandardized'
  576 + const payload = clean({
  577 + ...formForSubmit,
  578 + id: this.form.id,
  579 + destination,
  580 + type: 'DRAFT_DIST_AGMT',
  581 + totalQuantity: this.totalQuantity,
  582 + totalAmountExcludingTax: this.totalAmountExcludingTax,
  583 + totalAmountIncludingTax: this.totalAmountIncludingTax,
  584 + contractDistributorLineList: lines,
  585 + [fileIdKey]: this.fileInfo.id,
  586 + [fileNameKey]: this.fileInfo.name,
  587 + [standardizedKey]: this.standardStandardized,
  588 + })
  589 + const api = this.uploadType === 'formal' ? uploadFormalContract : uploadStandardContract
  590 + try {
  591 + await api(payload)
  592 + uni.showToast({ title: '提交成功', icon: 'none' })
  593 + setTimeout(() => { uni.redirectTo({ url: '/pages/contract_unplan/index' }) }, 400)
  594 + } catch (e) {
  595 + uni.showToast({ title: e.msg || '提交失败', icon: 'none' })
  596 + }
  597 + }
  598 + }
  599 +}
  600 +</script>
  601 +
  602 +<style lang="scss" scoped>
  603 +.total {
  604 + .total-text {
  605 + font-weight: 600;
  606 + font-size: 32rpx;
  607 + color: rgba(0, 0, 0, 0.9);
  608 + padding-bottom: 28rpx;
  609 + border-bottom: 2rpx solid #E7E7E7;
  610 + }
  611 +
  612 + .total-item {
  613 + display: flex;
  614 + align-items: center;
  615 + }
  616 +
  617 + .total-item-text {
  618 + font-weight: 400;
  619 + font-size: 28rpx;
  620 + color: rgba(0, 0, 0, 0.6);
  621 + line-height: 32rpx;
  622 + width: 240rpx;
  623 + padding: 12rpx 0;
  624 + }
  625 +
  626 + .total-item-price {
  627 + font-weight: 600;
  628 + font-size: 32rpx;
  629 + color: rgba(0, 0, 0, 0.9);
  630 + line-height: 32rpx;
  631 + }
  632 +
  633 + .text-red {
  634 + color: #D54941;
  635 + }
  636 +}
  637 +
  638 +.page {
  639 + display: flex;
  640 + flex-direction: column;
  641 + height: 100%;
  642 +}
  643 +
  644 +.scroll {
  645 + flex: 1;
  646 + padding: 12rpx 0 392rpx !important;
  647 +}
  648 +
  649 +.footer {
  650 + z-index: 2;
  651 + position: fixed;
  652 + left: 0;
  653 + right: 0;
  654 + bottom: 0;
  655 + padding: 32rpx;
  656 + padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
  657 + background: #fff;
  658 + box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
  659 +}
  660 +
  661 +.footer .btn {
  662 + height: 80rpx;
  663 + line-height: 80rpx;
  664 + border-radius: 12rpx;
  665 + font-size: 32rpx;
  666 +}
  667 +
  668 +.footer .submit {
  669 + background: $theme-primary;
  670 + color: #fff;
  671 +}
  672 +
  673 +.quality {
  674 + background-color: #fff;
  675 + display: flex;
  676 + align-items: center;
  677 + padding: 24rpx 32rpx;
  678 + border-bottom: 1rpx solid #f0f0f0;
  679 + margin-top: 20rpx;
  680 +
  681 + .title {
  682 + font-size: 32rpx;
  683 + color: rgba(0, 0, 0, 0.9);
  684 + font-weight: 600;
  685 + }
  686 +
  687 + .opCollapse {
  688 + color: rgba(0, 0, 0, 0.6);
  689 + width: 32rpx;
  690 + height: 28rpx;
  691 + margin-right: 16rpx;
  692 + }
  693 +}
  694 +
  695 +::v-deep .uni-list {
  696 + background: transparent;
  697 +}
  698 +
  699 +::v-deep .uni-list .uni-easyinput .uni-input-input {
  700 + color: rgba(0, 0, 0, 0.9);
  701 +}
  702 +
  703 +::v-deep .uni-list .uni-input-placeholder {
  704 + z-index: 1;
  705 +}
  706 +
  707 +::v-deep .uni-list .uni-input-input {
  708 + background-color: #ffffff;
  709 +}
  710 +
  711 +::v-deep .uni-list-item__extra-text {
  712 + font-size: 32rpx;
  713 +}
  714 +
  715 +::v-deep .uni-list-item__content-title {
  716 + font-size: 32rpx;
  717 + color: rgba(0, 0, 0, 0.9);
  718 +}
  719 +
  720 +::v-deep .uni-list-item__container {
  721 + padding: 32rpx;
  722 +}
  723 +
  724 +::v-deep .uni-list-item__container .uni-easyinput__placeholder-class {
  725 + font-size: 32rpx;
  726 + color: rgba(0, 0, 0, 0.4);
  727 +}
  728 +
  729 +::v-deep .uni-list-item__container .uni-easyinput__content {
  730 + border: none;
  731 + background-color: #ffffff !important;
  732 +}
  733 +
  734 +::v-deep .uni-list-item__container .uni-easyinput__content-input {
  735 + padding-left: 0 !important;
  736 + height: 48rpx;
  737 + line-height: 48rpx;
  738 + font-size: 32rpx;
  739 +}
  740 +
  741 +::v-deep .uni-list-item__container .item-title,
  742 +::v-deep .uni-list-item__container .uni-list-item__content {
  743 + flex: none;
  744 + min-height: 48rpx;
  745 + line-height: 48rpx;
  746 + font-size: 32rpx;
  747 + position: relative;
  748 + width: 210rpx;
  749 + margin-right: 32rpx;
  750 + color: rgba(0, 0, 0, 0.9);
  751 +}
  752 +
  753 +::v-deep .uni-list-item__container .item-title .required {
  754 + color: red;
  755 + position: absolute;
  756 + top: 50%;
  757 + transform: translateY(-50%);
  758 + left: -16rpx;
  759 +}
  760 +
  761 +::v-deep .uni-list-item.select-item.is-empty .uni-list-item__extra-text {
  762 + color: rgba(0, 0, 0, 0.4) !important;
  763 +}
  764 +
  765 +::v-deep .uni-list-item.select-item.is-filled .uni-list-item__extra-text {
  766 + color: rgba(0, 0, 0, 0.9) !important;
  767 +}
  768 +</style>
... ...