Commit 7c82fe02d61f3095f0d998afe67ea0f76365e654

Authored by gesilong
1 parent 553743b0

commit:过磅页面提交

  1 +import request from '@/utils/request'
  2 +import { ContentTypeEnum } from '@/utils/httpEnum'
  3 +
  4 +// 过磅码单分页查询
  5 +export function weighTicketQueryApi(params) {
  6 + return request({
  7 + url: '/procurement/weighTicket/query',
  8 + method: 'get',
  9 + params
  10 + })
  11 +}
  12 +
  13 +// 过磅码单详情
  14 +export function weighTicketDetailApi(params) {
  15 + return request({
  16 + url: '/procurement/weighTicket',
  17 + method: 'get',
  18 + params
  19 + })
  20 +}
  21 +
  22 +// 新增
  23 +export function weighTicketSaveApi(data) {
  24 + return request({
  25 + url: '/procurement/weighTicket',
  26 + method: 'post',
  27 + data,
  28 + contentType: ContentTypeEnum.JSON
  29 + })
  30 +}
  31 +
  32 +// 编辑
  33 +export function weighTicketUpdateApi(data) {
  34 + return request({
  35 + url: '/procurement/weighTicket',
  36 + method: 'put',
  37 + data,
  38 + contentType: ContentTypeEnum.JSON
  39 + })
  40 +}
  41 +
  42 +// 作废 / 恢复
  43 +export function weighTicketDeleteApi(params) {
  44 + return request({
  45 + url: '/procurement/weighTicket/delete',
  46 + method: 'put',
  47 + params
  48 + })
  49 +}
... ...
  1 +<template>
  2 + <view class="page">
  3 + <scroll-view class="scroll" scroll-y>
  4 + <uni-list>
  5 + <!-- 编号 -->
  6 + <uni-list-item class="select-item" :class="form.code ? 'is-filled' : 'is-empty'">
  7 + <template v-slot:body>
  8 + <view class="item-title"><text>编号</text></view>
  9 + </template>
  10 + <template v-slot:footer>
  11 + <view class="serial-number-row">
  12 + <text class="readonly-text value-code">{{ form.code || '-' }}</text>
  13 + <button class="generate-btn" @click="initCode">点此生成</button>
  14 + </view>
  15 + </template>
  16 + </uni-list-item>
  17 +
  18 + <!-- 类型 -->
  19 + <uni-list-item>
  20 + <template v-slot:body>
  21 + <view class="item-title"><text class="required">*</text><text>类型</text></view>
  22 + </template>
  23 + <template v-slot:footer>
  24 + <uni-easyinput v-model="form.type" :inputBorder="false" placeholder="请输入类型" />
  25 + </template>
  26 + </uni-list-item>
  27 +
  28 + <!-- 计划编号 -->
  29 + <uni-list-item>
  30 + <template v-slot:body>
  31 + <view class="item-title"><text class="required">*</text><text>计划编号</text></view>
  32 + </template>
  33 + <template v-slot:footer>
  34 + <uni-easyinput v-model="form.unit" :inputBorder="false" placeholder="请输入计划编号" />
  35 + </template>
  36 + </uni-list-item>
  37 +
  38 + <!-- 时间 -->
  39 + <uni-list-item class="select-item" :class="form.firstGrossWeightTime ? 'is-filled' : 'is-empty'">
  40 + <template v-slot:body>
  41 + <view class="item-title"><text class="required">*</text><text>时间</text></view>
  42 + </template>
  43 + <template v-slot:footer>
  44 + <uni-datetime-picker type="date" v-model="form.firstGrossWeightTime" />
  45 + </template>
  46 + </uni-list-item>
  47 +
  48 + <!-- 供料单位 -->
  49 + <uni-list-item>
  50 + <template v-slot:body>
  51 + <view class="item-title"><text class="required">*</text><text>供料单位</text></view>
  52 + </template>
  53 + <template v-slot:footer>
  54 + <uni-easyinput v-model="form.supplierName" :inputBorder="false" placeholder="请输入供料单位" />
  55 + </template>
  56 + </uni-list-item>
  57 +
  58 + <!-- 收料单位 -->
  59 + <uni-list-item>
  60 + <template v-slot:body>
  61 + <view class="item-title"><text class="required">*</text><text>收料单位</text></view>
  62 + </template>
  63 + <template v-slot:footer>
  64 + <uni-easyinput v-model="form.companyShortName" :inputBorder="false" placeholder="请输入收料单位" />
  65 + </template>
  66 + </uni-list-item>
  67 +
  68 + <!-- 物料名称 -->
  69 + <uni-list-item>
  70 + <template v-slot:body>
  71 + <view class="item-title"><text class="required">*</text><text>物料名称</text></view>
  72 + </template>
  73 + <template v-slot:footer>
  74 + <uni-easyinput v-model="form.materialName" :inputBorder="false" placeholder="请输入物料名称" />
  75 + </template>
  76 + </uni-list-item>
  77 +
  78 + <!-- 过磅总重 -->
  79 + <uni-list-item>
  80 + <template v-slot:body>
  81 + <view class="item-title"><text class="required">*</text><text>过磅总重</text></view>
  82 + </template>
  83 + <template v-slot:footer>
  84 + <uni-easyinput v-model="form.totalGrossWeight" type="digit" :inputBorder="false" placeholder="请输入过磅总重" @input="calcNetWeight" />
  85 + </template>
  86 + </uni-list-item>
  87 +
  88 + <!-- 实际伙重 -->
  89 + <uni-list-item title="实际伙重">
  90 + <template v-slot:footer>
  91 + <uni-easyinput v-model="form.actualImpurityWeight" type="digit" :inputBorder="false" placeholder="请输入实际伙重" @input="calcNetWeight" />
  92 + </template>
  93 + </uni-list-item>
  94 +
  95 + <!-- 货物净重 -->
  96 + <uni-list-item title="货物净重">
  97 + <template v-slot:footer>
  98 + <uni-easyinput v-model="form.netWeight" type="digit" :inputBorder="false" placeholder="请输入货物净重" />
  99 + </template>
  100 + </uni-list-item>
  101 +
  102 + <!-- 净重大写 -->
  103 + <uni-list-item title="净重大写">
  104 + <template v-slot:footer>
  105 + <uni-easyinput v-model="form.netWeightUpper" :inputBorder="false" placeholder="请输入净重大写" />
  106 + </template>
  107 + </uni-list-item>
  108 +
  109 + <!-- 来料扣杂类型 -->
  110 + <uni-list-item title="来料扣杂类型">
  111 + <template v-slot:footer>
  112 + <uni-easyinput v-model="form.deductionTypes" :inputBorder="false" placeholder="请输入来料扣杂类型" />
  113 + </template>
  114 + </uni-list-item>
  115 +
  116 + <!-- 供应存欠料 -->
  117 + <uni-list-item title="供应存欠料">
  118 + <template v-slot:footer>
  119 + <uni-easyinput v-model="form.supplierStockMaterial" type="digit" :inputBorder="false" placeholder="请输入供应存欠料" />
  120 + </template>
  121 + </uni-list-item>
  122 +
  123 + <!-- 物流存欠料 -->
  124 + <uni-list-item title="物流存欠料">
  125 + <template v-slot:footer>
  126 + <uni-easyinput v-model="form.logisticsStockMaterial" type="digit" :inputBorder="false" placeholder="请输入物流存欠料" />
  127 + </template>
  128 + </uni-list-item>
  129 +
  130 + <!-- 车牌号 -->
  131 + <uni-list-item>
  132 + <template v-slot:body>
  133 + <view class="item-title"><text class="required">*</text><text>车牌号</text></view>
  134 + </template>
  135 + <template v-slot:footer>
  136 + <uni-easyinput v-model="form.plateNumber" :inputBorder="false" placeholder="请输入车牌号" />
  137 + </template>
  138 + </uni-list-item>
  139 + </uni-list>
  140 +
  141 + <!-- 计划单明细 -->
  142 + <view class="sub-table">
  143 + <view class="header">
  144 + <image class="opCollapse" src="/static/images/title.png" />
  145 + <text class="title">计划单明细</text>
  146 + <view class="ops">
  147 + <image class="opAdd" @click="addPlan" src="/static/images/plus.png" />
  148 + </view>
  149 + </view>
  150 + <view class="add-list">
  151 + <view v-if="!planList.length" class="empty-tip">暂无明细,请添加</view>
  152 + <view v-for="(item, idx) in planList" :key="'p-' + idx" class="block">
  153 + <uni-list>
  154 + <uni-list-item title="计划品种">
  155 + <template v-slot:footer>
  156 + <uni-easyinput v-model="item.productName" :inputBorder="false" placeholder="请输入计划品种" />
  157 + </template>
  158 + </uni-list-item>
  159 + <uni-list-item title="计划数量">
  160 + <template v-slot:footer>
  161 + <uni-easyinput v-model="item.quantity" type="digit" :inputBorder="false" placeholder="请输入计划数量" />
  162 + </template>
  163 + </uni-list-item>
  164 + <uni-list-item title="计划编号">
  165 + <template v-slot:footer>
  166 + <uni-easyinput v-model="item.planCode" :inputBorder="false" placeholder="请输入计划编号" />
  167 + </template>
  168 + </uni-list-item>
  169 + </uni-list>
  170 + <view class="block-ops">
  171 + <div class="del" @click="removeRow('plan', idx)">
  172 + <image src="/static/images/delete.png" class="icon" />删除
  173 + </div>
  174 + </view>
  175 + </view>
  176 + </view>
  177 + </view>
  178 +
  179 + <!-- 过磅明细 -->
  180 + <view class="sub-table">
  181 + <view class="header">
  182 + <image class="opCollapse" src="/static/images/title.png" />
  183 + <text class="title">过磅明细</text>
  184 + <view class="ops">
  185 + <image class="opAdd" @click="addWeigh" src="/static/images/plus.png" />
  186 + </view>
  187 + </view>
  188 + <view class="add-list">
  189 + <view v-if="!weighList.length" class="empty-tip">暂无明细,请添加</view>
  190 + <view v-for="(item, idx) in weighList" :key="'w-' + idx" class="block">
  191 + <uni-list>
  192 + <uni-list-item title="过磅品种">
  193 + <template v-slot:footer>
  194 + <uni-easyinput v-model="item.productName" :inputBorder="false" placeholder="请输入过磅品种" />
  195 + </template>
  196 + </uni-list-item>
  197 + <uni-list-item title="开票品名">
  198 + <template v-slot:footer>
  199 + <uni-easyinput v-model="item.invoiceProductName" :inputBorder="false" placeholder="请输入开票品名" />
  200 + </template>
  201 + </uni-list-item>
  202 + <uni-list-item title="过磅数量">
  203 + <template v-slot:footer>
  204 + <uni-easyinput v-model="item.quantity" type="digit" :inputBorder="false" placeholder="请输入过磅数量" />
  205 + </template>
  206 + </uni-list-item>
  207 + <uni-list-item title="计划编号">
  208 + <template v-slot:footer>
  209 + <uni-easyinput v-model="item.planCode" :inputBorder="false" placeholder="请输入计划编号" />
  210 + </template>
  211 + </uni-list-item>
  212 + </uni-list>
  213 + <view class="block-ops">
  214 + <div class="del" @click="removeRow('weigh', idx)">
  215 + <image src="/static/images/delete.png" class="icon" />删除
  216 + </div>
  217 + </view>
  218 + </view>
  219 + </view>
  220 + </view>
  221 +
  222 + <!-- 申请数量明细 -->
  223 + <view class="sub-table">
  224 + <view class="header">
  225 + <image class="opCollapse" src="/static/images/title.png" />
  226 + <text class="title">申请数量明细</text>
  227 + <view class="ops">
  228 + <image class="opAdd" @click="addApply" src="/static/images/plus.png" />
  229 + </view>
  230 + </view>
  231 + <view class="add-list">
  232 + <view v-if="!applyList.length" class="empty-tip">暂无明细,请添加</view>
  233 + <view v-for="(item, idx) in applyList" :key="'a-' + idx" class="block">
  234 + <uni-list>
  235 + <uni-list-item title="类别">
  236 + <template v-slot:footer>
  237 + <uni-easyinput v-model="item.category" :inputBorder="false" placeholder="请输入类别" />
  238 + </template>
  239 + </uni-list-item>
  240 + <uni-list-item title="数量">
  241 + <template v-slot:footer>
  242 + <uni-easyinput v-model="item.quantity" type="digit" :inputBorder="false" placeholder="请输入数量" />
  243 + </template>
  244 + </uni-list-item>
  245 + </uni-list>
  246 + <view class="block-ops">
  247 + <div class="del" @click="removeRow('apply', idx)">
  248 + <image src="/static/images/delete.png" class="icon" />删除
  249 + </div>
  250 + </view>
  251 + </view>
  252 + </view>
  253 + </view>
  254 +
  255 + <!-- 备注模块 -->
  256 + <view class="remark-section">
  257 + <view class="header">
  258 + <image class="opCollapse" src="/static/images/title.png" />
  259 + <text class="title">备注</text>
  260 + </view>
  261 + <view class="section-content">
  262 + <view class="remark-group">
  263 + <view class="remark-label"><text class="required">*</text><text>业务摘要</text></view>
  264 + <uni-easyinput v-model="form.businessSummary" type="textarea" :inputBorder="false" placeholder="请输入业务摘要" maxlength="2000" />
  265 + </view>
  266 + <view class="remark-group">
  267 + <view class="remark-label">特别说明</view>
  268 + <uni-easyinput v-model="form.specialNote" type="textarea" :inputBorder="false" placeholder="请输入特别说明" maxlength="2000" />
  269 + </view>
  270 + <view class="remark-group">
  271 + <view class="remark-label">单据备注</view>
  272 + <uni-easyinput v-model="form.remark" type="textarea" :inputBorder="false" placeholder="请输入单据备注" maxlength="2000" />
  273 + </view>
  274 + </view>
  275 + </view>
  276 +
  277 + <view class="footer">
  278 + <button class="btn submit" type="primary" @click="onSubmit">提交</button>
  279 + </view>
  280 + </scroll-view>
  281 + </view>
  282 +</template>
  283 +
  284 +<script>
  285 +import { weighTicketSaveApi } from '@/api/procure-manage/weighTicket.js'
  286 +
  287 +export default {
  288 + name: 'AddWeightTicket',
  289 + data() {
  290 + return {
  291 + form: {
  292 + code: '',
  293 + type: '',
  294 + unit: '',
  295 + firstGrossWeightTime: '',
  296 + supplierName: '',
  297 + companyShortName: '',
  298 + materialName: '',
  299 + totalGrossWeight: '',
  300 + actualImpurityWeight: '',
  301 + netWeight: '',
  302 + netWeightUpper: '',
  303 + deductionTypes: '',
  304 + supplierStockMaterial: '',
  305 + logisticsStockMaterial: '',
  306 + plateNumber: '',
  307 + businessSummary: '',
  308 + specialNote: '',
  309 + remark: ''
  310 + },
  311 + planList: [],
  312 + weighList: [],
  313 + applyList: []
  314 + }
  315 + },
  316 + onLoad() {
  317 + this.initCode()
  318 + },
  319 + methods: {
  320 + initCode() {
  321 + // 编号生成接口待后端提供,先占位
  322 + this.form.code = this.form.code || ''
  323 + },
  324 + calcNetWeight() {
  325 + const g = Number(this.form.totalGrossWeight)
  326 + const i = Number(this.form.actualImpurityWeight || 0)
  327 + if (!isNaN(g) && g > 0) {
  328 + const net = g - (isNaN(i) ? 0 : i)
  329 + this.form.netWeight = String(Math.round(net * 10000) / 10000)
  330 + }
  331 + },
  332 + addPlan() {
  333 + this.planList.push({ productName: '', quantity: '', planCode: '' })
  334 + },
  335 + addWeigh() {
  336 + this.weighList.push({ productName: '', invoiceProductName: '', quantity: '', planCode: '' })
  337 + },
  338 + addApply() {
  339 + this.applyList.push({ category: '', quantity: '' })
  340 + },
  341 + removeRow(type, idx) {
  342 + if (type === 'plan') this.planList.splice(idx, 1)
  343 + else if (type === 'weigh') this.weighList.splice(idx, 1)
  344 + else if (type === 'apply') this.applyList.splice(idx, 1)
  345 + },
  346 + validate() {
  347 + const f = this.form
  348 + if (!f.type) return this.tip('请输入类型')
  349 + if (!f.unit) return this.tip('请输入计划编号')
  350 + if (!f.firstGrossWeightTime) return this.tip('请选择时间')
  351 + if (!f.supplierName) return this.tip('请输入供料单位')
  352 + if (!f.companyShortName) return this.tip('请输入收料单位')
  353 + if (!f.materialName) return this.tip('请输入物料名称')
  354 + if (!f.totalGrossWeight) return this.tip('请输入过磅总重')
  355 + if (!f.plateNumber) return this.tip('请输入车牌号')
  356 + if (!f.businessSummary) return this.tip('请输入业务摘要')
  357 + return true
  358 + },
  359 + tip(msg) {
  360 + uni.showToast({ title: msg, icon: 'none' })
  361 + return false
  362 + },
  363 + async onSubmit() {
  364 + if (!this.validate()) return
  365 + const confirmRes = await new Promise(resolve => {
  366 + uni.showModal({ title: '提示', content: '确定新增过磅码单吗?', confirmText: '确定', cancelText: '取消', success: resolve })
  367 + })
  368 + if (!(confirmRes && confirmRes.confirm)) return
  369 + const clean = (obj) => {
  370 + const out = {}
  371 + Object.keys(obj || {}).forEach(k => {
  372 + const v = obj[k]
  373 + const isEmptyString = typeof v === 'string' && v.trim() === ''
  374 + const isUndef = v === undefined || v === null
  375 + if (!(isEmptyString || isUndef)) out[k] = v
  376 + })
  377 + return out
  378 + }
  379 + const payload = clean({
  380 + ...this.form,
  381 + planDetailList: this.planList.map(it => clean(it)),
  382 + weighDetailList: this.weighList.map(it => clean(it)),
  383 + applyQuantityList: this.applyList.map(it => clean(it))
  384 + })
  385 + uni.showLoading({ title: '提交中...', mask: true })
  386 + weighTicketSaveApi(payload)
  387 + .then(() => {
  388 + uni.hideLoading()
  389 + uni.showToast({ title: '新增成功', icon: 'none' })
  390 + try { uni.setStorageSync('WEIGHT_TICKET_LIST_NEED_REFRESH', '1') } catch (e) {}
  391 + setTimeout(() => { uni.navigateBack() }, 400)
  392 + })
  393 + .catch(e => {
  394 + uni.hideLoading()
  395 + uni.showToast({ title: (e && (e.msg || e.message)) || '新增失败', icon: 'none' })
  396 + })
  397 + }
  398 + }
  399 +}
  400 +</script>
  401 +
  402 +<style lang="scss" scoped>
  403 +.page {
  404 + display: flex;
  405 + flex-direction: column;
  406 + height: 100%;
  407 +}
  408 +
  409 +.scroll {
  410 + flex: 1;
  411 + padding: 12rpx 0 200rpx !important;
  412 +}
  413 +
  414 +.footer {
  415 + z-index: 2;
  416 + position: fixed;
  417 + left: 0;
  418 + right: 0;
  419 + bottom: 0;
  420 + padding: 32rpx;
  421 + padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
  422 + background: #fff;
  423 + box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
  424 +
  425 + .btn {
  426 + height: 80rpx;
  427 + line-height: 80rpx;
  428 + border-radius: 12rpx;
  429 + font-size: 32rpx;
  430 + }
  431 +
  432 + .submit {
  433 + background: $theme-primary;
  434 + color: #fff;
  435 + }
  436 +}
  437 +
  438 +::v-deep .uni-list {
  439 + .uni-easyinput {
  440 + display: flex;
  441 +
  442 + .uni-input-input {
  443 + color: rgba(0, 0, 0, 0.9);
  444 + }
  445 + }
  446 +
  447 + .uni-input-placeholder {
  448 + z-index: 1;
  449 + }
  450 +
  451 + .uni-input-input {
  452 + background-color: #ffffff;
  453 + }
  454 +
  455 + background: transparent;
  456 +
  457 + &-item {
  458 + &__extra-text {
  459 + font-size: 32rpx;
  460 + }
  461 +
  462 + &__content-title {
  463 + font-size: 32rpx;
  464 + color: rgba(0, 0, 0, 0.9);
  465 + }
  466 +
  467 + &__container {
  468 + padding: 32rpx;
  469 +
  470 + .uni-easyinput {
  471 + &__placeholder-class {
  472 + font-size: 32rpx;
  473 + color: rgba(0, 0, 0, 0.4);
  474 + }
  475 +
  476 + &__content {
  477 + border: none;
  478 + background-color: #ffffff !important;
  479 +
  480 + &-input {
  481 + padding-left: 0 !important;
  482 + height: 48rpx;
  483 + line-height: 48rpx;
  484 + font-size: 32rpx;
  485 + }
  486 +
  487 + .content-clear-icon {
  488 + font-size: 44rpx !important;
  489 + }
  490 + }
  491 + }
  492 +
  493 + .item-title,
  494 + .uni-list-item__content {
  495 + flex: none;
  496 + min-height: 48rpx;
  497 + line-height: 48rpx;
  498 + font-size: 32rpx;
  499 + position: relative;
  500 + width: 240rpx;
  501 + margin-right: 32rpx;
  502 + color: rgba(0, 0, 0, 0.9);
  503 +
  504 + .required {
  505 + color: red;
  506 + position: absolute;
  507 + top: 50%;
  508 + transform: translateY(-50%);
  509 + left: -16rpx;
  510 + }
  511 + }
  512 + }
  513 +
  514 + &.select-item {
  515 + &.is-empty {
  516 + .uni-list-item__extra-text {
  517 + color: rgba(0, 0, 0, 0.4) !important;
  518 + }
  519 + }
  520 +
  521 + &.is-filled {
  522 + .uni-list-item__extra-text {
  523 + color: rgba(0, 0, 0, 0.9) !important;
  524 + }
  525 + }
  526 +
  527 + .serial-number-row {
  528 + display: flex;
  529 + align-items: center;
  530 +
  531 + .generate-btn {
  532 + margin-left: 24rpx;
  533 + height: 48rpx;
  534 + line-height: 48rpx;
  535 + padding: 0 24rpx;
  536 + font-size: 24rpx;
  537 + border-radius: 8rpx;
  538 + background: $theme-primary;
  539 + color: #fff;
  540 + }
  541 + }
  542 + }
  543 + }
  544 +}
  545 +
  546 +.readonly-text {
  547 + color: rgba(0, 0, 0, 0.9);
  548 + font-size: 32rpx;
  549 + line-height: 48rpx;
  550 + text-align: right;
  551 + white-space: pre-wrap;
  552 + word-break: break-all;
  553 +}
  554 +
  555 +.value-code {
  556 + width: 260rpx;
  557 + text-align: left;
  558 +}
  559 +
  560 +.sub-table,
  561 +.remark-section {
  562 + margin-top: 20rpx;
  563 + background: #fff;
  564 +}
  565 +
  566 +.header {
  567 + display: flex;
  568 + align-items: center;
  569 + padding: 24rpx 32rpx;
  570 + border-bottom: 1rpx solid #f0f0f0;
  571 +
  572 + .opCollapse {
  573 + width: 32rpx;
  574 + height: 28rpx;
  575 + margin-right: 16rpx;
  576 + margin-top: 8rpx;
  577 + }
  578 +
  579 + .title {
  580 + font-size: 32rpx;
  581 + color: rgba(0, 0, 0, 0.9);
  582 + font-weight: 600;
  583 + flex: 1;
  584 + }
  585 +
  586 + .ops {
  587 + display: flex;
  588 + align-items: center;
  589 +
  590 + .opAdd {
  591 + width: 40rpx;
  592 + height: 40rpx;
  593 + }
  594 + }
  595 +}
  596 +
  597 +.add-list {
  598 + padding: 0 0 16rpx;
  599 +
  600 + .empty-tip {
  601 + text-align: center;
  602 + padding: 60rpx 0;
  603 + color: rgba(0, 0, 0, 0.4);
  604 + font-size: 28rpx;
  605 + }
  606 +
  607 + .block {
  608 + border-bottom: 1rpx solid #f0f0f0;
  609 +
  610 + &:last-child {
  611 + border-bottom: none;
  612 + }
  613 +
  614 + .block-ops {
  615 + display: flex;
  616 + align-items: center;
  617 + justify-content: flex-end;
  618 + gap: 48rpx;
  619 + padding: 20rpx 32rpx;
  620 + background: #f8f8f8;
  621 +
  622 + .del,
  623 + .toggle {
  624 + display: flex;
  625 + align-items: center;
  626 + font-size: 28rpx;
  627 + color: rgba(0, 0, 0, 0.6);
  628 +
  629 + .icon {
  630 + width: 32rpx;
  631 + height: 32rpx;
  632 + margin-right: 8rpx;
  633 + }
  634 + }
  635 +
  636 + .del {
  637 + color: #d54941;
  638 + }
  639 + }
  640 + }
  641 +}
  642 +
  643 +.section-content {
  644 + padding: 32rpx;
  645 +}
  646 +
  647 +.remark-group {
  648 + margin-bottom: 32rpx;
  649 +
  650 + &:last-child {
  651 + margin-bottom: 0;
  652 + }
  653 +
  654 + .remark-label {
  655 + display: flex;
  656 + align-items: center;
  657 + font-size: 32rpx;
  658 + color: rgba(0, 0, 0, 0.9);
  659 + margin-bottom: 16rpx;
  660 + position: relative;
  661 + padding-left: 16rpx;
  662 +
  663 + .required {
  664 + color: red;
  665 + position: absolute;
  666 + left: 0;
  667 + }
  668 + }
  669 +}
  670 +</style>
... ...
  1 +<template>
  2 + <view class="page">
  3 + <scroll-view class="scroll" scroll-y>
  4 + <view class="detail-page">
  5 + <!-- 基础信息 -->
  6 + <view class="section">
  7 + <text class="row company">{{ safeText(form.code) }}</text>
  8 + <view class="row"><text class="label">类型</text><text class="value">{{ safeText(form.type) }}</text></view>
  9 + <view class="row"><text class="label">计划编号</text><text class="value">{{ safeText(form.unit) }}</text></view>
  10 + <view class="row"><text class="label">时间</text><text class="value">{{ formatDate(form.firstGrossWeightTime) }}</text></view>
  11 + <view class="row"><text class="label">供料单位</text><text class="value">{{ safeText(form.supplierName) }}</text></view>
  12 + <view class="row"><text class="label">收料单位</text><text class="value">{{ safeText(form.companyShortName) }}</text></view>
  13 + <view class="row"><text class="label">物料名称</text><text class="value">{{ safeText(form.materialName) }}</text></view>
  14 + <view class="row"><text class="label">过磅总重</text><text class="value">{{ formatNumber(form.totalGrossWeight) }}</text></view>
  15 + <view class="row"><text class="label">实际伙重</text><text class="value">{{ formatNumber(form.actualImpurityWeight) }}</text></view>
  16 + <view class="row"><text class="label">货物净重</text><text class="value">{{ formatNumber(form.netWeight) }}</text></view>
  17 + <view class="row"><text class="label">净重大写</text><text class="value">{{ safeText(form.netWeightUpper) }}</text></view>
  18 + <view class="row"><text class="label">来料扣杂类型</text><text class="value">{{ safeText(form.deductionTypes) }}</text></view>
  19 + <view class="row"><text class="label">供应存欠料</text><text class="value">{{ safeText(form.supplierStockMaterial) }}</text></view>
  20 + <view class="row"><text class="label">物流存欠料</text><text class="value">{{ safeText(form.logisticsStockMaterial) }}</text></view>
  21 + <view class="row"><text class="label">车牌号</text><text class="value">{{ safeText(form.plateNumber) }}</text></view>
  22 + </view>
  23 +
  24 + <!-- 业务摘要 -->
  25 + <view class="title-header">
  26 + <image class="title-header_icon" src="/static/images/title.png" />
  27 + <span>业务摘要</span>
  28 + </view>
  29 + <view class="section">
  30 + <text class="remark-text">{{ safeText(form.businessSummary) }}</text>
  31 + </view>
  32 +
  33 + <!-- 特别说明 -->
  34 + <view class="title-header">
  35 + <image class="title-header_icon" src="/static/images/title.png" />
  36 + <span>特别说明</span>
  37 + </view>
  38 + <view class="section">
  39 + <text class="remark-text">{{ safeText(form.specialNote) }}</text>
  40 + </view>
  41 +
  42 + <!-- 单据备注 -->
  43 + <view class="title-header">
  44 + <image class="title-header_icon" src="/static/images/title.png" />
  45 + <span>单据备注</span>
  46 + </view>
  47 + <view class="section">
  48 + <text class="remark-text">{{ safeText(form.specialNote) }}</text>
  49 + </view>
  50 +
  51 + <!-- 计划单明细 -->
  52 + <view class="sub-table">
  53 + <view class="sub-header">
  54 + <image class="sub-bar" src="/static/images/title.png" />
  55 + <text class="sub-title">计划单明细</text>
  56 + <view class="sub-toggle" @click="toggle('plan')">
  57 + <image class="sub-toggle_icon" :src="collapse.plan ? '/static/images/down.png' : '/static/images/up.png'" />
  58 + <text class="sub-toggle_text">{{ collapse.plan ? '展开' : '收起' }}</text>
  59 + </view>
  60 + </view>
  61 + <view v-if="!collapse.plan" class="sub-body">
  62 + <view v-if="!planList.length" class="empty-tip">暂无明细</view>
  63 + <view v-for="(item, idx) in planList" :key="'p-' + (item.id || idx)" class="card">
  64 + <view class="card-index">第 {{ idx + 1 }} 行</view>
  65 + <view class="row"><text class="label">计划品种</text><text class="value">{{ safeText(item.productName) }}</text></view>
  66 + <view class="row"><text class="label">计划数量</text><text class="value">{{ formatNumber(item.quantity) }}</text></view>
  67 + <view class="row"><text class="label">计划编号</text><text class="value">{{ safeText(item.planCode) }}</text></view>
  68 + </view>
  69 + </view>
  70 + </view>
  71 +
  72 + <!-- 过磅明细 -->
  73 + <view class="sub-table">
  74 + <view class="sub-header">
  75 + <image class="sub-bar" src="/static/images/title.png" />
  76 + <text class="sub-title">过磅明细</text>
  77 + <view class="sub-toggle" @click="toggle('weigh')">
  78 + <image class="sub-toggle_icon" :src="collapse.weigh ? '/static/images/down.png' : '/static/images/up.png'" />
  79 + <text class="sub-toggle_text">{{ collapse.weigh ? '展开' : '收起' }}</text>
  80 + </view>
  81 + </view>
  82 + <view v-if="!collapse.weigh" class="sub-body">
  83 + <view v-if="!weighList.length" class="empty-tip">暂无明细</view>
  84 + <view v-for="(item, idx) in weighList" :key="'w-' + (item.id || idx)" class="card">
  85 + <view class="card-index">第 {{ idx + 1 }} 行</view>
  86 + <view class="row"><text class="label">过磅品种</text><text class="value">{{ safeText(item.productName) }}</text></view>
  87 + <view class="row"><text class="label">开票品名</text><text class="value">{{ safeText(item.invoiceProductName) }}</text></view>
  88 + <view class="row"><text class="label">过磅数量</text><text class="value">{{ formatNumber(item.quantity) }}</text></view>
  89 + <view class="row"><text class="label">计划编号</text><text class="value">{{ safeText(item.planCode) }}</text></view>
  90 + </view>
  91 + </view>
  92 + </view>
  93 +
  94 + <!-- 申请数量明细 -->
  95 + <view class="sub-table">
  96 + <view class="sub-header">
  97 + <image class="sub-bar" src="/static/images/title.png" />
  98 + <text class="sub-title">申请数量明细</text>
  99 + <view class="sub-toggle" @click="toggle('apply')">
  100 + <image class="sub-toggle_icon" :src="collapse.apply ? '/static/images/down.png' : '/static/images/up.png'" />
  101 + <text class="sub-toggle_text">{{ collapse.apply ? '展开' : '收起' }}</text>
  102 + </view>
  103 + </view>
  104 + <view v-if="!collapse.apply" class="sub-body">
  105 + <view v-if="!applyList.length" class="empty-tip">暂无明细</view>
  106 + <view v-for="(item, idx) in applyList" :key="'a-' + (item.id || idx)" class="card">
  107 + <view class="card-index">第 {{ idx + 1 }} 行</view>
  108 + <view class="row"><text class="label">类别</text><text class="value">{{ safeText(item.category) }}</text></view>
  109 + <view class="row"><text class="label">数量</text><text class="value">{{ formatNumber(item.quantity) }}</text></view>
  110 + </view>
  111 + </view>
  112 + </view>
  113 + </view>
  114 + </scroll-view>
  115 + </view>
  116 +</template>
  117 +
  118 +<script>
  119 +import { weighTicketDetailApi } from '@/api/procure-manage/weighTicket.js'
  120 +
  121 +export default {
  122 + name: 'WeightTicketDetail',
  123 + data() {
  124 + return {
  125 + id: '',
  126 + form: {},
  127 + planList: [],
  128 + weighList: [],
  129 + applyList: [],
  130 + collapse: { plan: false, weigh: false, apply: false }
  131 + }
  132 + },
  133 + onLoad(query) {
  134 + this.id = (query && query.id) || ''
  135 + this.loadDetail()
  136 + },
  137 + onShow() {
  138 + let needRefresh = ''
  139 + try { needRefresh = uni.getStorageSync('WEIGHT_TICKET_DETAIL_NEED_REFRESH') } catch (e) {}
  140 + if (!needRefresh) return
  141 + try { uni.removeStorageSync('WEIGHT_TICKET_DETAIL_NEED_REFRESH') } catch (e) {}
  142 + this.loadDetail()
  143 + },
  144 + methods: {
  145 + toggle(key) {
  146 + this.collapse = { ...this.collapse, [key]: !this.collapse[key] }
  147 + },
  148 + loadDetail() {
  149 + if (!this.id) {
  150 + uni.showToast({ title: '缺少单据ID', icon: 'none' })
  151 + return
  152 + }
  153 + uni.showLoading && uni.showLoading({ title: '加载中...', mask: true })
  154 + weighTicketDetailApi({ id: this.id })
  155 + .then(res => {
  156 + const data = res && res.data ? (res.data.data || res.data) : {}
  157 + this.form = Object.assign({}, data)
  158 + this.planList = this.pickList(data, ['planDetailList', 'planLineList', 'procurementPlanLineList'])
  159 + this.weighList = this.pickList(data, ['weighDetailList', 'weighLineList', 'grossWeightList'])
  160 + this.applyList = this.pickList(data, ['applyQuantityList', 'applyDetailList', 'applyLineList'])
  161 + })
  162 + .catch(() => {
  163 + uni.showToast({ title: '详情加载失败', icon: 'none' })
  164 + })
  165 + .finally(() => {
  166 + uni.hideLoading && uni.hideLoading()
  167 + })
  168 + },
  169 + pickList(data, keys) {
  170 + if (!data) return []
  171 + for (const k of keys) {
  172 + if (Array.isArray(data[k])) return data[k].map(x => Object.assign({}, x))
  173 + }
  174 + return []
  175 + },
  176 + safeText(v) {
  177 + const s = v == null ? '' : String(v)
  178 + return s.trim() ? s : '-'
  179 + },
  180 + formatNumber(v) {
  181 + if (v === null || v === undefined || v === '') return '-'
  182 + const n = Number(v)
  183 + if (isNaN(n)) return String(v)
  184 + return n.toLocaleString('zh-CN', { maximumFractionDigits: 4 })
  185 + },
  186 + formatDate(v) {
  187 + const s = v == null ? '' : String(v).trim()
  188 + if (!s) return '-'
  189 + return s
  190 + }
  191 + }
  192 +}
  193 +</script>
  194 +
  195 +<style lang="scss" scoped>
  196 +.page {
  197 + display: flex;
  198 + flex-direction: column;
  199 + height: 100%;
  200 +}
  201 +.scroll {
  202 + flex: 1;
  203 + padding: 8rpx 0 32rpx;
  204 +}
  205 +.detail-page {
  206 + background: #f3f3f3;
  207 +}
  208 +.section {
  209 + padding: 32rpx;
  210 + background: #fff;
  211 + margin-bottom: 20rpx;
  212 +}
  213 +.title-header {
  214 + display: flex;
  215 + align-items: center;
  216 + padding: 24rpx 32rpx 12rpx;
  217 + background-color: #ffffff;
  218 + .title-header_icon { width: 36rpx; height: 36rpx; margin-right: 12rpx; }
  219 + span { font-size: 34rpx; font-weight: 600; color: rgba(0, 0, 0, 0.9); }
  220 +}
  221 +.row {
  222 + display: flex;
  223 + margin-bottom: 28rpx;
  224 + &:last-child { margin-bottom: 0; }
  225 + &.company {
  226 + font-size: 36rpx;
  227 + font-weight: 600;
  228 + color: rgba(0, 0, 0, 0.9);
  229 + padding-top: 8rpx;
  230 + line-height: 50rpx;
  231 + }
  232 + .label {
  233 + max-width: 420rpx;
  234 + margin-right: 20rpx;
  235 + line-height: 32rpx;
  236 + font-size: 28rpx;
  237 + color: rgba(0, 0, 0, 0.6);
  238 + }
  239 + .value {
  240 + flex: 1;
  241 + line-height: 32rpx;
  242 + font-size: 28rpx;
  243 + color: rgba(0, 0, 0, 0.9);
  244 + text-align: right;
  245 + word-break: break-all;
  246 + }
  247 +}
  248 +.remark-text {
  249 + font-size: 28rpx;
  250 + color: rgba(0, 0, 0, 0.9);
  251 + line-height: 1.6;
  252 + white-space: pre-wrap;
  253 +}
  254 +.sub-table {
  255 + background: #fff;
  256 + margin-bottom: 20rpx;
  257 +}
  258 +.sub-header {
  259 + display: flex;
  260 + align-items: center;
  261 + padding: 16rpx 0 16rpx 32rpx;
  262 + .sub-bar { width: 6rpx; height: 32rpx; margin-right: 14rpx; }
  263 + .sub-title { font-size: 30rpx; font-weight: 600; color: rgba(0, 0, 0, 0.9); flex: 1; line-height: 42rpx; }
  264 + .sub-toggle {
  265 + display: flex;
  266 + align-items: center;
  267 + padding: 0 12rpx;
  268 + height: 56rpx;
  269 + .sub-toggle_icon { width: 24rpx; height: 24rpx; margin-right: 8rpx; }
  270 + .sub-toggle_text { font-size: 26rpx; color: rgba(0, 0, 0, 0.6); }
  271 + }
  272 +}
  273 +.sub-body {
  274 + padding: 0 32rpx 24rpx;
  275 + .empty-tip {
  276 + text-align: center;
  277 + padding: 60rpx 0;
  278 + color: rgba(0, 0, 0, 0.4);
  279 + font-size: 28rpx;
  280 + }
  281 + .card {
  282 + position: relative;
  283 + background: #fafafa;
  284 + border-radius: 12rpx;
  285 + padding: 32rpx 28rpx 20rpx;
  286 + margin-bottom: 24rpx;
  287 + .card-index {
  288 + position: absolute;
  289 + top: 0;
  290 + right: 0;
  291 + background: rgba(24, 144, 255, 0.08);
  292 + color: $theme-primary;
  293 + font-size: 22rpx;
  294 + line-height: 36rpx;
  295 + padding: 0 16rpx;
  296 + border-bottom-left-radius: 12rpx;
  297 + border-top-right-radius: 12rpx;
  298 + }
  299 + .row {
  300 + align-items: center;
  301 + justify-content: space-between;
  302 + padding: 14rpx 0;
  303 + margin-bottom: 0;
  304 + border-bottom: 1rpx dashed #f2f2f2;
  305 + &:last-child { border-bottom: none; }
  306 + .label {
  307 + flex-shrink: 0;
  308 + width: 220rpx;
  309 + max-width: none;
  310 + margin-right: 0;
  311 + font-size: 28rpx;
  312 + color: rgba(0, 0, 0, 0.6);
  313 + line-height: 40rpx;
  314 + }
  315 + .value {
  316 + flex: 1;
  317 + text-align: right;
  318 + font-size: 28rpx;
  319 + color: rgba(0, 0, 0, 0.9);
  320 + line-height: 40rpx;
  321 + overflow: hidden;
  322 + text-overflow: ellipsis;
  323 + white-space: nowrap;
  324 + }
  325 + }
  326 + }
  327 +}
  328 +</style>
... ...
1 1 <template>
2   - <view class="page">
3   -
  2 + <view class="page">
  3 + <view class="ticket-list-fixed">
  4 + <view class="search-row">
  5 + <uni-search-bar
  6 + v-model="searchKeyword"
  7 + radius="6"
  8 + placeholder="请输入编号/计划编号/供料单位"
  9 + clearButton="auto"
  10 + cancelButton="none"
  11 + bgColor="#F3F3F3"
  12 + textColor="rgba(0,0,0,0.4)"
  13 + @confirm="search"
  14 + @input="onSearchInput"
  15 + />
  16 + <view class="tool-icons">
  17 + <image
  18 + v-if="$auth.hasPermi('procure-manage:weigh-ticket:add')"
  19 + class="tool-icon"
  20 + src="/static/images/dev_manage/add_icon.png"
  21 + @click="onAdd"
  22 + />
  23 + <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
  24 + </view>
  25 + </view>
  26 +
  27 + <view class="tabs">
  28 + <view
  29 + v-for="(t, i) in tabs"
  30 + :key="i"
  31 + :class="['tab', { active: deleted === t.value }]"
  32 + @click="switchTab(t)"
  33 + >
  34 + {{ t.label }}
  35 + </view>
  36 + </view>
4 37 </view>
5   -</template>
\ No newline at end of file
  38 +
  39 + <view class="list-box">
  40 + <card-list
  41 + ref="cardRef"
  42 + :fetch-fn="fetchList"
  43 + :query="query"
  44 + :extra="extraParams"
  45 + row-key="id"
  46 + :enable-refresh="true"
  47 + :enable-load-more="true"
  48 + @loaded="onCardLoaded"
  49 + @error="onCardError"
  50 + >
  51 + <template v-slot="{ item }">
  52 + <view class="card" @click="onCardClick(item)">
  53 + <view class="card-header">
  54 + <text class="title omit2">{{ item.supplierName || '-' }}</text>
  55 + <text :class="['status', `status_${item.approvalStatus}`]">{{ getAuditStatusText(item.approvalStatus) }}</text>
  56 + </view>
  57 + <view class="info-row">
  58 + <text>编号</text>
  59 + <text>{{ item.code || '-' }}</text>
  60 + </view>
  61 + <view class="info-row">
  62 + <text>计划编号</text>
  63 + <text>{{ item.planCode || '-' }}</text>
  64 + </view>
  65 + <view class="info-row">
  66 + <text>公司简称</text>
  67 + <text>{{ item.companyShortName || '-' }}</text>
  68 + </view>
  69 + <view class="info-row">
  70 + <text>时间</text>
  71 + <text>{{ formatDateOnly(item.firstGrossWeightTime) }}</text>
  72 + </view>
  73 + </view>
  74 + </template>
  75 + </card-list>
  76 + </view>
  77 +
  78 + <filter-modal
  79 + :visible.sync="filterVisible"
  80 + :value.sync="filterForm"
  81 + title="筛选"
  82 + @reset="onFilterReset"
  83 + @confirm="onFilterConfirm"
  84 + >
  85 + <template v-slot="{ model }">
  86 + <view class="filter-form">
  87 + <view class="form-item">
  88 + <view class="label">编号</view>
  89 + <input class="input" v-model="model.code" placeholder="请输入编号" />
  90 + </view>
  91 + <view class="form-item">
  92 + <view class="label">计划编号</view>
  93 + <input class="input" v-model="model.planCode" placeholder="请输入计划编号" />
  94 + </view>
  95 + <view class="form-item">
  96 + <view class="label">供料单位</view>
  97 + <input class="input" v-model="model.supplierName" placeholder="请输入供料单位" />
  98 + </view>
  99 + <view class="form-item">
  100 + <view class="label">公司简称</view>
  101 + <input class="input" v-model="model.companyShortName" placeholder="请输入公司简称" />
  102 + </view>
  103 + <view class="form-item">
  104 + <view class="label">审核状态</view>
  105 + <uni-data-checkbox
  106 + mode="tag"
  107 + :multiple="false"
  108 + :value-field="'value'"
  109 + :text-field="'text'"
  110 + v-model="model.approvalStatus"
  111 + @change="onApprovalStatusChange"
  112 + :localdata="approvalStatusOptions"
  113 + />
  114 + </view>
  115 + <view class="form-item">
  116 + <view class="label">时间</view>
  117 + <uni-datetime-picker type="daterange" v-model="model.timeRange" start="2023-01-01" />
  118 + </view>
  119 + </view>
  120 + </template>
  121 + </filter-modal>
  122 + </view>
  123 +</template>
  124 +
  125 +<script>
  126 +import CardList from '@/components/card/index.vue'
  127 +import FilterModal from '@/components/filter/index.vue'
  128 +import { getDicByCodes, getDicName } from '@/utils/dic.js'
  129 +import { weighTicketQueryApi } from '@/api/procure-manage/weighTicket.js'
  130 +
  131 +export default {
  132 + name: 'WeightTicketList',
  133 + components: { CardList, FilterModal },
  134 + data() {
  135 + return {
  136 + searchKeyword: '',
  137 + searchKeywordDebounced: '',
  138 + searchDebounceTimer: null,
  139 + deleted: 0,
  140 + tabs: [
  141 + { label: '有效', value: 0 },
  142 + { label: '作废', value: 1 }
  143 + ],
  144 + query: {
  145 + code: '',
  146 + planCode: '',
  147 + supplierName: '',
  148 + companyShortName: '',
  149 + approvalStatus: '',
  150 + timeRange: []
  151 + },
  152 + extraParams: {},
  153 + currentItems: [],
  154 + filterVisible: false,
  155 + filterForm: {
  156 + code: '',
  157 + planCode: '',
  158 + supplierName: '',
  159 + companyShortName: '',
  160 + approvalStatus: '',
  161 + timeRange: []
  162 + },
  163 + approvalStatusOptions: [{ value: '', text: '全部' }],
  164 + dicOptions: {
  165 + AUDIT_STATUS: []
  166 + }
  167 + }
  168 + },
  169 + computed: {
  170 + extraCombined() {
  171 + const keyword = this.searchKeywordDebounced || ''
  172 + return {
  173 + keyword: keyword || undefined,
  174 + deleted: this.deleted
  175 + }
  176 + }
  177 + },
  178 + watch: {
  179 + extraCombined: {
  180 + deep: true,
  181 + handler(v) {
  182 + this.extraParams = v
  183 + },
  184 + immediate: true
  185 + }
  186 + },
  187 + created() {
  188 + this.loadDicData()
  189 + },
  190 + onShow() {
  191 + let needRefresh = ''
  192 + try { needRefresh = uni.getStorageSync('WEIGHT_TICKET_LIST_NEED_REFRESH') } catch (e) {}
  193 + if (!needRefresh) return
  194 + try { uni.removeStorageSync('WEIGHT_TICKET_LIST_NEED_REFRESH') } catch (e) {}
  195 + if (this.$refs && this.$refs.cardRef && this.$refs.cardRef.reload) {
  196 + this.$refs.cardRef.reload()
  197 + }
  198 + },
  199 + onReachBottom() {
  200 + if (this.$refs && this.$refs.cardRef && this.$refs.cardRef.onLoadMore) {
  201 + this.$refs.cardRef.onLoadMore()
  202 + }
  203 + },
  204 + beforeDestroy() {
  205 + if (this.searchDebounceTimer) {
  206 + clearTimeout(this.searchDebounceTimer)
  207 + this.searchDebounceTimer = null
  208 + }
  209 + },
  210 + methods: {
  211 + async loadDicData() {
  212 + try {
  213 + const results = await getDicByCodes(['AUDIT_STATUS'])
  214 + this.dicOptions.AUDIT_STATUS = (results.AUDIT_STATUS && results.AUDIT_STATUS.data) || []
  215 + const list = Array.isArray(this.dicOptions.AUDIT_STATUS) ? this.dicOptions.AUDIT_STATUS : []
  216 + this.approvalStatusOptions = [{ value: '', text: '全部' }].concat(
  217 + list
  218 + .map(it => ({
  219 + value: it && it.code != null ? String(it.code) : '',
  220 + text: it && it.name != null ? String(it.name) : ''
  221 + }))
  222 + .filter(it => it.value)
  223 + )
  224 + } catch (e) {
  225 + this.dicOptions.AUDIT_STATUS = []
  226 + this.approvalStatusOptions = [{ value: '', text: '全部' }]
  227 + }
  228 + },
  229 + getAuditStatusText(status) {
  230 + const v = status == null ? '' : String(status)
  231 + if (!v) return '-'
  232 + return getDicName('AUDIT_STATUS', v, this.dicOptions.AUDIT_STATUS) || v
  233 + },
  234 + formatDateOnly(v) {
  235 + const s = v == null ? '' : String(v).trim()
  236 + if (!s) return '-'
  237 + if (s.length >= 10) return s.slice(0, 10)
  238 + return s
  239 + },
  240 + onCardLoaded({ items }) {
  241 + this.currentItems = items
  242 + },
  243 + onCardError() {
  244 + uni.showToast({ title: '列表加载失败', icon: 'none' })
  245 + },
  246 + onAdd() {
  247 + uni.navigateTo({ url: '/pages/weight-ticket/add' })
  248 + },
  249 + onSearchInput() {
  250 + if (this.searchDebounceTimer) clearTimeout(this.searchDebounceTimer)
  251 + this.searchDebounceTimer = setTimeout(() => {
  252 + this.searchKeywordDebounced = this.searchKeyword
  253 + this.searchDebounceTimer = null
  254 + }, 1200)
  255 + },
  256 + search(e) {
  257 + const val = e && e.value != null ? e.value : this.searchKeyword
  258 + this.searchKeyword = val
  259 + this.searchKeywordDebounced = val
  260 + },
  261 + switchTab(t) {
  262 + this.deleted = t.value
  263 + },
  264 + openFilter() {
  265 + this.filterForm = {
  266 + code: this.query.code || '',
  267 + planCode: this.query.planCode || '',
  268 + supplierName: this.query.supplierName || '',
  269 + companyShortName: this.query.companyShortName || '',
  270 + approvalStatus: this.query.approvalStatus || '',
  271 + timeRange: Array.isArray(this.query.timeRange) ? this.query.timeRange.slice(0) : []
  272 + }
  273 + this.filterVisible = true
  274 + },
  275 + onFilterReset(payload) {
  276 + this.filterForm = payload
  277 + },
  278 + onFilterConfirm(payload) {
  279 + this.query = {
  280 + code: payload.code || '',
  281 + planCode: payload.planCode || '',
  282 + supplierName: payload.supplierName || '',
  283 + companyShortName: payload.companyShortName || '',
  284 + approvalStatus: payload.approvalStatus || '',
  285 + timeRange: Array.isArray(payload.timeRange) ? payload.timeRange : []
  286 + }
  287 + },
  288 + onApprovalStatusChange(e) {
  289 + const raw =
  290 + e && e.detail && e.detail.value !== undefined
  291 + ? e.detail.value
  292 + : e && e.value !== undefined
  293 + ? e.value
  294 + : ''
  295 + this.filterForm.approvalStatus = raw
  296 + },
  297 + fetchList({ pageIndex, pageSize, query, extra }) {
  298 + const q = query || {}
  299 + const e = extra || {}
  300 + const range = Array.isArray(q.timeRange) ? q.timeRange : []
  301 + const keyword = e.keyword || ''
  302 + const params = {
  303 + pageIndex,
  304 + pageSize,
  305 + deleted: e.deleted != null ? e.deleted : 0,
  306 + code: q.code || '',
  307 + planCode: q.planCode || '',
  308 + supplierName: q.supplierName || '',
  309 + companyShortName: q.companyShortName || '',
  310 + approvalStatus: q.approvalStatus || '',
  311 + startFirstGrossWeightTime: range && range.length === 2 ? range[0] : '',
  312 + endFirstGrossWeightTime: range && range.length === 2 ? range[1] : ''
  313 + }
  314 + if (keyword) {
  315 + if (!params.code) params.code = keyword
  316 + if (!params.planCode) params.planCode = keyword
  317 + if (!params.supplierName) params.supplierName = keyword
  318 + }
  319 + return weighTicketQueryApi(params)
  320 + .then(res => {
  321 + const _data = (res && res.data) || {}
  322 + let records = _data.datas || _data.list || _data.records || []
  323 + const totalCount = _data.totalCount || _data.count || 0
  324 + const hasNext = _data.hasNext || false
  325 + records = records.map(it => ({ ...it }))
  326 + return { records, totalCount, hasNext }
  327 + })
  328 + .catch(() => {
  329 + this.onCardError()
  330 + return { records: [], totalCount: 0, hasNext: false }
  331 + })
  332 + },
  333 + onCardClick(item) {
  334 + const id = item && (item.id || item.weighTicketId)
  335 + if (!id) {
  336 + uni.showToast({ title: '缺少ID', icon: 'none' })
  337 + return
  338 + }
  339 + uni.navigateTo({ url: '/pages/weight-ticket/detail?id=' + id })
  340 + }
  341 + }
  342 +}
  343 +</script>
  344 +
  345 +<style lang="scss" scoped>
  346 +.page {
  347 + display: flex;
  348 + flex-direction: column;
  349 + height: 100vh;
  350 +}
  351 +.ticket-list-fixed {
  352 + position: fixed;
  353 + top: 96rpx;
  354 + left: 0;
  355 + right: 0;
  356 + z-index: 2;
  357 + background: #fff;
  358 + .search-row {
  359 + display: flex;
  360 + align-items: center;
  361 + padding: 16rpx 32rpx;
  362 + .uni-searchbar { padding: 0; flex: 1; }
  363 + .tool-icons {
  364 + display: flex;
  365 + .tool-icon { width: 48rpx; height: 48rpx; display: block; margin-left: 32rpx; }
  366 + }
  367 + }
  368 + .tabs {
  369 + display: flex;
  370 + align-items: center;
  371 + justify-content: space-between;
  372 + padding: 26rpx 34rpx;
  373 + border-bottom: solid 1px #e7e7e7;
  374 + .tab { width: 50%; text-align: center; color: rgba(0, 0, 0, 0.9); line-height: 44rpx; position: relative; font-weight: 600; }
  375 + .tab.active { color: $theme-primary; }
  376 + .tab.active::after {
  377 + content: '';
  378 + position: absolute;
  379 + left: 50%;
  380 + transform: translateX(-50%);
  381 + bottom: -13px;
  382 + width: 32rpx;
  383 + height: 6rpx;
  384 + border-radius: 4rpx;
  385 + background: $theme-primary;
  386 + }
  387 + }
  388 +}
  389 +::v-deep .uni-searchbar__box {
  390 + height: 80rpx !important;
  391 + justify-content: start;
  392 + .uni-searchbar__box-search-input { font-size: 32rpx !important; }
  393 +}
  394 +.list-box {
  395 + flex: 1;
  396 + padding-top: 236rpx;
  397 + .card { position: relative; }
  398 + .card-header {
  399 + margin-bottom: 28rpx;
  400 + position: relative;
  401 + .title { font-size: 36rpx; font-weight: 600; line-height: 50rpx; color: rgba(0, 0, 0, 0.9); width: 578rpx; }
  402 + .status {
  403 + position: absolute;
  404 + top: -32rpx;
  405 + right: -12rpx;
  406 + height: 48rpx;
  407 + line-height: 48rpx;
  408 + font-weight: 600;
  409 + color: #fff;
  410 + font-size: 24rpx;
  411 + padding: 0 14rpx;
  412 + border-radius: 6rpx;
  413 + box-sizing: content-box;
  414 +
  415 + &.status_AUDIT { background: $theme-primary; }
  416 + &.status_PASS { background: #2ba471; }
  417 + &.status_REFUSE { background: #d54941; }
  418 + &.status_CANCEL { background: #e7e7e7; color: rgba(0, 0, 0, 0.9); }
  419 + }
  420 + }
  421 + .info-row {
  422 + display: flex;
  423 + align-items: center;
  424 + color: rgba(0, 0, 0, 0.6);
  425 + font-size: 28rpx;
  426 + margin-bottom: 24rpx;
  427 + height: 32rpx;
  428 + &:last-child { margin-bottom: 0; }
  429 + text {
  430 + width: 50%;
  431 + &:last-child {
  432 + color: rgba(0, 0, 0, 0.9);
  433 + width: 50%;
  434 + overflow: hidden;
  435 + text-overflow: ellipsis;
  436 + white-space: nowrap;
  437 + }
  438 + }
  439 + }
  440 +}
  441 +.filter-form {
  442 + .form-item { margin-bottom: 24rpx; }
  443 + .label { margin-bottom: 20rpx; color: rgba(0, 0, 0, 0.9); height: 44rpx; line-height: 44rpx; font-size: 30rpx; }
  444 + .input {
  445 + width: 100%;
  446 + height: 72rpx;
  447 + line-height: 72rpx;
  448 + padding: 0 24rpx;
  449 + border: 1rpx solid #e7e7e7;
  450 + border-radius: 8rpx;
  451 + font-size: 28rpx;
  452 + color: rgba(0, 0, 0, 0.9);
  453 + background: #fff;
  454 + box-sizing: border-box;
  455 + }
  456 +}
  457 +</style>
... ...
  1 +<template>
  2 + <view class="page">
  3 + <scroll-view class="scroll" scroll-y>
  4 + <uni-list>
  5 + <!-- 编号 -->
  6 + <uni-list-item class="select-item" :class="form.code ? 'is-filled' : 'is-empty'">
  7 + <template v-slot:body>
  8 + <view class="item-title"><text>编号</text></view>
  9 + </template>
  10 + <template v-slot:footer>
  11 + <text class="readonly-text value-code">{{ form.code || '-' }}</text>
  12 + </template>
  13 + </uni-list-item>
  14 +
  15 + <!-- 类型 -->
  16 + <uni-list-item>
  17 + <template v-slot:body>
  18 + <view class="item-title"><text class="required">*</text><text>类型</text></view>
  19 + </template>
  20 + <template v-slot:footer>
  21 + <uni-easyinput v-model="form.type" :inputBorder="false" placeholder="请输入类型" />
  22 + </template>
  23 + </uni-list-item>
  24 +
  25 + <!-- 计划编号 -->
  26 + <uni-list-item>
  27 + <template v-slot:body>
  28 + <view class="item-title"><text class="required">*</text><text>计划编号</text></view>
  29 + </template>
  30 + <template v-slot:footer>
  31 + <uni-easyinput v-model="form.unit" :inputBorder="false" placeholder="请输入计划编号" />
  32 + </template>
  33 + </uni-list-item>
  34 +
  35 + <!-- 时间 -->
  36 + <uni-list-item class="select-item" :class="form.firstGrossWeightTime ? 'is-filled' : 'is-empty'">
  37 + <template v-slot:body>
  38 + <view class="item-title"><text class="required">*</text><text>时间</text></view>
  39 + </template>
  40 + <template v-slot:footer>
  41 + <uni-datetime-picker type="date" v-model="form.firstGrossWeightTime" />
  42 + </template>
  43 + </uni-list-item>
  44 +
  45 + <!-- 供料单位 -->
  46 + <uni-list-item>
  47 + <template v-slot:body>
  48 + <view class="item-title"><text class="required">*</text><text>供料单位</text></view>
  49 + </template>
  50 + <template v-slot:footer>
  51 + <uni-easyinput v-model="form.supplierName" :inputBorder="false" placeholder="请输入供料单位" />
  52 + </template>
  53 + </uni-list-item>
  54 +
  55 + <!-- 收料单位 -->
  56 + <uni-list-item>
  57 + <template v-slot:body>
  58 + <view class="item-title"><text class="required">*</text><text>收料单位</text></view>
  59 + </template>
  60 + <template v-slot:footer>
  61 + <uni-easyinput v-model="form.companyShortName" :inputBorder="false" placeholder="请输入收料单位" />
  62 + </template>
  63 + </uni-list-item>
  64 +
  65 + <!-- 物料名称 -->
  66 + <uni-list-item>
  67 + <template v-slot:body>
  68 + <view class="item-title"><text class="required">*</text><text>物料名称</text></view>
  69 + </template>
  70 + <template v-slot:footer>
  71 + <uni-easyinput v-model="form.materialName" :inputBorder="false" placeholder="请输入物料名称" />
  72 + </template>
  73 + </uni-list-item>
  74 +
  75 + <!-- 过磅总重 -->
  76 + <uni-list-item>
  77 + <template v-slot:body>
  78 + <view class="item-title"><text class="required">*</text><text>过磅总重</text></view>
  79 + </template>
  80 + <template v-slot:footer>
  81 + <uni-easyinput v-model="form.totalGrossWeight" type="digit" :inputBorder="false" placeholder="请输入过磅总重" @input="calcNetWeight" />
  82 + </template>
  83 + </uni-list-item>
  84 +
  85 + <!-- 实际伙重 -->
  86 + <uni-list-item title="实际伙重">
  87 + <template v-slot:footer>
  88 + <uni-easyinput v-model="form.actualImpurityWeight" type="digit" :inputBorder="false" placeholder="请输入实际伙重" @input="calcNetWeight" />
  89 + </template>
  90 + </uni-list-item>
  91 +
  92 + <!-- 货物净重 -->
  93 + <uni-list-item title="货物净重">
  94 + <template v-slot:footer>
  95 + <uni-easyinput v-model="form.netWeight" type="digit" :inputBorder="false" placeholder="请输入货物净重" />
  96 + </template>
  97 + </uni-list-item>
  98 +
  99 + <!-- 净重大写 -->
  100 + <uni-list-item title="净重大写">
  101 + <template v-slot:footer>
  102 + <uni-easyinput v-model="form.netWeightUpper" :inputBorder="false" placeholder="请输入净重大写" />
  103 + </template>
  104 + </uni-list-item>
  105 +
  106 + <!-- 来料扣杂类型 -->
  107 + <uni-list-item title="来料扣杂类型">
  108 + <template v-slot:footer>
  109 + <uni-easyinput v-model="form.deductionTypes" :inputBorder="false" placeholder="请输入来料扣杂类型" />
  110 + </template>
  111 + </uni-list-item>
  112 +
  113 + <!-- 供应存欠料 -->
  114 + <uni-list-item title="供应存欠料">
  115 + <template v-slot:footer>
  116 + <uni-easyinput v-model="form.supplierStockMaterial" type="digit" :inputBorder="false" placeholder="请输入供应存欠料" />
  117 + </template>
  118 + </uni-list-item>
  119 +
  120 + <!-- 物流存欠料 -->
  121 + <uni-list-item title="物流存欠料">
  122 + <template v-slot:footer>
  123 + <uni-easyinput v-model="form.logisticsStockMaterial" type="digit" :inputBorder="false" placeholder="请输入物流存欠料" />
  124 + </template>
  125 + </uni-list-item>
  126 +
  127 + <!-- 车牌号 -->
  128 + <uni-list-item>
  129 + <template v-slot:body>
  130 + <view class="item-title"><text class="required">*</text><text>车牌号</text></view>
  131 + </template>
  132 + <template v-slot:footer>
  133 + <uni-easyinput v-model="form.plateNumber" :inputBorder="false" placeholder="请输入车牌号" />
  134 + </template>
  135 + </uni-list-item>
  136 + </uni-list>
  137 +
  138 + <!-- 计划单明细 -->
  139 + <view class="sub-table">
  140 + <view class="header">
  141 + <image class="opCollapse" src="/static/images/title.png" />
  142 + <text class="title">计划单明细</text>
  143 + <view class="ops">
  144 + <image class="opAdd" @click="addPlan" src="/static/images/plus.png" />
  145 + </view>
  146 + </view>
  147 + <view class="add-list">
  148 + <view v-if="!planList.length" class="empty-tip">暂无明细,请添加</view>
  149 + <view v-for="(item, idx) in planList" :key="'p-' + idx" class="block">
  150 + <uni-list>
  151 + <uni-list-item title="计划品种">
  152 + <template v-slot:footer>
  153 + <uni-easyinput v-model="item.productName" :inputBorder="false" placeholder="请输入计划品种" />
  154 + </template>
  155 + </uni-list-item>
  156 + <uni-list-item title="计划数量">
  157 + <template v-slot:footer>
  158 + <uni-easyinput v-model="item.quantity" type="digit" :inputBorder="false" placeholder="请输入计划数量" />
  159 + </template>
  160 + </uni-list-item>
  161 + <uni-list-item title="计划编号">
  162 + <template v-slot:footer>
  163 + <uni-easyinput v-model="item.planCode" :inputBorder="false" placeholder="请输入计划编号" />
  164 + </template>
  165 + </uni-list-item>
  166 + </uni-list>
  167 + <view class="block-ops">
  168 + <div class="del" @click="removeRow('plan', idx)">
  169 + <image src="/static/images/delete.png" class="icon" />删除
  170 + </div>
  171 + </view>
  172 + </view>
  173 + </view>
  174 + </view>
  175 +
  176 + <!-- 过磅明细 -->
  177 + <view class="sub-table">
  178 + <view class="header">
  179 + <image class="opCollapse" src="/static/images/title.png" />
  180 + <text class="title">过磅明细</text>
  181 + <view class="ops">
  182 + <image class="opAdd" @click="addWeigh" src="/static/images/plus.png" />
  183 + </view>
  184 + </view>
  185 + <view class="add-list">
  186 + <view v-if="!weighList.length" class="empty-tip">暂无明细,请添加</view>
  187 + <view v-for="(item, idx) in weighList" :key="'w-' + idx" class="block">
  188 + <uni-list>
  189 + <uni-list-item title="过磅品种">
  190 + <template v-slot:footer>
  191 + <uni-easyinput v-model="item.productName" :inputBorder="false" placeholder="请输入过磅品种" />
  192 + </template>
  193 + </uni-list-item>
  194 + <uni-list-item title="开票品名">
  195 + <template v-slot:footer>
  196 + <uni-easyinput v-model="item.invoiceProductName" :inputBorder="false" placeholder="请输入开票品名" />
  197 + </template>
  198 + </uni-list-item>
  199 + <uni-list-item title="过磅数量">
  200 + <template v-slot:footer>
  201 + <uni-easyinput v-model="item.quantity" type="digit" :inputBorder="false" placeholder="请输入过磅数量" />
  202 + </template>
  203 + </uni-list-item>
  204 + <uni-list-item title="计划编号">
  205 + <template v-slot:footer>
  206 + <uni-easyinput v-model="item.planCode" :inputBorder="false" placeholder="请输入计划编号" />
  207 + </template>
  208 + </uni-list-item>
  209 + </uni-list>
  210 + <view class="block-ops">
  211 + <div class="del" @click="removeRow('weigh', idx)">
  212 + <image src="/static/images/delete.png" class="icon" />删除
  213 + </div>
  214 + </view>
  215 + </view>
  216 + </view>
  217 + </view>
  218 +
  219 + <!-- 申请数量明细 -->
  220 + <view class="sub-table">
  221 + <view class="header">
  222 + <image class="opCollapse" src="/static/images/title.png" />
  223 + <text class="title">申请数量明细</text>
  224 + <view class="ops">
  225 + <image class="opAdd" @click="addApply" src="/static/images/plus.png" />
  226 + </view>
  227 + </view>
  228 + <view class="add-list">
  229 + <view v-if="!applyList.length" class="empty-tip">暂无明细,请添加</view>
  230 + <view v-for="(item, idx) in applyList" :key="'a-' + idx" class="block">
  231 + <uni-list>
  232 + <uni-list-item title="类别">
  233 + <template v-slot:footer>
  234 + <uni-easyinput v-model="item.category" :inputBorder="false" placeholder="请输入类别" />
  235 + </template>
  236 + </uni-list-item>
  237 + <uni-list-item title="数量">
  238 + <template v-slot:footer>
  239 + <uni-easyinput v-model="item.quantity" type="digit" :inputBorder="false" placeholder="请输入数量" />
  240 + </template>
  241 + </uni-list-item>
  242 + </uni-list>
  243 + <view class="block-ops">
  244 + <div class="del" @click="removeRow('apply', idx)">
  245 + <image src="/static/images/delete.png" class="icon" />删除
  246 + </div>
  247 + </view>
  248 + </view>
  249 + </view>
  250 + </view>
  251 +
  252 + <!-- 备注模块 -->
  253 + <view class="remark-section">
  254 + <view class="header">
  255 + <image class="opCollapse" src="/static/images/title.png" />
  256 + <text class="title">备注</text>
  257 + </view>
  258 + <view class="section-content">
  259 + <view class="remark-group">
  260 + <view class="remark-label"><text class="required">*</text><text>业务摘要</text></view>
  261 + <uni-easyinput v-model="form.businessSummary" type="textarea" :inputBorder="false" placeholder="请输入业务摘要" maxlength="2000" />
  262 + </view>
  263 + <view class="remark-group">
  264 + <view class="remark-label">特别说明</view>
  265 + <uni-easyinput v-model="form.specialNote" type="textarea" :inputBorder="false" placeholder="请输入特别说明" maxlength="2000" />
  266 + </view>
  267 + <view class="remark-group">
  268 + <view class="remark-label">单据备注</view>
  269 + <uni-easyinput v-model="form.remark" type="textarea" :inputBorder="false" placeholder="请输入单据备注" maxlength="2000" />
  270 + </view>
  271 + </view>
  272 + </view>
  273 +
  274 + <view class="footer">
  275 + <button class="btn submit" type="primary" @click="onSubmit">保存</button>
  276 + </view>
  277 + </scroll-view>
  278 + </view>
  279 +</template>
  280 +
  281 +<script>
  282 +import { weighTicketDetailApi, weighTicketUpdateApi } from '@/api/procure-manage/weighTicket.js'
  283 +
  284 +export default {
  285 + name: 'ModifyWeightTicket',
  286 + data() {
  287 + return {
  288 + id: '',
  289 + form: {
  290 + code: '',
  291 + type: '',
  292 + unit: '',
  293 + firstGrossWeightTime: '',
  294 + supplierName: '',
  295 + companyShortName: '',
  296 + materialName: '',
  297 + totalGrossWeight: '',
  298 + actualImpurityWeight: '',
  299 + netWeight: '',
  300 + netWeightUpper: '',
  301 + deductionTypes: '',
  302 + supplierStockMaterial: '',
  303 + logisticsStockMaterial: '',
  304 + plateNumber: '',
  305 + businessSummary: '',
  306 + specialNote: '',
  307 + remark: ''
  308 + },
  309 + planList: [],
  310 + weighList: [],
  311 + applyList: []
  312 + }
  313 + },
  314 + onLoad(query) {
  315 + this.id = (query && query.id) || ''
  316 + this.loadDetail()
  317 + },
  318 + methods: {
  319 + loadDetail() {
  320 + if (!this.id) {
  321 + uni.showToast({ title: '缺少单据ID', icon: 'none' })
  322 + return
  323 + }
  324 + uni.showLoading({ title: '加载中...', mask: true })
  325 + weighTicketDetailApi({ id: this.id })
  326 + .then(res => {
  327 + const data = res && res.data ? (res.data.data || res.data) : {}
  328 + this.form = Object.assign({}, this.form, data)
  329 + this.planList = this.pickList(data, ['planDetailList', 'planLineList', 'procurementPlanLineList'])
  330 + this.weighList = this.pickList(data, ['weighDetailList', 'weighLineList', 'grossWeightList'])
  331 + this.applyList = this.pickList(data, ['applyQuantityList', 'applyDetailList', 'applyLineList'])
  332 + })
  333 + .catch(() => {
  334 + uni.showToast({ title: '加载详情失败', icon: 'none' })
  335 + })
  336 + .finally(() => {
  337 + uni.hideLoading()
  338 + })
  339 + },
  340 + pickList(data, keys) {
  341 + if (!data) return []
  342 + for (const k of keys) {
  343 + if (Array.isArray(data[k])) return data[k].map(x => Object.assign({}, x))
  344 + }
  345 + return []
  346 + },
  347 + calcNetWeight() {
  348 + const g = Number(this.form.totalGrossWeight)
  349 + const i = Number(this.form.actualImpurityWeight || 0)
  350 + if (!isNaN(g) && g > 0) {
  351 + const net = g - (isNaN(i) ? 0 : i)
  352 + this.form.netWeight = String(Math.round(net * 10000) / 10000)
  353 + }
  354 + },
  355 + addPlan() {
  356 + this.planList.push({ productName: '', quantity: '', planCode: '' })
  357 + },
  358 + addWeigh() {
  359 + this.weighList.push({ productName: '', invoiceProductName: '', quantity: '', planCode: '' })
  360 + },
  361 + addApply() {
  362 + this.applyList.push({ category: '', quantity: '' })
  363 + },
  364 + removeRow(type, idx) {
  365 + if (type === 'plan') this.planList.splice(idx, 1)
  366 + else if (type === 'weigh') this.weighList.splice(idx, 1)
  367 + else if (type === 'apply') this.applyList.splice(idx, 1)
  368 + },
  369 + validate() {
  370 + const f = this.form
  371 + if (!f.type) return this.tip('请输入类型')
  372 + if (!f.unit) return this.tip('请输入计划编号')
  373 + if (!f.firstGrossWeightTime) return this.tip('请选择时间')
  374 + if (!f.supplierName) return this.tip('请输入供料单位')
  375 + if (!f.companyShortName) return this.tip('请输入收料单位')
  376 + if (!f.materialName) return this.tip('请输入物料名称')
  377 + if (!f.totalGrossWeight) return this.tip('请输入过磅总重')
  378 + if (!f.plateNumber) return this.tip('请输入车牌号')
  379 + if (!f.businessSummary) return this.tip('请输入业务摘要')
  380 + return true
  381 + },
  382 + tip(msg) {
  383 + uni.showToast({ title: msg, icon: 'none' })
  384 + return false
  385 + },
  386 + async onSubmit() {
  387 + if (!this.validate()) return
  388 + const confirmRes = await new Promise(resolve => {
  389 + uni.showModal({ title: '提示', content: '确定保存修改吗?', confirmText: '确定', cancelText: '取消', success: resolve })
  390 + })
  391 + if (!(confirmRes && confirmRes.confirm)) return
  392 + const clean = (obj) => {
  393 + const out = {}
  394 + Object.keys(obj || {}).forEach(k => {
  395 + const v = obj[k]
  396 + const isEmptyString = typeof v === 'string' && v.trim() === ''
  397 + const isUndef = v === undefined || v === null
  398 + if (!(isEmptyString || isUndef)) out[k] = v
  399 + })
  400 + return out
  401 + }
  402 + const payload = clean({
  403 + ...this.form,
  404 + id: this.id,
  405 + planDetailList: this.planList.map(it => clean(it)),
  406 + weighDetailList: this.weighList.map(it => clean(it)),
  407 + applyQuantityList: this.applyList.map(it => clean(it))
  408 + })
  409 + uni.showLoading({ title: '保存中...', mask: true })
  410 + weighTicketUpdateApi(payload)
  411 + .then(() => {
  412 + uni.hideLoading()
  413 + uni.showToast({ title: '保存成功', icon: 'none' })
  414 + try {
  415 + uni.setStorageSync('WEIGHT_TICKET_LIST_NEED_REFRESH', '1')
  416 + uni.setStorageSync('WEIGHT_TICKET_DETAIL_NEED_REFRESH', '1')
  417 + } catch (e) {}
  418 + setTimeout(() => { uni.navigateBack() }, 400)
  419 + })
  420 + .catch(e => {
  421 + uni.hideLoading()
  422 + uni.showToast({ title: (e && (e.msg || e.message)) || '保存失败', icon: 'none' })
  423 + })
  424 + }
  425 + }
  426 +}
  427 +</script>
  428 +
  429 +<style lang="scss" scoped>
  430 +.page {
  431 + display: flex;
  432 + flex-direction: column;
  433 + height: 100%;
  434 +}
  435 +
  436 +.scroll {
  437 + flex: 1;
  438 + padding: 12rpx 0 200rpx !important;
  439 +}
  440 +
  441 +.footer {
  442 + z-index: 2;
  443 + position: fixed;
  444 + left: 0;
  445 + right: 0;
  446 + bottom: 0;
  447 + padding: 32rpx;
  448 + padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
  449 + background: #fff;
  450 + box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
  451 +
  452 + .btn {
  453 + height: 80rpx;
  454 + line-height: 80rpx;
  455 + border-radius: 12rpx;
  456 + font-size: 32rpx;
  457 + }
  458 +
  459 + .submit {
  460 + background: $theme-primary;
  461 + color: #fff;
  462 + }
  463 +}
  464 +
  465 +::v-deep .uni-list {
  466 + .uni-easyinput {
  467 + display: flex;
  468 +
  469 + .uni-input-input {
  470 + color: rgba(0, 0, 0, 0.9);
  471 + }
  472 + }
  473 +
  474 + .uni-input-placeholder {
  475 + z-index: 1;
  476 + }
  477 +
  478 + .uni-input-input {
  479 + background-color: #ffffff;
  480 + }
  481 +
  482 + background: transparent;
  483 +
  484 + &-item {
  485 + &__extra-text {
  486 + font-size: 32rpx;
  487 + }
  488 +
  489 + &__content-title {
  490 + font-size: 32rpx;
  491 + color: rgba(0, 0, 0, 0.9);
  492 + }
  493 +
  494 + &__container {
  495 + padding: 32rpx;
  496 +
  497 + .uni-easyinput {
  498 + &__placeholder-class {
  499 + font-size: 32rpx;
  500 + color: rgba(0, 0, 0, 0.4);
  501 + }
  502 +
  503 + &__content {
  504 + border: none;
  505 + background-color: #ffffff !important;
  506 +
  507 + &-input {
  508 + padding-left: 0 !important;
  509 + height: 48rpx;
  510 + line-height: 48rpx;
  511 + font-size: 32rpx;
  512 + }
  513 +
  514 + .content-clear-icon {
  515 + font-size: 44rpx !important;
  516 + }
  517 + }
  518 + }
  519 +
  520 + .item-title,
  521 + .uni-list-item__content {
  522 + flex: none;
  523 + min-height: 48rpx;
  524 + line-height: 48rpx;
  525 + font-size: 32rpx;
  526 + position: relative;
  527 + width: 240rpx;
  528 + margin-right: 32rpx;
  529 + color: rgba(0, 0, 0, 0.9);
  530 +
  531 + .required {
  532 + color: red;
  533 + position: absolute;
  534 + top: 50%;
  535 + transform: translateY(-50%);
  536 + left: -16rpx;
  537 + }
  538 + }
  539 + }
  540 +
  541 + &.select-item {
  542 + &.is-empty {
  543 + .uni-list-item__extra-text {
  544 + color: rgba(0, 0, 0, 0.4) !important;
  545 + }
  546 + }
  547 +
  548 + &.is-filled {
  549 + .uni-list-item__extra-text {
  550 + color: rgba(0, 0, 0, 0.9) !important;
  551 + }
  552 + }
  553 +
  554 + .serial-number-row {
  555 + display: flex;
  556 + align-items: center;
  557 +
  558 + .generate-btn {
  559 + margin-left: 24rpx;
  560 + height: 48rpx;
  561 + line-height: 48rpx;
  562 + padding: 0 24rpx;
  563 + font-size: 24rpx;
  564 + border-radius: 8rpx;
  565 + background: $theme-primary;
  566 + color: #fff;
  567 + }
  568 + }
  569 + }
  570 + }
  571 +}
  572 +
  573 +.readonly-text {
  574 + color: rgba(0, 0, 0, 0.9);
  575 + font-size: 32rpx;
  576 + line-height: 48rpx;
  577 + text-align: right;
  578 + white-space: pre-wrap;
  579 + word-break: break-all;
  580 +}
  581 +
  582 +.value-code {
  583 + width: 260rpx;
  584 + text-align: left;
  585 +}
  586 +
  587 +.sub-table,
  588 +.remark-section {
  589 + margin-top: 20rpx;
  590 + background: #fff;
  591 +}
  592 +
  593 +.header {
  594 + display: flex;
  595 + align-items: center;
  596 + padding: 24rpx 32rpx;
  597 + border-bottom: 1rpx solid #f0f0f0;
  598 +
  599 + .opCollapse {
  600 + width: 32rpx;
  601 + height: 28rpx;
  602 + margin-right: 16rpx;
  603 + margin-top: 8rpx;
  604 + }
  605 +
  606 + .title {
  607 + font-size: 32rpx;
  608 + color: rgba(0, 0, 0, 0.9);
  609 + font-weight: 600;
  610 + flex: 1;
  611 + }
  612 +
  613 + .ops {
  614 + display: flex;
  615 + align-items: center;
  616 +
  617 + .opAdd {
  618 + width: 40rpx;
  619 + height: 40rpx;
  620 + }
  621 + }
  622 +}
  623 +
  624 +.add-list {
  625 + padding: 0 0 16rpx;
  626 +
  627 + .empty-tip {
  628 + text-align: center;
  629 + padding: 60rpx 0;
  630 + color: rgba(0, 0, 0, 0.4);
  631 + font-size: 28rpx;
  632 + }
  633 +
  634 + .block {
  635 + border-bottom: 1rpx solid #f0f0f0;
  636 +
  637 + &:last-child {
  638 + border-bottom: none;
  639 + }
  640 +
  641 + .block-ops {
  642 + display: flex;
  643 + align-items: center;
  644 + justify-content: flex-end;
  645 + gap: 48rpx;
  646 + padding: 20rpx 32rpx;
  647 + background: #f8f8f8;
  648 +
  649 + .del,
  650 + .toggle {
  651 + display: flex;
  652 + align-items: center;
  653 + font-size: 28rpx;
  654 + color: rgba(0, 0, 0, 0.6);
  655 +
  656 + .icon {
  657 + width: 32rpx;
  658 + height: 32rpx;
  659 + margin-right: 8rpx;
  660 + }
  661 + }
  662 +
  663 + .del {
  664 + color: #d54941;
  665 + }
  666 + }
  667 + }
  668 +}
  669 +
  670 +.section-content {
  671 + padding: 32rpx;
  672 +}
  673 +
  674 +.remark-group {
  675 + margin-bottom: 32rpx;
  676 +
  677 + &:last-child {
  678 + margin-bottom: 0;
  679 + }
  680 +
  681 + .remark-label {
  682 + display: flex;
  683 + align-items: center;
  684 + font-size: 32rpx;
  685 + color: rgba(0, 0, 0, 0.9);
  686 + margin-bottom: 16rpx;
  687 + position: relative;
  688 + padding-left: 16rpx;
  689 +
  690 + .required {
  691 + color: red;
  692 + position: absolute;
  693 + left: 0;
  694 + }
  695 + }
  696 +}
  697 +</style>
... ...