Commit 29f6d426cc266f7caadcbf145f7d3a33e2d5a284

Authored by gesilong
2 parents 362b7ef1 2532e300

Merge branch 'cjerp-contract-1.0' into test_cjerp

Too many changes to show.

To preserve performance only 14 of 18 files are displayed.

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