Commit 9e3a17c53c3a5e7a9c1303ce495f70dd7b802677

Authored by gesilong
1 parent 776adc9d

commit:补单代码提交

... ... @@ -17,6 +17,14 @@ export function procurementPlanChangeQueryApi(params) {
17 17 })
18 18 }
19 19
  20 +export function procurementReplenishQueryApi(params) {
  21 + return request({
  22 + url: '/procurement/plan/replenish/query',
  23 + method: 'get',
  24 + params
  25 + })
  26 +}
  27 +
20 28 export function procurementPlanCanChangeOrReplenishmentApi(params) {
21 29 return request({
22 30 url: '/procurement/plan/queryCanChangeOrReplenishment',
... ... @@ -42,6 +50,14 @@ export function procurementPlanChangeFindByIdApi(params) {
42 50 })
43 51 }
44 52
  53 +export function procurementPlanReplenishFindByIdApi(params) {
  54 + return request({
  55 + url: '/procurement/plan/replenish',
  56 + method: 'get',
  57 + params
  58 + })
  59 +}
  60 +
45 61 export function procurementPlanChangeUpdateApi(data) {
46 62 return request({
47 63 url: '/procurement/plan/change/update',
... ... @@ -125,6 +141,14 @@ export function procurementPlanChangeSubmitApi(id) {
125 141 })
126 142 }
127 143
  144 +export function procurementPlanReplenishSubmitApi(id) {
  145 + return request({
  146 + url: '/procurement/plan/replenish/submit',
  147 + method: 'post',
  148 + params: { id: id }
  149 + })
  150 +}
  151 +
128 152 export function procurementPlanChangeCancelApi(id) {
129 153 return request({
130 154 url: '/procurement/plan/change/cancel',
... ... @@ -132,3 +156,12 @@ export function procurementPlanChangeCancelApi(id) {
132 156 params: { id: id }
133 157 })
134 158 }
  159 +
  160 +
  161 +export function procurementPlanReplenishCancelApi(id) {
  162 + return request({
  163 + url: '/procurement/plan/replenish/cancel',
  164 + method: 'post',
  165 + params: { id: id }
  166 + })
  167 +}
\ No newline at end of file
... ...
  1 +<template>
  2 + <view class="page">
  3 + <scroll-view class="scroll" scroll-y>
  4 + <view class="detail-page">
  5 + <view class="section">
  6 + <text class="row company">{{ safeText(form.code) }}</text>
  7 + <view class="row"><text class="label">公司简称</text><text class="value">{{ safeText(form.companyShortName || form.companyName) }}</text></view>
  8 + <view class="row"><text class="label">供应商名称</text><text class="value">{{ safeText(form.supplierName) }}</text></view>
  9 + <view class="row"><text class="label">采购处</text><text class="value">{{ safeText(form.purchaseDepartmentName || form.purchaseDepartment) }}</text></view>
  10 + <view class="row"><text class="label">区域</text><text class="value">{{ safeText(form.regionName || form.region) }}</text></view>
  11 + <view class="row"><text class="label">日期</text><text class="value">{{ formatDateOnly(form.date) }}</text></view>
  12 + <view class="row"><text class="label">报价时效</text><text class="value">{{ safeText(form.validityPeriod) }}</text></view>
  13 + <view class="row"><text class="label">报价人</text><text class="value">{{ safeText(form.quoterName) }}</text></view>
  14 + <view class="row"><text class="label">是否长单操作</text><text class="value">{{ boolText(form.longTermOperation) }}</text></view>
  15 + <view class="row"><text class="label">是否终端客户</text><text class="value">{{ boolText(form.terminalCustomer) }}</text></view>
  16 + <view class="row"><text class="label">是否未点价</text><text class="value">{{ boolText(form.priced) }}</text></view>
  17 + <view v-if="form.priced === true" class="row"><text class="label">点价截止日期</text><text class="value">{{ formatDateOnly(form.pricingDeadline) }}</text></view>
  18 + <view v-if="form.priced === true" class="row"><text class="label">是否暂定价</text><text class="value">{{ boolText(form.temporaryPrice) }}</text></view>
  19 + <view class="row"><text class="label">其他费用凭票到厂另行结算</text><text class="value">{{ boolText(form.otherExpenseSettlement) }}</text></view>
  20 + <view class="row"><text class="label">交提货方式</text><text class="value">{{ getDeliveryMethodLabel() }}</text></view>
  21 + <view class="row"><text class="label">是否通货买断</text><text class="value">{{ boolText(form.commodityBuyout) }}</text></view>
  22 + <view class="row"><text class="label">是否质量买断</text><text class="value">{{ boolText(form.qualityBuyout) }}</text></view>
  23 + <view class="row"><text class="label">是否数量买断</text><text class="value">{{ boolText(form.quantityBuyout) }}</text></view>
  24 + <view class="row"><text class="label">是否送货上门</text><text class="value">{{ boolText(form.doorDelivery) }}</text></view>
  25 + <view class="row"><text class="label">另付运费</text><text class="value">{{ formatNumber(form.shippingCost) }}</text></view>
  26 + <view class="row"><text class="label">装车费</text><text class="value">{{ formatNumber(form.loadingFee) }}</text></view>
  27 + <view class="row"><text class="label">开票品名</text><text class="value">{{ safeText(form.invoiceProductName) }}</text></view>
  28 + <view class="row"><text class="label">交货日期</text><text class="value">{{ formatDateOnly(form.deliveryDate) }}</text></view>
  29 + <view class="row"><text class="label">结算方式</text><text class="value">{{ safeText(form.settlementMethod) }}</text></view>
  30 + <view class="row"><text class="label">结算比例(%)</text><text class="value">{{ formatNumber(form.settlementRatio) }}</text></view>
  31 + <view class="row"><text class="label">价格表编号</text><text class="value">{{ priceTableDisplay }}</text></view>
  32 + <view class="row"><text class="label">协调事由</text><text class="value">{{ safeText(form.coordinationReason) }}</text></view>
  33 + <view class="row"><text class="label">票类状况</text><text class="value">{{ safeText(form.invoiceTypeStatus) }}</text></view>
  34 + <view class="row"><text class="label">数量合计</text><text class="value">{{ formatNumber(form.totalQuantity) }}</text></view>
  35 + <view class="row" v-if="attachmentList.length">
  36 + <text class="label">附件</text>
  37 + <view class="attach-list">
  38 + <view v-for="(at, idx) in attachmentList" :key="idx" class="attach-item">
  39 + <text class="attach-name">{{ at.name }}</text>
  40 + <text class="attach-view" @click.stop="onPreviewAttachment(at)">查看</text>
  41 + </view>
  42 + </view>
  43 + </view>
  44 + </view>
  45 +
  46 + <view class="title-header">
  47 + <image class="title-header_icon" src="/static/images/title.png" />
  48 + <span>明细信息</span>
  49 + </view>
  50 + <view v-if="lineListWithName.length" class="section">
  51 + <view v-for="(line, idx) in lineListWithName" :key="line.itemId || idx" class="line-block">
  52 + <view class="line-title">明细{{ idx + 1 }}</view>
  53 + <view class="row"><text class="label">品种</text><text class="value">{{ safeText(line.productName) }}</text></view>
  54 + <view class="row"><text class="label">料型</text><text class="value">{{ safeText(line.materialType) }}</text></view>
  55 + <view class="row"><text class="label">数量(吨)</text><text class="value">{{ formatNumber(line.quantity) }}</text></view>
  56 + <view class="row"><text class="label">实际采购价</text><text class="value">{{ formatNumber(line.actualPurchasePrice) }}</text></view>
  57 + <view class="row"><text class="label">含运到厂价</text><text class="value">{{ formatNumber(line.includingShippingPrice) }}</text></view>
  58 + <view class="row"><text class="label">价格表价格</text><text class="value">{{ formatNumber(line.priceListPrices) }}</text></view>
  59 + <view class="row"><text class="label">协调幅度</text><text class="value">{{ formatNumber(line.coordinationRange) }}</text></view>
  60 + <view class="row"><text class="label">买断料预计损耗</text><text class="value">{{ formatNumber(line.estimatedLoss) }}</text></view>
  61 + <view class="row"><text class="label">申请损耗(%)</text><text class="value">{{ formatNumber(line.applicationAttrition) }}</text></view>
  62 + <view class="row"><text class="label">选择分厂</text><text class="value">{{ safeText(line.workshopName) }}</text></view>
  63 + </view>
  64 + </view>
  65 + <view v-else class="section empty-tip">暂无明细</view>
  66 +
  67 + <view class="title-header">
  68 + <image class="title-header_icon" src="/static/images/title.png" />
  69 + <span>料质状况</span>
  70 + </view>
  71 + <view class="section">
  72 + <view class="row"><text class="label">是否启用料质状况</text><text class="value">{{ boolText(form.materialConditionEnabled) }}</text></view>
  73 + <template v-if="form.materialConditionEnabled">
  74 + <view v-for="mc in materialConditionConfigs" :key="mc.field" class="material-group">
  75 + <text class="material-label">{{ mc.label }}</text>
  76 + <view class="tag-list">
  77 + <view v-for="opt in getDictOptions(mc.dictCode)" :key="opt.code" class="tag-btn" :class="{ active: isTagSelected(mc.field, opt.code) }">{{ opt.name }}</view>
  78 + </view>
  79 + </view>
  80 + </template>
  81 + </view>
  82 +
  83 + <view class="title-header">
  84 + <image class="title-header_icon" src="/static/images/title.png" />
  85 + <span>备注</span>
  86 + </view>
  87 + <view class="section">
  88 + <text class="remark-text">{{ safeText(form.remark) }}</text>
  89 + </view>
  90 +
  91 + <view class="title-header">
  92 + <image class="title-header_icon" src="/static/images/title.png" />
  93 + <span>变更事由</span>
  94 + </view>
  95 + <view class="section">
  96 + <text class="remark-text">{{ safeText(form.changeReason) }}</text>
  97 + </view>
  98 + </view>
  99 + </scroll-view>
  100 + <detail-buttons :buttons="displayButtons" @click="handleButtonClick" />
  101 + </view>
  102 +</template>
  103 +
  104 +<script>
  105 +import { procurementPlanReplenishFindByIdApi, procurementPlanReplenishSubmitApi, procurementPlanReplenishCancelApi } from '@/api/procure-manage/procurementPlan.js'
  106 +import { breedRelationshipQueryApi, workshopQueryApi } from '@/api/devManage.js'
  107 +import { getDicByCodes } from '@/utils/dic.js'
  108 +import DetailButtons from '@/components/detail-buttons/index.vue'
  109 +export default {
  110 + name: 'SupplePlanDetail',
  111 + components: { DetailButtons },
  112 + data() {
  113 + return {
  114 + id: '',
  115 + form: {},
  116 + lineList: [],
  117 + attachmentList: [],
  118 + materialConditionConfigs: [
  119 + { field: 'materialConditionCopperRice', label: '铜米', dictCode: 'COPPER_RICE' },
  120 + { field: 'materialConditionBrightCopper', label: '光亮铜', dictCode: 'BRIGHT_COPPER' },
  121 + { field: 'materialConditionFirstClass', label: '一特', dictCode: 'FIRST_CLASS' },
  122 + { field: 'materialConditionSecondClass', label: '二特', dictCode: 'SECOND_CLASS' },
  123 + { field: 'materialConditionTinCoated', label: '镀锡紫', dictCode: 'TIN_COATED' },
  124 + { field: 'materialConditionScrap', label: '角料', dictCode: 'SCRAP' },
  125 + { field: 'materialConditionWhiteYellow', label: '镀白黄', dictCode: 'WHITE_YELLOW' },
  126 + { field: 'materialConditionPhosphorCopper', label: '磷铜', dictCode: 'PHOSPHOR_COPPER' }
  127 + ],
  128 + dictData: {},
  129 + productOptions: [],
  130 + workshopOptions: [],
  131 + buttons: [
  132 + { text: '编辑', visible: true, variant: 'outline', event: 'edit' },
  133 + { text: '发起变更审核', visible: true, variant: 'primary', event: 'initiate' },
  134 + { text: '取消', visible: true, variant: 'outline', event: 'cancel' },
  135 + { text: '审核', visible: true, variant: 'primary', event: 'approve' },
  136 + { text: '审核详情', visible: true, event: 'approveDetail' },
  137 + ],
  138 + }
  139 + },
  140 + computed: {
  141 + productMap() {
  142 + var list = Array.isArray(this.productOptions) ? this.productOptions : []
  143 + var m = {}
  144 + list.forEach(function (o) {
  145 + var key = String(o.productId || o.id || o.value || '')
  146 + if (key) m[key] = o
  147 + })
  148 + return m
  149 + },
  150 + workshopMap() {
  151 + var list = Array.isArray(this.workshopOptions) ? this.workshopOptions : []
  152 + var m = {}
  153 + list.forEach(function (o) {
  154 + var key = String(o.workshopId || o.id || o.value || '')
  155 + if (key) m[key] = o
  156 + })
  157 + return m
  158 + },
  159 + lineListWithName() {
  160 + var self = this
  161 + var list = Array.isArray(this.lineList) ? this.lineList : []
  162 + return list.map(function (row) {
  163 + var pid = String(row.productId || '')
  164 + var wid = String(row.workshopId || '')
  165 + var p = pid ? self.productMap[pid] : null
  166 + var w = wid ? self.workshopMap[wid] : null
  167 + return Object.assign({}, row, {
  168 + productName: row.productName || (p ? (p.productName || p.name || p.label || '') : ''),
  169 + workshopName: row.workshopName || (w ? (w.workshopName || w.name || w.label || '') : '')
  170 + })
  171 + })
  172 + },
  173 + priceTableDisplay() {
  174 + var d = this.form || {}
  175 + var code = d.priceTableCode != null ? d.priceTableCode : (d.priceId != null ? d.priceId : '')
  176 + var name = d.priceTableName || ''
  177 + if (name || code) {
  178 + return (name ? name + (code ? ' (' + code + ')' : '') : String(code))
  179 + }
  180 + return '-'
  181 + },
  182 + displayButtons() {
  183 + const status = this.form ? this.form.approvalStatus : '';
  184 + const isDraft = status === 'DRAFT';
  185 + const isAudit = status === 'AUDIT';
  186 + const isPass = status === 'PASS';
  187 + const isRefuse = status === 'REFUSE';
  188 + const canExamine = isAudit && this.form && this.form.showExamine === true;
  189 + return [
  190 + { ...this.buttons[0], visible: ((isDraft || isRefuse) && this.$auth.hasPermi('plan-manage:supple-plan:modify')) },
  191 + { ...this.buttons[1], visible: ((isDraft || isRefuse) && this.$auth.hasPermi('plan-manage:supple-plan:initiate')) },
  192 + { ...this.buttons[2], visible: (isRefuse && this.$auth.hasPermi('plan-manage:supple-plan:cancel')) },
  193 + { ...this.buttons[3], visible: (canExamine && this.$auth.hasPermi('plan-manage:supple-plan:approve')) },
  194 + { ...this.buttons[4], visible: ((isAudit || isPass) && this.form.showExamine && this.$auth.hasPermi('plan-manage:supple-plan:view')) },
  195 + ]
  196 + }
  197 + },
  198 + onLoad(query) {
  199 + this.id = (query && query.id) || ''
  200 + this.loadDictData()
  201 + this.loadRefData()
  202 + this.loadDetail()
  203 + },
  204 + methods: {
  205 + handleButtonClick(btn) {
  206 + if (!btn || btn.disabled) return
  207 + const e = btn.event || ''
  208 + if (e === 'edit') return this.onEdit()
  209 + if (e === 'initiate') return this.onInitiate()
  210 + if (e === 'approve') return this.onApprove()
  211 + if (e === 'approveDetail') return this.onApproveDetail()
  212 + if (e === 'cancel') return this.onCancel()
  213 + },
  214 + refreshListFlags() {
  215 + try {
  216 + uni.setStorageSync('SUPPLE_PLAN_LIST_NEED_REFRESH', '1')
  217 + } catch (e) {}
  218 + },
  219 + runWithConfirm(opts) {
  220 + var self = this
  221 + var title = opts.title || '提示'
  222 + var content = opts.content || ''
  223 + var run = opts.run
  224 + var loading = opts.loading || '处理中'
  225 + var successText = opts.successText || '操作成功'
  226 + var failText = opts.failText || '操作失败'
  227 + if (!this.id) {
  228 + uni.showToast({ title: '缺少单据id', icon: 'none' })
  229 + return
  230 + }
  231 + var apiFn = function () {
  232 + uni.showLoading({ title: loading, mask: true })
  233 + Promise.resolve(run(self.id)).then(function () {
  234 + uni.hideLoading()
  235 + uni.showToast({ title: successText, icon: 'none' })
  236 + self.refreshListFlags()
  237 + self.loadDetail()
  238 + }).catch(function (e) {
  239 + uni.hideLoading()
  240 + uni.showToast({ title: (e && (e.msg || e.message)) ? (e.msg || e.message) : failText, icon: 'none' })
  241 + })
  242 + }
  243 + if (opts.skipConfirm) {
  244 + apiFn()
  245 + return
  246 + }
  247 + uni.showModal({
  248 + title: title,
  249 + content: content,
  250 + confirmText: '确定',
  251 + cancelText: '取消',
  252 + success: function (res) {
  253 + if (!res || !res.confirm) return
  254 + apiFn()
  255 + }
  256 + })
  257 + },
  258 + onInitiate() {
  259 + this.runWithConfirm({
  260 + title: '发起补货审核',
  261 + content: '确认发起补货审核吗',
  262 + loading: '提交中',
  263 + successText: '发起成功',
  264 + failText: '发起补货审核失败',
  265 + run: function (id) { return procurementPlanReplenishSubmitApi(id) }
  266 + })
  267 + },
  268 + onEdit() {
  269 + if (!this.id) {
  270 + uni.showToast({ title: '缺少单据ID', icon: 'none' })
  271 + return
  272 + }
  273 + uni.navigateTo({ url: '/pages/supple-plan/modify?id=' + this.id })
  274 + },
  275 + async loadDictData() {
  276 + var codes = [].concat(
  277 + this.materialConditionConfigs.map(function (mc) { return mc.dictCode }),
  278 + ['DELIVERY_METHOD']
  279 + )
  280 + try {
  281 + var results = await getDicByCodes(codes)
  282 + var d = results || {}
  283 + this.dictData = d
  284 + this.deliveryOptions = (d.DELIVERY_METHOD && d.DELIVERY_METHOD.data) || []
  285 + } catch (e) {
  286 + this.dictData = {}
  287 + this.deliveryOptions = []
  288 + }
  289 + },
  290 + async loadRefData() {
  291 + var self = this
  292 + try {
  293 + var results = await Promise.all([
  294 + this.pCall(breedRelationshipQueryApi, { pageIndex: 1, pageSize: 1000 }),
  295 + this.pCall(workshopQueryApi, { pageIndex: 1, pageSize: 1000 })
  296 + ])
  297 + var r1 = (results[0] && results[0].data) ? results[0].data : {}
  298 + var r2 = (results[1] && results[1].data) ? results[1].data : {}
  299 + self.productOptions = (r1.datas && Array.isArray(r1.datas)) ? r1.datas : ((r1.list && Array.isArray(r1.list)) ? r1.list : ((r1.records && Array.isArray(r1.records)) ? r1.records : []))
  300 + self.workshopOptions = (r2.datas && Array.isArray(r2.datas)) ? r2.datas : ((r2.list && Array.isArray(r2.list)) ? r2.list : ((r2.records && Array.isArray(r2.records)) ? r2.records : []))
  301 + } catch (e) {
  302 + self.productOptions = []
  303 + self.workshopOptions = []
  304 + }
  305 + },
  306 + pCall(fn, params) {
  307 + try {
  308 + return Promise.resolve(fn(params))
  309 + } catch (e) {
  310 + return Promise.reject(e)
  311 + }
  312 + },
  313 + async loadDetail() {
  314 + if (!this.id) return
  315 + try {
  316 + var res = await procurementPlanReplenishFindByIdApi({ id: this.id })
  317 + var d = (res && res.data) ? res.data : {}
  318 + var boolFields = ['longTermOperation', 'terminalCustomer', 'priced', 'temporaryPrice', 'otherExpenseSettlement', 'commodityBuyout', 'qualityBuyout', 'quantityBuyout', 'doorDelivery', 'materialConditionEnabled']
  319 + boolFields.forEach(function (f) {
  320 + var v = d[f]
  321 + if (typeof v === 'string') {
  322 + d[f] = v === 'true' || v === '1'
  323 + } else if (typeof v === 'number') {
  324 + d[f] = v === 1
  325 + } else {
  326 + d[f] = !!v
  327 + }
  328 + })
  329 + this.materialConditionConfigs.forEach(function (mc) {
  330 + var v = d[mc.field]
  331 + if (typeof v === 'string' && v) {
  332 + d[mc.field] = v.split(',').filter(Boolean)
  333 + } else if (!Array.isArray(v)) {
  334 + d[mc.field] = []
  335 + }
  336 + })
  337 + this.form = d
  338 + var lines = d.lines || d.procurementPlanLineList || d.lineList || []
  339 + this.lineList = Array.isArray(lines) ? lines : []
  340 + this.buildAttachmentList()
  341 + } catch (e) {
  342 + uni.showToast({ title: '加载详情失败', icon: 'none' })
  343 + }
  344 + },
  345 + buildAttachmentList() {
  346 + var d = this.form || {}
  347 + var ids = d.attachmentFileIds
  348 + var names = d.attachmentFileNames
  349 + var idArr = (typeof ids === 'string' && ids) ? ids.split(',').filter(Boolean) : (Array.isArray(ids) ? ids : [])
  350 + var nameArr = (typeof names === 'string' && names) ? names.split(',').filter(Boolean) : (Array.isArray(names) ? names : [])
  351 + var len = Math.max(idArr.length, nameArr.length)
  352 + var list = []
  353 + for (var i = 0; i < len; i++) {
  354 + list.push({ id: idArr[i] || '', name: nameArr[i] || ('附件' + (i + 1)) })
  355 + }
  356 + this.attachmentList = list
  357 + },
  358 + getDictOptions(dictCode) {
  359 + var data = this.dictData[dictCode]
  360 + return (data && data.data) ? data.data : []
  361 + },
  362 + isTagSelected(field, code) {
  363 + var selected = this.form ? this.form[field] : undefined
  364 + if (Array.isArray(selected)) return selected.indexOf(code) >= 0
  365 + if (typeof selected === 'string' && selected) {
  366 + return selected.split(',').indexOf(code) >= 0
  367 + }
  368 + return false
  369 + },
  370 + getDeliveryMethodLabel() {
  371 + var opts = this.deliveryOptions || []
  372 + var v = String(this.form.deliveryMode != null ? this.form.deliveryMode : '')
  373 + if (!v) return '-'
  374 + for (var i = 0; i < opts.length; i++) {
  375 + var o = opts[i]
  376 + var code = o.code != null ? String(o.code) : (o.value != null ? String(o.value) : '')
  377 + if (code === v) return o.name || o.label || '-'
  378 + }
  379 + return v
  380 + },
  381 + boolText(v) {
  382 + if (typeof v === 'boolean') return v ? '是' : '否'
  383 + if (v === 'true' || v === '1' || v === 1) return '是'
  384 + if (v === 'false' || v === '0' || v === 0) return '否'
  385 + return '-'
  386 + },
  387 + formatDateOnly(v) {
  388 + var s = v == null ? '' : String(v).trim()
  389 + if (!s) return '-'
  390 + if (s.length >= 10) return s.slice(0, 10)
  391 + return s
  392 + },
  393 + safeText(v) {
  394 + var s = v == null ? '' : String(v)
  395 + return s.trim() ? s : '-'
  396 + },
  397 + formatNumber(v) {
  398 + if (v == null || v === '') return '-'
  399 + var n = Number(v)
  400 + if (isNaN(n)) return String(v)
  401 + return n.toLocaleString('zh-CN', { maximumFractionDigits: 4 })
  402 + },
  403 + onCancel() {
  404 + this.runWithConfirm({
  405 + title: '取消',
  406 + content: '确认取消该补货单吗?',
  407 + loading: '提交中',
  408 + successText: '取消成功',
  409 + failText: '取消失败',
  410 + run: function (id) { return procurementPlanReplenishCancelApi(id) }
  411 + })
  412 + },
  413 + onApprove() {
  414 + const id = this.id || (this.form && this.form.id) || ''
  415 + if (!id) return
  416 + const CACHE_KEY = 'sourceBusinessId'
  417 + const TYPE = 'contractType'
  418 + uni.setStorageSync(TYPE, 'PLAN_CHANGE')
  419 + uni.setStorageSync(CACHE_KEY, id)
  420 + uni.navigateTo({ url: '/pages/flow/audit' })
  421 + },
  422 + onApproveDetail() {
  423 + const id = this.id || (this.form && this.form.id) || ''
  424 + if (!id) return
  425 + const CACHE_KEY = 'sourceBusinessId'
  426 + const TYPE = 'contractType'
  427 + uni.setStorageSync(TYPE, 'PLAN_CHANGE')
  428 + uni.setStorageSync(CACHE_KEY, id)
  429 + uni.navigateTo({ url: '/pages/flow/audit_detail' })
  430 + },
  431 + onPreviewAttachment(at) {
  432 + if (!at || !at.id) {
  433 + uni.showToast({ title: '无法查看', icon: 'none' })
  434 + return
  435 + }
  436 + uni.showToast({ title: '查看附件 ' + at.name, icon: 'none' })
  437 + }
  438 + }
  439 +}
  440 +</script>
  441 +
  442 +<style lang="scss" scoped>
  443 +.page {
  444 + display: flex;
  445 + flex-direction: column;
  446 + height: 100%;
  447 +}
  448 +.scroll {
  449 + flex: 1;
  450 + padding: 8rpx 0 144rpx;
  451 +}
  452 +.detail-page {
  453 + background: #f3f3f3;
  454 +}
  455 +.title-header {
  456 + display: flex;
  457 + align-items: center;
  458 + padding: 24rpx 32rpx 12rpx;
  459 + background-color: #ffffff;
  460 + .title-header_icon {
  461 + width: 36rpx;
  462 + height: 36rpx;
  463 + margin-right: 12rpx;
  464 + }
  465 + span {
  466 + font-size: 34rpx;
  467 + font-weight: 600;
  468 + color: rgba(0, 0, 0, 0.9);
  469 + }
  470 +}
  471 +.section {
  472 + padding: 32rpx;
  473 + background: #fff;
  474 + margin-bottom: 20rpx;
  475 +}
  476 +.row {
  477 + display: flex;
  478 + margin-bottom: 28rpx;
  479 + &:last-child { margin-bottom: 0; }
  480 + &.company {
  481 + font-size: 36rpx;
  482 + font-weight: 600;
  483 + color: rgba(0, 0, 0, 0.9);
  484 + padding-top: 8rpx;
  485 + line-height: 50rpx;
  486 + }
  487 + .label {
  488 + max-width: 420rpx;
  489 + margin-right: 20rpx;
  490 + line-height: 32rpx;
  491 + font-size: 28rpx;
  492 + color: rgba(0, 0, 0, 0.6);
  493 + }
  494 + .value {
  495 + flex: 1;
  496 + line-height: 32rpx;
  497 + font-size: 28rpx;
  498 + color: rgba(0, 0, 0, 0.9);
  499 + text-align: right;
  500 + word-break: break-all;
  501 + }
  502 +}
  503 +.line-block {
  504 + padding-bottom: 24rpx;
  505 + margin-bottom: 24rpx;
  506 + border-bottom: 1rpx solid #f0f0f0;
  507 + &:last-child {
  508 + padding-bottom: 0;
  509 + margin-bottom: 0;
  510 + border-bottom: none;
  511 + }
  512 +}
  513 +.line-title {
  514 + font-size: 30rpx;
  515 + font-weight: 600;
  516 + color: rgba(0, 0, 0, 0.9);
  517 + margin-bottom: 20rpx;
  518 +}
  519 +.attach-list {
  520 + flex: 1;
  521 + display: flex;
  522 + flex-direction: column;
  523 + align-items: flex-end;
  524 + gap: 8rpx;
  525 +}
  526 +.attach-item {
  527 + display: flex;
  528 + align-items: center;
  529 + gap: 16rpx;
  530 + .attach-name {
  531 + font-size: 26rpx;
  532 + color: rgba(0, 0, 0, 0.9);
  533 + }
  534 + .attach-view {
  535 + font-size: 26rpx;
  536 + color: $theme-primary;
  537 + }
  538 +}
  539 +.material-group {
  540 + margin-top: 32rpx;
  541 + &:first-child { margin-top: 0; }
  542 +}
  543 +.material-label {
  544 + display: block;
  545 + font-size: 28rpx;
  546 + color: rgba(0, 0, 0, 0.6);
  547 + margin-bottom: 20rpx;
  548 +}
  549 +.tag-list {
  550 + display: flex;
  551 + flex-wrap: wrap;
  552 + gap: 16rpx;
  553 +}
  554 +.tag-btn {
  555 + padding: 12rpx 24rpx;
  556 + border: 1rpx solid #ddd;
  557 + border-radius: 8rpx;
  558 + font-size: 28rpx;
  559 + color: #999;
  560 + background: #f5f5f5;
  561 +}
  562 +.tag-btn.active {
  563 + background: $theme-primary;
  564 + border-color: $theme-primary;
  565 + color: #fff;
  566 +}
  567 +.remark-text {
  568 + font-size: 28rpx;
  569 + color: rgba(0, 0, 0, 0.9);
  570 + line-height: 1.6;
  571 + white-space: pre-wrap;
  572 +}
  573 +.empty-tip {
  574 + text-align: center;
  575 + font-size: 28rpx;
  576 + color: rgba(0, 0, 0, 0.4);
  577 + padding: 24rpx 0;
  578 +}
  579 +</style>
... ...
... ... @@ -15,17 +15,7 @@
15 15 />
16 16 <view class="tool-icons">
17 17 <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
18   - </view>
19   - </view>
20   -
21   - <view class="tabs">
22   - <view
23   - v-for="(t, i) in tabs"
24   - :key="i"
25   - :class="['tab', { active: frozen === t.value }]"
26   - @click="switchTab(t)"
27   - >
28   - {{ t.label }}
  18 + <image v-if="$auth.hasPermi('plan-manage:schedule-plan:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
29 19 </view>
30 20 </view>
31 21 </view>
... ... @@ -46,13 +36,11 @@
46 36 <view class="card" @click="onCardClick(item)">
47 37 <view class="card-header">
48 38 <text class="title omit2">{{ item.code || '-' }}</text>
49   - <text class="status" :style="getProcessStatusStyle(item.processStatus)">
50   - {{ getProcessStatusText(item.processStatus) }}
51   - </text>
  39 + <text :class="['status', `status_${item.approvalStatus}`]">{{ getAuditStatusText(item.approvalStatus) }}</text>
52 40 </view>
53 41 <view class="info-row">
54 42 <text>公司名称</text>
55   - <text>{{ item.companyShortName || item.companyName || '-' }}</text>
  43 + <text>{{item.companyShortName || '-' }}</text>
56 44 </view>
57 45 <view class="info-row">
58 46 <text>供应商名称</text>
... ... @@ -60,7 +48,11 @@
60 48 </view>
61 49 <view class="info-row">
62 50 <text>数量</text>
63   - <text>{{ formatQuantity(getTotalQuantity(item)) }}</text>
  51 + <text>{{ formatQuantity(item.totalQuantity || 0) }}</text>
  52 + </view>
  53 + <view class="info-row">
  54 + <text>采购处</text>
  55 + <text>{{ item.purchaseDepartmentName || '-' }}</text>
64 56 </view>
65 57 </view>
66 58 </template>
... ... @@ -98,21 +90,16 @@
98 90 import CardList from '@/components/card/index.vue'
99 91 import FilterModal from '@/components/filter/index.vue'
100 92 import { getDicByCodes, getDicName } from '@/utils/dic.js'
101   -import { procurementPlanQueryApi } from '@/api/procure-manage/procurementPlan.js'
  93 +import { procurementReplenishQueryApi } from '@/api/procure-manage/procurementPlan.js'
102 94
103 95 export default {
104   - name: 'SupplePlanList',
  96 + name: 'SupplyPlan',
105 97 components: { CardList, FilterModal },
106 98 data() {
107 99 return {
108 100 searchKeyword: '',
109 101 searchKeywordDebounced: '',
110 102 searchDebounceTimer: null,
111   - frozen: false,
112   - tabs: [
113   - { label: '未冻结', value: false },
114   - { label: '已冻结', value: true }
115   - ],
116 103 query: {
117 104 code: '',
118 105 supplierName: '',
... ... @@ -127,7 +114,7 @@ export default {
127 114 dateRange: []
128 115 },
129 116 dicOptions: {
130   - PROCESS_STATUS: []
  117 + AUDIT_STATUS: []
131 118 }
132 119 }
133 120 },
... ... @@ -135,8 +122,7 @@ export default {
135 122 extraCombined() {
136 123 const keyword = this.searchKeywordDebounced || ''
137 124 return {
138   - keyword: keyword || undefined,
139   - frozen: this.frozen
  125 + keyword: keyword || undefined
140 126 }
141 127 }
142 128 },
... ... @@ -154,9 +140,9 @@ export default {
154 140 },
155 141 onShow() {
156 142 let needRefresh = ''
157   - try { needRefresh = uni.getStorageSync('SUPPLE_PLAN_LIST_NEED_REFRESH') } catch (e) {}
  143 + try { needRefresh = uni.getStorageSync('SCHEDULE_PLAN_LIST_NEED_REFRESH') } catch (e) {}
158 144 if (!needRefresh) return
159   - try { uni.removeStorageSync('SUPPLE_PLAN_LIST_NEED_REFRESH') } catch (e) {}
  145 + try { uni.removeStorageSync('SCHEDULE_PLAN_LIST_NEED_REFRESH') } catch (e) {}
160 146 if (this.$refs && this.$refs.cardRef && this.$refs.cardRef.reload) {
161 147 this.$refs.cardRef.reload()
162 148 }
... ... @@ -173,87 +159,21 @@ export default {
173 159 }
174 160 },
175 161 methods: {
  162 + onAdd() {
  163 + uni.navigateTo({ url: '/pages/schedule-plan/add' })
  164 + },
176 165 async loadDicData() {
177 166 try {
178   - const results = await getDicByCodes(['PROCESS_STATUS'])
179   - this.dicOptions.PROCESS_STATUS = (results.PROCESS_STATUS && results.PROCESS_STATUS.data) || []
  167 + const results = await getDicByCodes(['AUDIT_STATUS'])
  168 + this.dicOptions.AUDIT_STATUS = (results.AUDIT_STATUS && results.AUDIT_STATUS.data) || []
180 169 } catch (e) {
181   - this.dicOptions.PROCESS_STATUS = []
  170 + this.dicOptions.AUDIT_STATUS = []
182 171 }
183 172 },
184   - getProcessStatusText(status) {
  173 + getAuditStatusText(status) {
185 174 const v = status == null ? '' : String(status)
186 175 if (!v) return '-'
187   - return getDicName('PROCESS_STATUS', v, this.dicOptions.PROCESS_STATUS) || v
188   - },
189   - getProcessStatusStyle(status) {
190   - var v = status == null ? '' : String(status)
191   - var name = v ? this.getProcessStatusText(v) : ''
192   - var sem = this.getSemanticColor(name)
193   - if (sem) return sem
194   - var list = Array.isArray(this.dicOptions.PROCESS_STATUS) ? this.dicOptions.PROCESS_STATUS : []
195   - var idx = -1
196   - for (var i = 0; i < list.length; i++) {
197   - if (list[i] && list[i].code === v) { idx = i; break }
198   - }
199   - if (idx < 0) {
200   - idx = this.hashIndex(v, 12)
201   - }
202   - var palette = this.getStatusPalette()
203   - var color = palette[idx % palette.length]
204   - return {
205   - color: color.color,
206   - backgroundColor: color.bgColor
207   - }
208   - },
209   - getSemanticColor(name) {
210   - var n = name == null ? '' : String(name)
211   - if (!n) return null
212   - var map = [
213   - { keys: ['草稿', '待提交', '新建', 'DRAFT'], color: '#606266', bgColor: '#EBEEF5' },
214   - { keys: ['审批中', '审核中', '审批', '审核', '待审核', '待审批', 'APPROVING'], color: '#1976D2', bgColor: '#E3F2FD' },
215   - { keys: ['通过', '已通过', '审批通过', '审核通过', '已完成', '完成', 'PASS', 'COMPLETED', 'APPROVED'], color: '#2BA471', bgColor: '#E3F9E9' },
216   - { keys: ['驳回', '拒绝', '不通过', '未通过', 'REJECT', 'REFUSE', 'REJECTED'], color: '#D54941', bgColor: '#FFF0ED' },
217   - { keys: ['取消', '已取消', '撤销', '已撤销', 'CANCEL', 'CANCELLED'], color: '#909399', bgColor: '#F4F4F5' },
218   - { keys: ['进行中', '执行中', '处理中'], color: '#E37318', bgColor: '#FFF3E0' },
219   - { keys: ['归档', '已归档'], color: '#5E35B1', bgColor: '#EDE7F6' },
220   - { keys: ['待发货', '已发货'], color: '#0097A7', bgColor: '#E0F7FA' }
221   - ]
222   - for (var i = 0; i < map.length; i++) {
223   - var it = map[i]
224   - for (var j = 0; j < it.keys.length; j++) {
225   - var k = String(it.keys[j])
226   - if (k && (n.indexOf(k) >= 0 || n.toLowerCase().indexOf(k.toLowerCase()) >= 0)) {
227   - return { color: it.color, backgroundColor: it.bgColor }
228   - }
229   - }
230   - }
231   - return null
232   - },
233   - getStatusPalette() {
234   - return [
235   - { color: '#1976D2', bgColor: '#E3F2FD' },
236   - { color: '#2BA471', bgColor: '#E3F9E9' },
237   - { color: '#D54941', bgColor: '#FFF0ED' },
238   - { color: '#E37318', bgColor: '#FFF3E0' },
239   - { color: '#7B1FA2', bgColor: '#F3E5F5' },
240   - { color: '#00838F', bgColor: '#E0F7FA' },
241   - { color: '#EF6C00', bgColor: '#FFF3E0' },
242   - { color: '#455A64', bgColor: '#ECEFF1' },
243   - { color: '#6A1B9A', bgColor: '#F3E5F5' },
244   - { color: '#C62828', bgColor: '#FFEBEE' },
245   - { color: '#2E7D32', bgColor: '#E8F5E9' },
246   - { color: '#1565C0', bgColor: '#E3F2FD' }
247   - ]
248   - },
249   - hashIndex(str, size) {
250   - var s = str == null ? '' : String(str)
251   - if (!s) return 0
252   - var h = 0
253   - for (var i = 0; i < s.length; i++) {
254   - h = (h * 31 + s.charCodeAt(i)) >>> 0
255   - }
256   - return h % size
  176 + return getDicName('AUDIT_STATUS', v, this.dicOptions.AUDIT_STATUS) || v
257 177 },
258 178 getTotalQuantity(item) {
259 179 const lines = item && item.procurementPlanLineList && Array.isArray(item.procurementPlanLineList)
... ... @@ -296,9 +216,6 @@ export default {
296 216 this.searchKeyword = val
297 217 this.searchKeywordDebounced = val
298 218 },
299   - switchTab(t) {
300   - this.frozen = t.value
301   - },
302 219 openFilter() {
303 220 this.filterForm = {
304 221 code: this.query.code || '',
... ... @@ -330,7 +247,6 @@ export default {
330 247 const params = {
331 248 pageIndex: pageIndex,
332 249 pageSize: pageSize,
333   - frozen: e.frozen != null ? e.frozen : false,
334 250 code: q.code || '',
335 251 supplierName: q.supplierName || '',
336 252 startDate: range && range.length === 2 ? range[0] : '',
... ... @@ -340,7 +256,7 @@ export default {
340 256 if (!params.code) params.code = keyword
341 257 if (!params.supplierName) params.supplierName = keyword
342 258 }
343   - return procurementPlanQueryApi(params).then(function (res) {
  259 + return procurementReplenishQueryApi(params).then(function (res) {
344 260 const _data = res && res.data ? res.data : {}
345 261 let records = _data.datas || _data.list || _data.records || []
346 262 const totalCount = _data.totalCount || _data.count || 0
... ... @@ -382,31 +298,11 @@ export default {
382 298 .tool-icon { width: 48rpx; height: 48rpx; display: block; margin-left: 32rpx; }
383 299 }
384 300 }
385   - .tabs {
386   - display: flex;
387   - align-items: center;
388   - justify-content: space-between;
389   - padding: 26rpx 34rpx;
390   - border-bottom: solid 1px #E7E7E7;
391   - .tab { width: 50%; text-align: center; color: rgba(0,0,0,0.9); line-height: 44rpx; position: relative; font-weight: 600; }
392   - .tab.active { color: $theme-primary; }
393   - .tab.active::after {
394   - content: '';
395   - position: absolute;
396   - left: 50%;
397   - transform: translateX(-50%);
398   - bottom: -13px;
399   - width: 32rpx;
400   - height: 6rpx;
401   - border-radius: 4rpx;
402   - background: $theme-primary;
403   - }
404   - }
405 301 }
406 302 ::v-deep .uni-searchbar__box { height: 80rpx !important; justify-content: start; .uni-searchbar__box-search-input { font-size: 32rpx !important; } }
407 303 .list-box {
408 304 flex: 1;
409   - padding-top: 236rpx;
  305 + padding-top: 140rpx;
410 306 .card { position: relative; }
411 307 .card-header {
412 308 margin-bottom: 28rpx;
... ... @@ -419,10 +315,28 @@ export default {
419 315 height: 48rpx;
420 316 line-height: 48rpx;
421 317 font-weight: 600;
  318 + color: #fff;
422 319 font-size: 24rpx;
423 320 padding: 0 14rpx;
424 321 border-radius: 6rpx;
425 322 box-sizing: content-box;
  323 +
  324 + &.status_AUDIT {
  325 + background: $theme-primary;
  326 + }
  327 +
  328 + &.status_PASS {
  329 + background: #2BA471;
  330 + }
  331 +
  332 + &.status_REFUSE {
  333 + background: #D54941;
  334 + }
  335 +
  336 + &.status_CANCEL {
  337 + background: #E7E7E7;
  338 + color: rgba(0, 0, 0, 0.9);
  339 + }
426 340 }
427 341 }
428 342 .info-row {
... ...