Commit 9ee36fd91be4dbc934c843de563f44ec023336eb

Authored by 史婷婷
1 parent e9181994

feat: 补货单-新增暂存

... ... @@ -696,6 +696,14 @@
696 696 "navigationBarBackgroundColor": "#ffffff",
697 697 "navigationBarTextStyle": "black"
698 698 }
  699 + },
  700 + {
  701 + "path": "pages/replenishment_order/add",
  702 + "style": {
  703 + "navigationBarTitleText": "新增补货单",
  704 + "navigationBarBackgroundColor": "#ffffff",
  705 + "navigationBarTextStyle": "black"
  706 + }
699 707 }
700 708 ],
701 709 "subPackages": [
... ...
  1 +<template>
  2 + <view class="page">
  3 + <scroll-view class="scroll" scroll-y>
  4 + <uni-list>
  5 + <view class="section">
  6 + <uni-list-item class="select-item" :class="form.purchaseOrderName ? 'is-filled' : 'is-empty'" clickable
  7 + @click="openRelate('purchaseOrderName')" :rightText="form.purchaseOrderName || '请选择订单编号'" showArrow>
  8 + <template v-slot:body>
  9 + <view class="item-title"><text class="required">*</text><text>订单编号</text></view>
  10 + </template>
  11 + </uni-list-item>
  12 + <uni-list-item title="补货单编号">
  13 + <template v-slot:footer>
  14 + <view class="readonly-text">{{ form.code }}</view>
  15 + </template>
  16 + </uni-list-item>
  17 + <uni-list-item title="分厂">
  18 + <template v-slot:footer>
  19 + <view class="readonly-text">{{ form.workshopName }}</view>
  20 + </template>
  21 + </uni-list-item>
  22 + <uni-list-item title="办事处">
  23 + <template v-slot:footer>
  24 + <view class="readonly-text">{{ form.deptName }}</view>
  25 + </template>
  26 + </uni-list-item>
  27 + <uni-list-item title="区域">
  28 + <template v-slot:footer>
  29 + <view class="readonly-text">{{ form.regionName }}</view>
  30 + </template>
  31 + </uni-list-item>
  32 + <uni-list-item title="购货单位">
  33 + <template v-slot:footer>
  34 + <view class="readonly-text">{{ form.customerName }}</view>
  35 + </template>
  36 + </uni-list-item>
  37 + <uni-list-item title="原计划发货日期">
  38 + <template v-slot:footer>
  39 + <uni-datetime-picker type="date" v-model="form.originPlanShipDate" :end="maxDeliveryDate" />
  40 + </template>
  41 + </uni-list-item>
  42 + </view>
  43 +
  44 + <!-- 产品 -->
  45 + <view class="section2">
  46 + <Product mode="add" :list="initPurchaseOrderLineList" @change="purchaseOrderLineListChange"
  47 + :orderDate="form.orderDate" />
  48 + </view>
  49 +
  50 + </uni-list>
  51 + </scroll-view>
  52 +
  53 + <view class="footer">
  54 + <view class="view-total">
  55 + <view class="head">合计</view>
  56 + <view class="row">
  57 + <view class="row2">
  58 + <text class="label">需发</text><text class="value">{{ form.totalQuantity }}</text>
  59 + </view>
  60 + <view class="row2">
  61 + <text class="label">实发</text><text class="value">{{ form.totalShippedQuantity }}</text>
  62 + </view>
  63 + </view>
  64 + <view class="row">
  65 + <text class="label">需求补货</text><text class="value">{{ form.totalSupplementaryQuantity }}</text>
  66 + </view>
  67 + </view>
  68 + <button class="btn submit" type="primary" @click="onSubmit">提交</button>
  69 + </view>
  70 + <SingleSelectSheet :visible.sync="sheet.visible" :title="sheet.title" :options="sheet.options" v-model="sheet.value"
  71 + @confirm="onSheetConfirm" />
  72 + <RelateSelectSheet :visible.sync="relate.visible" :title="relate.title" :source="relate.source"
  73 + :display-fields="relate.display" :multiple="relate.multiple" :row-key="relate.rowKey"
  74 + :selectedKeys.sync="relate.selectedKeys" :source-extra="{ queryType: 'REPLENISHMENT' }"
  75 + @confirm="onRelateConfirm" />
  76 + </view>
  77 +</template>
  78 +
  79 +<script>
  80 +import { loadOrderApi } from '@/api/change_list.js'
  81 +import { createApi, getCodeApi } from '@/api/replenishment_order.js'
  82 +import Product from './product.vue'
  83 +import SingleSelectSheet from '@/components/single-select/index.vue'
  84 +import RelateSelectSheet from '@/components/relate-select/index.vue'
  85 +import { getDicName } from '@/utils/dic.js'
  86 +import { getDicByCodes } from '@/utils/dic'
  87 +
  88 +export default {
  89 + name: 'ReplenishmentOrderAdd',
  90 + components: { Product, SingleSelectSheet, RelateSelectSheet },
  91 + data() {
  92 + return {
  93 + form: {
  94 + purchaseOrderId: '',
  95 + id: '',
  96 + // 订单基础信息
  97 + purchaseOrderName: '',
  98 + customerName: '',
  99 + customerId: '',
  100 + workshopName: '',
  101 + workshopId: '',
  102 + originPlanShipDate: '',
  103 + deptName: '',
  104 + deptId: '',
  105 + totalQuantity: '',
  106 + totalShippedQuantity: '',
  107 + totalSupplementaryQuantity: '',
  108 + code: '',
  109 + // 默认当前日期 格式为 yyyy-MM-dd
  110 + orderDate: new Date().toISOString().substring(0, 10),
  111 +
  112 + },
  113 + initPurchaseOrderLineList: [],
  114 + dicOptions: { SUPPLIER: [], APPLICABLE_STANDARD: [] },
  115 + sheet: { visible: false, title: '请选择', options: [], value: '', field: '' },
  116 + relate: { visible: false, title: '选择', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' },
  117 + maxDeliveryDate: new Date().toISOString().substring(0, 10),
  118 + }
  119 + },
  120 + onLoad() {
  121 + this.loadDicOptions()
  122 + },
  123 + methods: {
  124 + loadDicOptions() {
  125 + const dicCodes = ['SUPPLIER', 'APPLICABLE_STANDARD']
  126 + return getDicByCodes(dicCodes).then(results => {
  127 + this.dicOptions.SUPPLIER = results.SUPPLIER && results.SUPPLIER.data ? results.SUPPLIER.data : []
  128 + this.dicOptions.APPLICABLE_STANDARD = results.APPLICABLE_STANDARD && results.APPLICABLE_STANDARD.data ? results.APPLICABLE_STANDARD.data : []
  129 + this.refreshStandardName()
  130 + }).catch(() => { this.dicOptions = { SUPPLIER: [], APPLICABLE_STANDARD: [] } })
  131 + },
  132 + async loadDetail(id) {
  133 + try {
  134 + const res = await getDetailApi(id)
  135 + const m = res.data || {}
  136 + const next = { ...this.form, ...m }
  137 + next.id = m.id || m.code || id
  138 + next.purchaseOrderLineList = Array.isArray(m.purchaseOrderLineList) ? m.purchaseOrderLineList.map(x => ({ ...x })) : []
  139 + this.form = next;
  140 + this.initPurchaseOrderLineList = next.purchaseOrderLineList || [];
  141 + this.refreshStandardName()
  142 + } catch (e) {
  143 + uni.showToast({ title: '加载失败', icon: 'none' })
  144 + }
  145 + },
  146 + refreshStandardName() {
  147 + const est = (this.dicOptions.APPLICABLE_STANDARD || []).find(o => String(o.code) === String(this.form.executionStandard))
  148 + this.form.executionStandardName = est ? (est.name || '') : (this.form.executionStandardName || '')
  149 + },
  150 + openSheet(field) {
  151 + if (field === 'executionStandard') {
  152 + const options = (this.dicOptions.APPLICABLE_STANDARD || []).map(it => ({ label: it.name || '', value: it.code || '' }))
  153 + const current = this.form.executionStandard
  154 + const match = options.find(o => String(o.value) === String(current))
  155 + this.sheet = { ...this.sheet, visible: true, title: '执行标准', options, field, value: match ? match.value : '' }
  156 + }
  157 + },
  158 + onSheetConfirm({ value, label }) {
  159 + const field = this.sheet.field
  160 + if (field === 'executionStandard') {
  161 + this.form.executionStandard = value || ''
  162 + this.form.executionStandardName = label || ''
  163 + }
  164 + this.sheet.visible = false
  165 + },
  166 + openRelate(fieldKey) {
  167 + let config = {}
  168 + if (fieldKey === 'purchaseOrderName') {
  169 + config = {
  170 + title: '订单',
  171 + source: 'orderAssoc',
  172 + rowKey: 'id',
  173 + multiple: false,
  174 + display: [
  175 + { label: '订单编号', field: 'orderNo' },
  176 + { label: '订货单位', field: 'orderingUnitName' },
  177 + { label: '生产厂', field: 'workshopName' },
  178 + { label: '办事处', field: 'deptName' },
  179 + { label: '总数量(kg)', field: 'totalQuantity' },
  180 + { label: '订货日期', field: 'orderDate' },
  181 + { label: '下单人', field: 'contractCreateByName' }
  182 + ]
  183 + }
  184 + }
  185 + const currentId = this.form && (this.form.id || this.form.code)
  186 + const selectedKeys = currentId ? [currentId] : []
  187 + this.sheet.visible = false
  188 + this.relate.title = config.title
  189 + this.relate.source = config.source
  190 + this.relate.display = config.display
  191 + this.relate.multiple = config.multiple
  192 + this.relate.rowKey = config.rowKey
  193 + this.relate.selectedKeys = selectedKeys
  194 + this.relate.fieldKey = fieldKey
  195 + this.$nextTick(() => { this.relate.visible = true })
  196 + },
  197 + async onRelateConfirm({ items }) {
  198 + const _fieldKey = this.relate.fieldKey
  199 + const first = (items && items.length > 0) ? items[0] : null
  200 + if (_fieldKey === 'purchaseOrderName') {
  201 + const id = first && (first.id || first.code)
  202 + if (id) {
  203 + try {
  204 + const res = await loadOrderApi([id]);
  205 + const res2 = await getCodeApi(res.data[0].id || '');
  206 +
  207 + const data = res && res.data ? res.data : null;
  208 + const data2 = res2 && res2.data ? res2.data : null;
  209 + const item = Array.isArray(data) ? (data[0] || {}) : (data || {})
  210 + const next = { ...this.form, ...item, code: data2 };
  211 + next.purchaseOrderName = next.orderNo || '';
  212 + next.purchaseOrderId = next.id || '';
  213 + next.customerName = next.orderingUnitName || '';
  214 + next.customerId = next.orderingUnit || '';
  215 + next.id = '';
  216 + next.originPlanShipDate = '';
  217 + next.totalShippedQuantity = '';
  218 + next.totalSupplementaryQuantity = '';
  219 + this.form = next;
  220 + const lines = Array.isArray(next.purchaseOrderLineList) ? next.purchaseOrderLineList.map(x => ({ ...x, purchaseOrderLineId: x.id, shippedQuantity: x.assessmentExceedsAgreement, supplementaryQuantity: '', id: '' })) : []
  221 + this.initPurchaseOrderLineList = lines
  222 + this.calculateSummary(lines)
  223 + this.refreshStandardName()
  224 + } catch (e) {
  225 + }
  226 + } else {
  227 + }
  228 + }
  229 + },
  230 + getDicName: getDicName,
  231 + validateRequired() {
  232 + const checks = [
  233 + { key: 'orderNo', label: '订单编号' }
  234 + ]
  235 + for (const it of checks) {
  236 + const val = this.form[it.key]
  237 + if (val === undefined || val === null || String(val).trim() === '') {
  238 + uni.showToast({ title: `请先选择${it.label}`, icon: 'none' })
  239 + return false
  240 + }
  241 + }
  242 + return true
  243 + },
  244 + validateLineListRequired() {
  245 + const list = Array.isArray(this.form.purchaseOrderLineList) ? this.form.purchaseOrderLineList : []
  246 + if (list.length === 0) {
  247 + uni.showToast({ title: '请先添加产品', icon: 'none' })
  248 + return false
  249 + }
  250 + const fields = [
  251 + { key: 'industry', label: '行业' },
  252 + { key: 'quality', label: '品质' },
  253 + { key: 'brand', label: '牌号' },
  254 + { key: 'quantity', label: '数量' },
  255 + { key: 'deliveryDate', label: '发货日期' },
  256 + ]
  257 + for (let i = 0; i < list.length; i++) {
  258 + const it = list[i] || {}
  259 + for (const f of fields) {
  260 + const v = it && it[f.key]
  261 + if (v === undefined || v === null || String(v).trim() === '') {
  262 + uni.showToast({ title: `产品第${i + 1}条:${f.label}不能为空!`, icon: 'none' })
  263 + return false
  264 + }
  265 + }
  266 + const has = (v) => v !== undefined && v !== null && String(v).trim() !== ''
  267 + if (has(it.thicknessTolPos) && has(it.thicknessTolNeg)) {
  268 + const pos = Number(it.thicknessTolPos)
  269 + const neg = Number(it.thicknessTolNeg)
  270 + if (!(pos > neg)) {
  271 + uni.showToast({ title: `产品第${i + 1}条:厚度公差上限需大于下限`, icon: 'none' })
  272 + return false
  273 + }
  274 + }
  275 + if (has(it.widthTolPos) && has(it.widthTolNeg)) {
  276 + const pos = Number(it.widthTolPos)
  277 + const neg = Number(it.widthTolNeg)
  278 + if (!(pos > neg)) {
  279 + uni.showToast({ title: `产品第${i + 1}条:宽度公差上限需大于下限`, icon: 'none' })
  280 + return false
  281 + }
  282 + }
  283 + if (has(it.lengthTolPos) && has(it.lengthTolNeg)) {
  284 + const pos = Number(it.lengthTolPos)
  285 + const neg = Number(it.lengthTolNeg)
  286 + if (!(pos > neg)) {
  287 + uni.showToast({ title: `产品第${i + 1}条:长度公差上限需大于下限`, icon: 'none' })
  288 + return false
  289 + }
  290 + }
  291 + }
  292 + return true
  293 + },
  294 + async onSubmit() {
  295 + if (!this.validateRequired()) return
  296 + if (!this.validateLineListRequired()) return
  297 + const payload = { ...this.form }
  298 + payload.orderSpecList = payload.purchaseOrderLineList || [];
  299 + delete payload.purchaseOrderLineList;
  300 + console.log('onSubmit__payload', payload)
  301 + return
  302 + try {
  303 + await createApi(payload)
  304 + uni.showToast({ title: '保存成功', icon: 'success' })
  305 + setTimeout(() => { uni.redirectTo({ url: '/pages/change_list/index' }) }, 300)
  306 + } catch (e) {
  307 + uni.showToast({ title: (e && e.msg) || '保存失败', icon: 'none' })
  308 + }
  309 + },
  310 + calculateSummary(list) {
  311 + const summary = (list || []).reduce((acc, it) => {
  312 + const qty = Number(it.supplementaryQuantity) || 0
  313 + const shipped = Number(it.shippedQuantity) || 0
  314 + const orderQty = Number(it.quantity) || 0
  315 + acc.totalSupplementaryQuantity += qty
  316 + acc.totalShippedQuantity += shipped
  317 + acc.totalQuantity += orderQty
  318 + return acc
  319 + }, { totalQuantity: 0, totalShippedQuantity: 0, totalSupplementaryQuantity: 0 })
  320 + this.form.totalQuantity = summary.totalQuantity
  321 + this.form.totalShippedQuantity = summary.totalShippedQuantity
  322 + this.form.totalSupplementaryQuantity = summary.totalSupplementaryQuantity
  323 + },
  324 + purchaseOrderLineListChange(data) {
  325 + // const list = Array.isArray(data) ? data : []
  326 + // this.form.purchaseOrderLineList = list
  327 + // this.calculateSummary(list)
  328 + },
  329 + }
  330 +}
  331 +</script>
  332 +
  333 +<style lang="scss" scoped>
  334 +.page {
  335 + display: flex;
  336 + flex-direction: column;
  337 + height: 100%;
  338 +}
  339 +
  340 +.scroll {
  341 + flex: 1;
  342 + padding: 6rpx 0 356rpx;
  343 +}
  344 +
  345 +
  346 +
  347 +.title-header {
  348 + background-color: #fff;
  349 + display: flex;
  350 + align-items: center;
  351 + padding: 32rpx 32rpx 22rpx;
  352 +
  353 + .title-header_icon {
  354 + width: 32rpx;
  355 + height: 28rpx;
  356 + margin-right: 16rpx;
  357 + }
  358 +
  359 + span {
  360 + color: rgba(0, 0, 0, 0.9);
  361 + font-size: 32rpx;
  362 + line-height: 44rpx;
  363 + font-weight: 600;
  364 + }
  365 +}
  366 +
  367 +
  368 +.section {
  369 + background: #fff;
  370 + margin-bottom: 20rpx;
  371 +}
  372 +
  373 +.section2 {
  374 + background: #f1f1f1;
  375 +}
  376 +
  377 +::v-deep .uni-list {
  378 + background: transparent;
  379 +
  380 + &-item {
  381 + &__extra-text {
  382 + font-size: 32rpx;
  383 + }
  384 +
  385 + &__content-title {
  386 + font-size: 32rpx;
  387 + color: rgba(0, 0, 0, 0.9);
  388 + }
  389 +
  390 + &__container {
  391 + padding: 32rpx;
  392 + // align-items: center;
  393 +
  394 + .uni-easyinput {
  395 +
  396 + .is-disabled {
  397 + background-color: transparent !important;
  398 + }
  399 +
  400 + &__placeholder-class {
  401 + font-size: 32rpx;
  402 + color: rgba(0, 0, 0, 0.4);
  403 + }
  404 +
  405 + &__content {
  406 + border: none;
  407 +
  408 + &-input {
  409 + padding-left: 0 !important;
  410 + height: 48rpx;
  411 + line-height: 48rpx;
  412 + font-size: 32rpx;
  413 + }
  414 +
  415 + .content-clear-icon {
  416 + font-size: 44rpx !important;
  417 + }
  418 + }
  419 + }
  420 +
  421 + .amount-row {
  422 + flex: 1;
  423 + display: flex;
  424 + align-items: center;
  425 +
  426 + .uni-easyinput {
  427 + flex: 1;
  428 + }
  429 +
  430 + .unit {
  431 + margin-left: 16rpx;
  432 + color: rgba(0, 0, 0, 0.9);
  433 + }
  434 + }
  435 +
  436 + .item-title,
  437 + .uni-list-item__content {
  438 + flex: none;
  439 + min-height: 48rpx;
  440 + line-height: 48rpx;
  441 + font-size: 32rpx;
  442 + position: relative;
  443 + width: 210rpx;
  444 + margin-right: 32rpx;
  445 + color: rgba(0, 0, 0, 0.9);
  446 + padding-right: 0;
  447 +
  448 +
  449 + .required {
  450 + color: red;
  451 + position: absolute;
  452 + top: 50%;
  453 + transform: translateY(-50%);
  454 + left: -16rpx;
  455 + }
  456 + }
  457 +
  458 + }
  459 +
  460 + &.select-item {
  461 + &.is-empty {
  462 + .uni-list-item__extra-text {
  463 + color: rgba(0, 0, 0, 0.4) !important;
  464 + }
  465 + }
  466 +
  467 + &.is-filled {
  468 + .uni-list-item__extra-text {
  469 + color: rgba(0, 0, 0, 0.9) !important;
  470 + }
  471 + }
  472 +
  473 + .serial-number-row {
  474 + display: flex;
  475 + align-items: center;
  476 + }
  477 +
  478 + }
  479 +
  480 + &.mgb10 {
  481 + margin-bottom: 20rpx;
  482 + }
  483 +
  484 + }
  485 +
  486 + .title-header {
  487 + background-color: #fff;
  488 + display: flex;
  489 + align-items: center;
  490 + padding: 32rpx 32rpx 22rpx;
  491 +
  492 + &_icon {
  493 + width: 32rpx;
  494 + height: 28rpx;
  495 + margin-right: 16rpx;
  496 + }
  497 +
  498 + span {
  499 + color: rgba(0, 0, 0, 0.9);
  500 + font-size: 32rpx;
  501 + line-height: 44rpx;
  502 + font-weight: 600;
  503 + }
  504 + }
  505 +}
  506 +
  507 +/* 只读 easyinput 根据内容自适应高度 */
  508 +::v-deep .uni-list-item__container {
  509 + align-items: flex-start;
  510 +}
  511 +
  512 +/* 只读文本样式 */
  513 +.readonly-text {
  514 + color: rgba(0, 0, 0, 0.9);
  515 + font-size: 32rpx;
  516 + line-height: 48rpx;
  517 + text-align: right;
  518 + white-space: pre-wrap;
  519 + word-break: break-all;
  520 +}
  521 +
  522 +
  523 +.footer {
  524 + position: fixed;
  525 + left: 0;
  526 + right: 0;
  527 + bottom: 0;
  528 + padding: 0 32rpx 32rpx;
  529 + padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
  530 + background: #fff;
  531 + box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
  532 + z-index: 10;
  533 +
  534 + .btn {
  535 + height: 80rpx;
  536 + line-height: 80rpx;
  537 + border-radius: 12rpx;
  538 + font-size: 32rpx;
  539 + }
  540 +
  541 + .submit {
  542 + background: $theme-primary;
  543 + color: #fff;
  544 + }
  545 +
  546 + .view-total {
  547 + padding: 20rpx 0;
  548 +
  549 + .head {
  550 + font-size: 32rpx;
  551 + font-weight: 600;
  552 + line-height: 50rpx;
  553 + color: rgba(0, 0, 0, 0.9);
  554 + padding-bottom: 16rpx;
  555 + margin-bottom: 24rpx;
  556 + ;
  557 + border-bottom: 1px dashed #E7E7E7;
  558 + }
  559 +
  560 + .row {
  561 + display: flex;
  562 + margin-bottom: 24rpx;
  563 + line-height: 32rpx;
  564 +
  565 + .row2 {
  566 + width: 50%;
  567 + }
  568 +
  569 + .label {
  570 + width: 180rpx;
  571 + margin-right: 14rpx;
  572 + color: rgba(0, 0, 0, 0.6);
  573 + font-size: 28rpx;
  574 + }
  575 +
  576 + .value {
  577 + flex: 1;
  578 + color: rgba(0, 0, 0, 0.9);
  579 + font-size: 28rpx;
  580 + white-space: pre-wrap;
  581 + word-break: break-all;
  582 + }
  583 + }
  584 + }
  585 +}
  586 +</style>
... ...
  1 +<template>
  2 + <view class="product" :class="{ 'history': mode == 'history' }">
  3 +
  4 + <!-- 新增&详情-产品 -->
  5 + <view class="header bp">
  6 + <image class="opCollapse" src="/static/images/title.png" />
  7 + <text class="title">{{ title || '产品' }}</text>
  8 + <view class="ops">
  9 + <image v-if="mode === 'add'" class="opAdd" @click="onAdd" src="/static/images/plus.png" />
  10 + <view v-if="mode === 'view'" class="op1" @click="toggleViewCollapse">
  11 + <image class="opAdd" :src="collapsedView ? '/static/images/down.png' : '/static/images/up.png'" />
  12 + <text class="op">{{ collapsedView ? '展开' : '收起' }} </text>
  13 + </view>
  14 +
  15 + </view>
  16 + </view>
  17 +
  18 + <view v-if="mode === 'add'" class="section">
  19 + <view v-for="(item, idx) in items" :key="'a-' + idx" class="block">
  20 + <uni-list class="edit-list">
  21 + <uni-list-item title="行业">
  22 + <template v-slot:footer>
  23 + <uni-easyinput v-model="item.industry" placeholder="请输入行业" :inputBorder="false" />
  24 + </template>
  25 + </uni-list-item>
  26 + <uni-list-item title="品质">
  27 + <template v-slot:footer>
  28 + <uni-easyinput v-model="item.quality" placeholder="请输入品质" :inputBorder="false" />
  29 + </template>
  30 + </uni-list-item>
  31 + <uni-list-item title="牌号">
  32 + <template v-slot:footer>
  33 + <uni-easyinput v-model="item.brand" placeholder="请输入牌号" :inputBorder="false" />
  34 + </template>
  35 + </uni-list-item>
  36 + <view v-show="!item.collapsed">
  37 + <uni-list-item title="厚度(mm)">
  38 + <template v-slot:footer>
  39 + <uni-easyinput type="digit" v-model="item.thickness" placeholder="请输入厚度"
  40 + :inputBorder="false"
  41 + @input="onNonNegativeNumberInput($event, item, idx, 'thickness')"
  42 + @blur="onNonNegativeNumberBlur(item, idx, 'thickness')" />
  43 + </template>
  44 + </uni-list-item>
  45 + <uni-list-item title="厚度公差上限(mm)">
  46 + <template v-slot:footer>
  47 + <uni-easyinput type="number" v-model="item.thicknessTolPos" placeholder="请输入厚度公差上限"
  48 + :inputBorder="false"
  49 + @input="onRealNumberInput($event, item, idx, 'thicknessTolPos')"
  50 + @blur="onRealNumberBlur(item, idx, 'thicknessTolPos')" />
  51 + </template>
  52 + </uni-list-item>
  53 + <uni-list-item title="厚度公差下限(mm)">
  54 + <template v-slot:footer>
  55 + <uni-easyinput type="number" v-model="item.thicknessTolNeg" placeholder="请输入厚度公差下限"
  56 + :inputBorder="false"
  57 + @input="onRealNumberInput($event, item, idx, 'thicknessTolNeg')"
  58 + @blur="onRealNumberBlur(item, idx, 'thicknessTolNeg')" />
  59 + </template>
  60 + </uni-list-item>
  61 + <uni-list-item title="宽度(mm)">
  62 + <template v-slot:footer>
  63 + <uni-easyinput type="digit" v-model="item.width" placeholder="请输入宽度"
  64 + :inputBorder="false" @input="onNonNegativeNumberInput($event, item, idx, 'width')"
  65 + @blur="onNonNegativeNumberBlur(item, idx, 'width')" />
  66 + </template>
  67 + </uni-list-item>
  68 + <uni-list-item title="宽度公差上限(mm)">
  69 + <template v-slot:footer>
  70 + <uni-easyinput type="number" v-model="item.widthTolPos" placeholder="请输入宽度公差上限"
  71 + :inputBorder="false"
  72 + @input="onRealNumberInput($event, item, idx, 'widthTolPos')"
  73 + @blur="onRealNumberBlur(item, idx, 'widthTolPos')" />
  74 + </template>
  75 + </uni-list-item>
  76 + <uni-list-item title="宽度公差下限(mm)">
  77 + <template v-slot:footer>
  78 + <uni-easyinput type="number" v-model="item.widthTolNeg" placeholder="请输入宽度公差下限"
  79 + :inputBorder="false"
  80 + @input="onRealNumberInput($event, item, idx, 'widthTolNeg')"
  81 + @blur="onRealNumberBlur(item, idx, 'widthTolNeg')" />
  82 + </template>
  83 + </uni-list-item>
  84 + <uni-list-item title="长度(mm)">
  85 + <template v-slot:footer>
  86 + <uni-easyinput type="digit" v-model="item.length" placeholder="请输入长度"
  87 + :inputBorder="false" @input="onNonNegativeNumberInput($event, item, idx, 'length')"
  88 + @blur="onNonNegativeNumberBlur(item, idx, 'length')" />
  89 + </template>
  90 + </uni-list-item>
  91 + <uni-list-item title="长度公差上限(mm)">
  92 + <template v-slot:footer>
  93 + <uni-easyinput type="number" v-model="item.lengthTolPos" placeholder="请输入长度公差上限"
  94 + :inputBorder="false"
  95 + @input="onRealNumberInput($event, item, idx, 'lengthTolPos')"
  96 + @blur="onRealNumberBlur(item, idx, 'lengthTolPos')" />
  97 + </template>
  98 + </uni-list-item>
  99 + <uni-list-item title="长度公差下限(mm)">
  100 + <template v-slot:footer>
  101 + <uni-easyinput type="number" v-model="item.lengthTolNeg" placeholder="请输入长度公差下限"
  102 + :inputBorder="false"
  103 + @input="onRealNumberInput($event, item, idx, 'lengthTolNeg')"
  104 + @blur="onRealNumberBlur(item, idx, 'lengthTolNeg')" />
  105 + </template>
  106 + </uni-list-item>
  107 + <uni-list-item title="状态">
  108 + <template v-slot:footer>
  109 + <uni-easyinput v-model="item.status" placeholder="请输入状态" :inputBorder="false" />
  110 + </template>
  111 + </uni-list-item>
  112 + <uni-list-item title="数量kg">
  113 + <template v-slot:footer>
  114 + <uni-easyinput type="digit" v-model="item.quantity" placeholder="请输入数量kg"
  115 + :inputBorder="false"
  116 + @input="onNonNegativeNumberInput($event, item, idx, 'quantity')"
  117 + @blur="onNonNegativeNumberBlur(item, idx, 'quantity')" />
  118 + </template>
  119 + </uni-list-item>
  120 + <uni-list-item v-if="item.showSalesPrice" title="销售价格">
  121 + <template v-slot:footer>
  122 + <uni-easyinput type="digit" v-model="item.salesPrice" placeholder="请输入销售价格"
  123 + :inputBorder="false"
  124 + @input="onNonNegativeNumberInput($event, item, idx, 'salesPrice')"
  125 + @blur="onNonNegativeNumberBlur(item, idx, 'salesPrice')" />
  126 + </template>
  127 + </uni-list-item>
  128 + <uni-list-item class="amount-item">
  129 + <template v-slot:body>
  130 + <view class="item-title"><text>包装费</text></view>
  131 + </template>
  132 + <template v-slot:footer>
  133 + <view class="amount-row">
  134 + <uni-easyinput type="digit" v-model="item.packagingFee" placeholder="0.00"
  135 + :inputBorder="false"
  136 + @input="onNonNegativeNumberInput($event, item, idx, 'packagingFee')"
  137 + @blur="onNonNegativeNumberBlur(item, idx, 'packagingFee')" />
  138 + <text class="unit">元</text>
  139 + </view>
  140 + </template>
  141 + </uni-list-item>
  142 + <uni-list-item title="发货日期">
  143 + <template v-slot:footer>
  144 + <uni-datetime-picker type="date" v-model="item.deliveryDate" :start="minDeliveryDate"
  145 + @change="onDeliveryChange($event, item, idx)" />
  146 + </template>
  147 + </uni-list-item>
  148 + <uni-list-item title="考核超协">
  149 + <template v-slot:footer>
  150 + <uni-easyinput v-model="item.assessmentExceedsAgreement" placeholder="请输入考核超协"
  151 + :inputBorder="false" />
  152 + </template>
  153 + </uni-list-item>
  154 + </view>
  155 + </uni-list>
  156 +
  157 + <view class="block-ops">
  158 + <div class="del" @click="onRemove(item.purchaseOrderId)">
  159 + <image src="/static/images/delete.png" class="icon" />
  160 + 删除
  161 + </div>
  162 + <div class="toggle" @click="toggleItem(idx)">
  163 + <image :src="item.collapsed ? '/static/images/up.png' : '/static/images/down.png'"
  164 + class="icon" />
  165 + {{ item.collapsed ? '展开' : '收起' }}
  166 + </div>
  167 + </view>
  168 + </view>
  169 + </view>
  170 +
  171 + <view v-else-if="mode === 'view'" class="view-list" v-show="!collapsedView">
  172 + <view v-for="(item, idx) in items" :key="'v-' + idx" class="card">
  173 + <view class="row"><text class="label">行业</text><text class="value">{{ item.industry }}</text></view>
  174 + <view class="row"><text class="label">品质</text><text class="value">{{ item.quality }}</text></view>
  175 + <view class="row"><text class="label">牌号</text><text class="value">{{ item.brand }}</text></view>
  176 + <!-- 厚(公差) * 宽(公差) * 长(公差) -->
  177 + <view class="row row-spec"><text class="label">规格(mm)</text>
  178 + <view class="value value-spec">
  179 + <view v-if="item.thickness" class="value-spec_val">{{ item.thickness }}</view>
  180 + <view v-if="item.thickness" class="value-spec_box">
  181 + <view v-if="item.thicknessTolPos" class="value-spec_box_1">{{ item.thicknessTolPos > 0 ? '+' + item.thicknessTolPos : item.thicknessTolPos }}
  182 + </view>
  183 + <view v-if="item.thicknessTolNeg" class="value-spec_box_2">{{ item.thicknessTolNeg > 0 ? '+' + item.thicknessTolNeg : item.thicknessTolNeg }}
  184 + </view>
  185 + </view>
  186 + <view v-if="item.width" class="value-spec_val p12">*</view>
  187 + <view v-if="item.width" class="value-spec_val">{{ item.width }}</view>
  188 + <view v-if="item.width" class="value-spec_box">
  189 + <view v-if="item.widthTolPos" class="value-spec_box_1">{{ item.widthTolPos > 0 ? '+' + item.widthTolPos : item.widthTolPos }}
  190 + </view>
  191 + <view v-if="item.widthTolNeg" class="value-spec_box_2">{{ item.widthTolNeg > 0 ? '+' + item.widthTolNeg : item.widthTolNeg }}
  192 + </view>
  193 + </view>
  194 + <view v-if="item.length" class="value-spec_val p12">*</view>
  195 + <view v-if="item.length" class="value-spec_val">{{ item.length }}</view>
  196 + <view v-if="item.length" class="value-spec_box">
  197 + <view v-if="item.lengthTolPos" class="value-spec_box_1">{{ item.lengthTolPos > 0 ? '+' + item.lengthTolPos : item.lengthTolPos }}
  198 + </view>
  199 + <view v-if="item.lengthTolNeg" class="value-spec_box_2">{{ item.lengthTolNeg > 0 ? '+' + item.lengthTolNeg : item.lengthTolNeg }}
  200 + </view>
  201 + </view>
  202 + </view>
  203 + </view>
  204 + <view class="row"><text class="label">状态</text><text class="value">{{ item.status }}</text></view>
  205 + <view class="row"><text class="label">数量kg</text><text class="value">{{ item.quantity }}</text></view>
  206 + <!-- showSalesPrice 判断是否显示 -->
  207 + <view class="row" v-if="item.showSalesPrice"><text class="label">销售价格</text><text class="value">{{
  208 + item.salesPrice }}</text></view>
  209 + <view class="row"><text class="label">包装费</text><text class="value">{{
  210 + item.packagingFee }}</text></view>
  211 + <view class="row"><text class="label">发货日期</text><text class="value">{{ item.deliveryDate }}</text>
  212 + </view>
  213 + <view class="row"><text class="label">考核超协</text><text class="value">{{ item.assessmentExceedsAgreement
  214 + }}</text></view>
  215 + </view>
  216 + <view class="view-total">
  217 + <view class="head">合计</view>
  218 + <view class="row">
  219 + <text class="label">总数量</text><text class="value">{{ totalQuantity }}</text>
  220 + </view>
  221 + </view>
  222 + </view>
  223 +
  224 + </view>
  225 +</template>
  226 +<script>
  227 +import { uuid } from '@/utils/uuid.js'
  228 +export default {
  229 + name: 'Product',
  230 + props: {
  231 + title: { type: String, default: '' },
  232 + mode: { type: String, default: 'add' },
  233 + list: { type: Array, default: () => [] },
  234 + max: { type: Number, default: 8 },
  235 + totalQuantity: { type: Number, default: 0 },
  236 + orderDate: { type: String, default: '' }
  237 + },
  238 + data() {
  239 + return {
  240 + items: [],
  241 + collapsedView: false,
  242 + }
  243 + },
  244 + computed: {
  245 + minDeliveryDate() {
  246 + const s = this.orderDate
  247 + if (!s) return ''
  248 + const parts = String(s).split('-')
  249 + const y = Number(parts[0])
  250 + const m = Number(parts[1])
  251 + const d = Number(parts[2])
  252 + if (!y || !m || !d) return ''
  253 + const dt = new Date(y, m - 1, d)
  254 + dt.setDate(dt.getDate() + 1)
  255 + const yy = dt.getFullYear()
  256 + const mm = String(dt.getMonth() + 1).padStart(2, '0')
  257 + const dd = String(dt.getDate()).padStart(2, '0')
  258 + return `${yy}/${mm}/${dd}`
  259 + }
  260 + },
  261 + watch: {
  262 + items: {
  263 + handler() { this.emitChange() },
  264 + deep: true
  265 + },
  266 + list: {
  267 + handler(v) {
  268 + const arr = Array.isArray(v) ? v : []
  269 + this.items = arr.map(x => {
  270 + const it = { ...this.defaultItem(), ...x, collapsed: true }
  271 + return it
  272 + })
  273 + },
  274 + deep: true
  275 + },
  276 + },
  277 + created() {
  278 + const init = Array.isArray(this.list) && this.list.length > 0 ? this.list.map(v => ({ ...this.defaultItem(), ...v, collapsed: false })) : [{ ...this.defaultItem(), collapsed: false }]
  279 + this.items = init
  280 + },
  281 + methods: {
  282 + defaultItem() {
  283 + return {
  284 + id: '',
  285 + purchaseOrderId: uuid(),
  286 + collapsed: false,
  287 + industry: '',
  288 + quality: '',
  289 + brand: '',
  290 + thickness: '',
  291 + thicknessTolPos: '',
  292 + thicknessTolNeg: '',
  293 + width: '',
  294 + widthTolPos: '',
  295 + widthTolNeg: '',
  296 + length: '',
  297 + lengthTolPos: '',
  298 + lengthTolNeg: '',
  299 + status: '',
  300 + quantity: '',
  301 + salesPrice: '',
  302 + showSalesPrice: false,
  303 + deliveryDate: '',
  304 + assessmentExceedsAgreement: ''
  305 + }
  306 + },
  307 +
  308 + onAdd() {
  309 + const obj = this.defaultItem()
  310 + obj.collapsed = true
  311 + this.items.push(obj)
  312 + this.emitChange()
  313 + },
  314 + onRemove(id) {
  315 + if (!id) return
  316 + uni.showModal({
  317 + title: '系统提示',
  318 + content: '是否确定删除选中的产品?',
  319 + confirmText: '确定',
  320 + cancelText: '取消',
  321 + success: (res) => {
  322 + if (res && res.confirm) {
  323 + const i = this.items.findIndex(it => String(it.purchaseOrderId) === String(id))
  324 + if (i >= 0) {
  325 + this.items.splice(i, 1)
  326 + this.emitChange()
  327 + }
  328 + }
  329 + }
  330 + })
  331 + },
  332 + toggleItem(idx) {
  333 + const it = this.items[idx]
  334 + if (!it) return
  335 + it.collapsed = !it.collapsed
  336 + this.$set(this.items, idx, it)
  337 + },
  338 + emitChange() {
  339 + const out = this.items.map(it => ({ ...it }))
  340 + this.$emit('input', out)
  341 + this.$emit('update:value', out)
  342 + this.$emit('change', out)
  343 + },
  344 + onNonNegativeNumberInput(val, item, idx, field) {
  345 + let v = String(val != null ? val : (item && item[field]) || '')
  346 + v = v.replace(/[^0-9.]/g, '')
  347 + v = v.replace(/(\..*)\./g, '$1')
  348 + if (v.startsWith('.')) v = '0' + v
  349 + if (v === '') { item[field] = ''; if (typeof idx === 'number') this.$set(this.items, idx, { ...item }); return }
  350 + const num = Number(v)
  351 + if (isNaN(num) || num < 0) {
  352 + item[field] = '0'
  353 + } else {
  354 + item[field] = v
  355 + }
  356 + if (typeof idx === 'number') this.$set(this.items, idx, { ...item })
  357 + },
  358 + onNonNegativeNumberBlur(item, idx, field) {
  359 + const v = String((item && item[field]) || '')
  360 + const num = Number(v)
  361 + if (isNaN(num) || num < 0) item[field] = '0'
  362 + if (typeof idx === 'number') this.$set(this.items, idx, { ...item })
  363 + },
  364 + onRealNumberInput(val, item, idx, field) {
  365 + let s = String(val != null ? val : (item && item[field]) || '')
  366 + const neg = s.trim().startsWith('-')
  367 + s = s.replace(/[^0-9.\-]/g, '')
  368 + s = s.replace(/(?!^)-/g, '')
  369 + s = s.replace(/(\..*)\./g, '$1')
  370 + if (s.startsWith('.')) s = '0' + s
  371 + if (s.startsWith('-.')) s = '-0.' + s.slice(2)
  372 + if (neg && !s.startsWith('-')) s = '-' + s.replace(/-/g, '')
  373 + item[field] = s
  374 + if (typeof idx === 'number') this.$set(this.items, idx, { ...item })
  375 + },
  376 + onRealNumberBlur(item, idx, field) {
  377 + const s = String((item && item[field]) || '')
  378 + if (s === '') { if (typeof idx === 'number') this.$set(this.items, idx, { ...item }); return }
  379 + const n = Number(s)
  380 + if (isNaN(n)) item[field] = ''
  381 + if (typeof idx === 'number') this.$set(this.items, idx, { ...item })
  382 + },
  383 + toggleViewCollapse() {
  384 + this.collapsedView = !this.collapsedView
  385 + },
  386 + onDeliveryChange(e, item, idx) {
  387 + const getStr = (x) => {
  388 + if (x && x.detail && x.detail.value !== undefined) return x.detail.value
  389 + if (typeof x === 'string') return x
  390 + return item && item.deliveryDate ? item.deliveryDate : ''
  391 + }
  392 + const val = getStr(e)
  393 + if (!val || !this.orderDate) return
  394 + const parse = (s) => {
  395 + const p = String(s).replace(/\//g, '-').split('-')
  396 + const y = Number(p[0])
  397 + const m = Number(p[1])
  398 + const d = Number(p[2])
  399 + return new Date(y, m - 1, d)
  400 + }
  401 + const sel = parse(val)
  402 + const ord = parse(this.orderDate)
  403 + if (!(sel > ord)) {
  404 + item.deliveryDate = ''
  405 + this.$set(this.items, idx, { ...item })
  406 + uni.showToast({ title: '发货日期必须大于订货日期', icon: 'none' })
  407 + }
  408 + }
  409 + }
  410 +}
  411 +</script>
  412 +<style lang="scss" scoped>
  413 +.header {
  414 + background-color: #fff;
  415 + display: flex;
  416 + align-items: center;
  417 + padding: 24rpx 32rpx;
  418 +
  419 + &.bp {
  420 + border-bottom: 1px solid #f0f0f0;
  421 + }
  422 +}
  423 +
  424 +.dot {
  425 + width: 16rpx;
  426 + height: 16rpx;
  427 + background: #3D48A3;
  428 + border-radius: 50%;
  429 + margin-right: 12rpx;
  430 +}
  431 +
  432 +.title {
  433 + font-size: 32rpx;
  434 + color: rgba(0, 0, 0, 0.9);
  435 + font-weight: 600;
  436 +}
  437 +
  438 +.ops {
  439 + margin-left: auto;
  440 +}
  441 +
  442 +.op {
  443 + color: $theme-primary;
  444 + font-size: 28rpx;
  445 + margin-left: 8rpx;
  446 +}
  447 +
  448 +.op1 {
  449 + display: flex;
  450 + align-items: center;
  451 +}
  452 +
  453 +.opAdd {
  454 + color: rgba(0, 0, 0, 0.6);
  455 + width: 40rpx;
  456 + height: 40rpx;
  457 +}
  458 +
  459 +.opCollapse {
  460 + color: rgba(0, 0, 0, 0.6);
  461 + width: 32rpx;
  462 + height: 28rpx;
  463 + margin-right: 16rpx;
  464 +}
  465 +
  466 +::v-deep .uni-list {
  467 + background: transparent;
  468 +
  469 + .uni-list--border-top {
  470 + background-color: transparent !important;
  471 + }
  472 +
  473 + &-item {
  474 + &__extra-text {
  475 + font-size: 32rpx;
  476 + }
  477 +
  478 + &__content-title {
  479 + font-size: 32rpx;
  480 + color: rgba(0, 0, 0, 0.9);
  481 + }
  482 +
  483 + &__container {
  484 + padding: 32rpx;
  485 +
  486 + .uni-easyinput {
  487 +
  488 + .is-disabled {
  489 + background-color: transparent !important;
  490 + }
  491 +
  492 + &__placeholder-class {
  493 + font-size: 32rpx;
  494 + color: rgba(0, 0, 0, 0.4);
  495 + }
  496 +
  497 + &__content {
  498 + border: none;
  499 +
  500 + &-input {
  501 + padding-left: 0 !important;
  502 + height: 48rpx;
  503 + line-height: 48rpx;
  504 + font-size: 32rpx;
  505 + }
  506 +
  507 + .content-clear-icon {
  508 + font-size: 44rpx !important;
  509 + }
  510 + }
  511 + }
  512 +
  513 + .amount-row {
  514 + flex: 1;
  515 + display: flex;
  516 + align-items: center;
  517 +
  518 + .uni-easyinput {
  519 + flex: 1;
  520 + }
  521 +
  522 + .unit {
  523 + margin-left: 16rpx;
  524 + color: rgba(0, 0, 0, 0.9);
  525 + }
  526 + }
  527 +
  528 + .item-title,
  529 + .uni-list-item__content {
  530 + flex: none;
  531 + min-height: 48rpx;
  532 + line-height: 48rpx;
  533 + font-size: 32rpx;
  534 + position: relative;
  535 + width: 210rpx;
  536 + margin-right: 32rpx;
  537 + color: rgba(0, 0, 0, 0.9);
  538 + padding-right: 0;
  539 +
  540 +
  541 + .required {
  542 + color: red;
  543 + position: absolute;
  544 + top: 50%;
  545 + transform: translateY(-50%);
  546 + left: -16rpx;
  547 + }
  548 + }
  549 +
  550 + }
  551 +
  552 + &.select-item {
  553 + &.is-empty {
  554 + .uni-list-item__extra-text {
  555 + color: rgba(0, 0, 0, 0.4) !important;
  556 + }
  557 + }
  558 +
  559 + &.is-filled {
  560 + .uni-list-item__extra-text {
  561 + color: rgba(0, 0, 0, 0.9) !important;
  562 + }
  563 + }
  564 +
  565 + .serial-number-row {
  566 + display: flex;
  567 + align-items: center;
  568 + }
  569 +
  570 + }
  571 +
  572 + &.mgb10 {
  573 + margin-bottom: 20rpx;
  574 + }
  575 +
  576 + }
  577 +
  578 + .title-header {
  579 + background-color: #fff;
  580 + display: flex;
  581 + align-items: center;
  582 + padding: 32rpx 32rpx 22rpx;
  583 +
  584 + &_icon {
  585 + width: 32rpx;
  586 + height: 28rpx;
  587 + margin-right: 16rpx;
  588 + }
  589 +
  590 + span {
  591 + color: rgba(0, 0, 0, 0.9);
  592 + font-size: 32rpx;
  593 + line-height: 44rpx;
  594 + font-weight: 600;
  595 + }
  596 + }
  597 +}
  598 +
  599 +/* 只读 easyinput 根据内容自适应高度 */
  600 +::v-deep .uni-list-item__container {
  601 + align-items: flex-start;
  602 +}
  603 +
  604 +.block-ops {
  605 + display: flex;
  606 + padding: 20rpx 32rpx 20rpx;
  607 + justify-content: space-around;
  608 +}
  609 +
  610 +.del {
  611 + color: #D54941;
  612 + font-size: 28rpx;
  613 + display: flex;
  614 + align-items: center;
  615 +
  616 + image {
  617 + width: 40rpx;
  618 + height: 40rpx;
  619 + }
  620 +}
  621 +
  622 +.toggle {
  623 + color: $theme-primary;
  624 + font-size: 28rpx;
  625 + display: flex;
  626 + align-items: center;
  627 +
  628 + image {
  629 + width: 40rpx;
  630 + height: 40rpx;
  631 + }
  632 +}
  633 +
  634 +.section {
  635 + background: #f1f1f1;
  636 + margin-bottom: 20rpx;
  637 +
  638 + .block {
  639 + background: #ffffff;
  640 + // padding: 32rpx 0;
  641 + margin-bottom: 20rpx;
  642 +
  643 + &:last-child {
  644 + margin-bottom: 0;
  645 + }
  646 + }
  647 +
  648 + .row {
  649 + display: flex;
  650 + // margin-bottom: 24rpx;
  651 + line-height: 32rpx;
  652 + padding: 32rpx;
  653 + border-bottom: 1rpx solid #f2f2f2;
  654 +
  655 +
  656 + &.noneStyle {
  657 + border-bottom: 0;
  658 + border-bottom: none;
  659 + }
  660 +
  661 + &.row-spec {
  662 + align-items: center;
  663 + }
  664 + }
  665 +
  666 + .row:last-child {
  667 + margin-bottom: 0;
  668 + }
  669 +
  670 + .label {
  671 + width: 210rpx;
  672 + margin-right: 32rpx;
  673 + color: rgba(0, 0, 0, 0.9);
  674 + font-size: 32rpx;
  675 + line-height: 48rpx;
  676 + }
  677 +
  678 + .value {
  679 + flex: 1;
  680 + color: rgba(0, 0, 0, 0.9);
  681 + font-size: 32rpx;
  682 + white-space: pre-wrap;
  683 + word-break: break-all;
  684 + line-height: 48rpx;
  685 + }
  686 +
  687 + .value-spec {
  688 + height: 48rpx;
  689 + display: flex;
  690 + align-items: center;
  691 + color: #000000;
  692 +
  693 + &_box {
  694 + position: relative;
  695 + width: 60rpx;
  696 + height: 48rpx;
  697 +
  698 + &_1 {
  699 + font-size: 16rpx;
  700 + position: absolute;
  701 + top: -10rpx;
  702 + left: 0;
  703 + }
  704 +
  705 + &_2 {
  706 + font-size: 16rpx;
  707 + position: absolute;
  708 + bottom: -10rpx;
  709 + left: 0;
  710 + }
  711 + }
  712 +
  713 + &_val {
  714 + font-size: 28rpx;
  715 +
  716 + &.p12 {
  717 + padding-right: 12rpx;
  718 + }
  719 + }
  720 + }
  721 +
  722 + .view-total {
  723 + padding-top: 20rpx;
  724 +
  725 + .head {
  726 + font-size: 32rpx;
  727 + font-weight: 600;
  728 + line-height: 50rpx;
  729 + color: rgba(0, 0, 0, 0.9);
  730 + padding-bottom: 16rpx;
  731 + margin-bottom: 24rpx;
  732 + ;
  733 + border-bottom: 1px dashed #E7E7E7;
  734 + }
  735 +
  736 + .row {
  737 + display: flex;
  738 + margin-bottom: 24rpx;
  739 + line-height: 32rpx;
  740 +
  741 + .label {
  742 + width: 180rpx;
  743 + margin-right: 14rpx;
  744 + color: rgba(0, 0, 0, 0.6);
  745 + font-size: 28rpx;
  746 + }
  747 +
  748 + .value {
  749 + flex: 1;
  750 + color: rgba(0, 0, 0, 0.9);
  751 + font-size: 28rpx;
  752 + white-space: pre-wrap;
  753 + word-break: break-all;
  754 + }
  755 + }
  756 + }
  757 +}
  758 +
  759 +.view-list {
  760 + padding: 26rpx 32rpx;
  761 + background: #ffffff;
  762 +
  763 + .card {
  764 + background: #f3f3f3;
  765 + border-radius: 16rpx;
  766 + padding: 32rpx 44rpx;
  767 + margin-bottom: 20rpx;
  768 +
  769 + &:last-child {
  770 + margin-bottom: 0;
  771 + }
  772 + }
  773 +
  774 + .row {
  775 + display: flex;
  776 + margin-bottom: 24rpx;
  777 + line-height: 32rpx;
  778 +
  779 + &.row-spec {
  780 + height: 60rpx;
  781 + align-items: center;
  782 + }
  783 + }
  784 +
  785 + .row:last-child {
  786 + margin-bottom: 0;
  787 + }
  788 +
  789 + .label {
  790 + width: 140rpx;
  791 + margin-right: 14rpx;
  792 + color: rgba(0, 0, 0, 0.6);
  793 + font-size: 28rpx;
  794 + }
  795 +
  796 + .value {
  797 + flex: 1;
  798 + color: rgba(0, 0, 0, 0.9);
  799 + font-size: 28rpx;
  800 + white-space: pre-wrap;
  801 + word-break: break-all;
  802 + }
  803 +
  804 + .value-spec {
  805 + height: 60rpx;
  806 + display: flex;
  807 + align-items: center;
  808 + color: #000000;
  809 +
  810 + &_box {
  811 + position: relative;
  812 + width: 60rpx;
  813 + height: 60rpx;
  814 +
  815 + &_1 {
  816 + font-size: 16rpx;
  817 + position: absolute;
  818 + top: 0;
  819 + left: 0;
  820 + }
  821 +
  822 + &_2 {
  823 + font-size: 16rpx;
  824 + position: absolute;
  825 + bottom: 0;
  826 + left: 0;
  827 + }
  828 + }
  829 +
  830 + &_val {
  831 + font-size: 28rpx;
  832 +
  833 + &.p12 {
  834 + padding-right: 12rpx;
  835 + }
  836 + }
  837 + }
  838 +
  839 + .view-total {
  840 + padding-top: 20rpx;
  841 +
  842 + .head {
  843 + font-size: 32rpx;
  844 + font-weight: 600;
  845 + line-height: 50rpx;
  846 + color: rgba(0, 0, 0, 0.9);
  847 + padding-bottom: 16rpx;
  848 + margin-bottom: 24rpx;
  849 + ;
  850 + border-bottom: 1px dashed #E7E7E7;
  851 + }
  852 +
  853 + .row {
  854 + display: flex;
  855 + margin-bottom: 24rpx;
  856 + line-height: 32rpx;
  857 +
  858 + .label {
  859 + width: 180rpx;
  860 + margin-right: 14rpx;
  861 + color: rgba(0, 0, 0, 0.6);
  862 + font-size: 28rpx;
  863 + }
  864 +
  865 + .value {
  866 + flex: 1;
  867 + color: rgba(0, 0, 0, 0.9);
  868 + font-size: 28rpx;
  869 + white-space: pre-wrap;
  870 + word-break: break-all;
  871 + }
  872 + }
  873 + }
  874 +}
  875 +</style>
... ...