1. 新增仓库选择组件多选支持,适配批量库区操作 2. 售后单新增自动生成编号与当前日期填充 3. 盘点计划新增流程审批操作按钮,支持驳回与审批通过 4. 优化库区绑定页面,支持编辑删除已绑定库区 5. 替换人员选择为可搜索下拉框,支持多选参与人 6. 新增驳回审批弹窗,提供快捷驳回理由 7. 优化表单提交逻辑,适配多库区数据格式
147 lines
7.8 KiB
Vue
147 lines
7.8 KiB
Vue
<template>
|
||
<div v-if="!currentRow" class="empty-tip"><i class="el-icon-info"></i><span>{{ emptyText }}</span></div>
|
||
<div v-else v-loading="loading" class="detail-content">
|
||
<div class="doc-header">
|
||
<div class="doc-header-top">
|
||
<div class="doc-title-group">
|
||
<div class="doc-title">{{ currentRow.planCode }}</div>
|
||
<div class="doc-subtitle">{{ subtitle }}</div>
|
||
</div>
|
||
<div class="doc-header-right">
|
||
<el-button size="mini" type="text" icon="el-icon-refresh" @click="refresh">刷新</el-button>
|
||
<el-button v-if="currentRow.planStatus === 0" size="mini" type="text" icon="el-icon-edit" @click="$emit('edit-plan', currentRow)">编辑</el-button>
|
||
<el-button v-if="currentRow.planStatus === 0" size="mini" type="text" icon="el-icon-delete" @click="$emit('delete-plan', currentRow)">删除</el-button>
|
||
<el-button v-if="currentRow.planStatus === 4" size="mini" type="success" icon="el-icon-circle-check" @click="$emit('archive')">归档封存</el-button>
|
||
</div>
|
||
</div>
|
||
<div class="doc-status-row">
|
||
<span class="doc-status-label">Status:</span>
|
||
<el-tag v-if="currentRow.planStatus === 0" type="info" size="small">草稿</el-tag>
|
||
<el-tag v-else-if="currentRow.planStatus === 1" size="small">计划待审批</el-tag>
|
||
<el-tag v-else-if="currentRow.planStatus === 2" type="warning" size="small">盘库执行中</el-tag>
|
||
<el-tag v-else-if="currentRow.planStatus === 3" size="small">差异审批中</el-tag>
|
||
<el-tag v-else-if="currentRow.planStatus === 4" type="danger" size="small">差异处理中</el-tag>
|
||
<el-tag v-else-if="currentRow.planStatus === 5" type="success" size="small">已归档</el-tag>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="detail-meta">
|
||
<span><i class="el-icon-document"></i>{{ currentRow.planName }}</span>
|
||
<span v-if="currentRow.countDate"><i class="el-icon-date"></i>{{ formatTime(currentRow.countDate, '{y}-{m}-{d}') }}</span>
|
||
<span v-if="currentRow.countUserName"><i class="el-icon-user-solid"></i>{{ currentRow.countUserName }}</span>
|
||
<span v-if="currentRow.principalUserName"><i class="el-icon-s-custom"></i>{{ currentRow.principalUserName }}</span>
|
||
</div>
|
||
|
||
<CountFlowSection :planStatus="currentRow.planStatus" />
|
||
|
||
<el-divider />
|
||
|
||
<!-- 流程操作按钮 -->
|
||
<div v-if="currentRow.planStatus === 0" class="section-title">
|
||
<span>流程操作 <span class="en-sub">· Actions</span></span>
|
||
</div>
|
||
<div class="flow-actions" v-if="currentRow.planStatus === 0">
|
||
<el-button type="primary" size="small" icon="el-icon-s-promotion" @click="$emit('submit-approval')">提交审批</el-button>
|
||
</div>
|
||
|
||
<el-divider v-if="currentRow.planStatus === 0" />
|
||
|
||
<!-- 计划待审批 (1) 操作 -->
|
||
<div v-if="currentRow.planStatus === 1" class="section-title">
|
||
<span>流程操作 <span class="en-sub">· Actions</span></span>
|
||
</div>
|
||
<div class="flow-actions" v-if="currentRow.planStatus === 1">
|
||
<el-button type="danger" size="small" icon="el-icon-close" @click="$emit('reject')">驳回</el-button>
|
||
<el-button type="primary" size="small" icon="el-icon-check" @click="$emit('approve')">审批通过</el-button>
|
||
</div>
|
||
<el-divider v-if="currentRow.planStatus === 1" />
|
||
|
||
<!-- 差异审批中 (3) 操作 -->
|
||
<div v-if="currentRow.planStatus === 3" class="section-title">
|
||
<span>流程操作 <span class="en-sub">· Actions</span></span>
|
||
</div>
|
||
<div class="flow-actions" v-if="currentRow.planStatus === 3">
|
||
<el-button type="danger" size="small" icon="el-icon-close" @click="$emit('reject')">驳回</el-button>
|
||
<el-button type="primary" size="small" icon="el-icon-check" @click="$emit('diff-approve')">审批通过</el-button>
|
||
</div>
|
||
<el-divider v-if="currentRow.planStatus === 3" />
|
||
|
||
<div class="section-title">库区盘点明细 <span class="en-sub">· Warehouses</span>
|
||
<el-button v-if="currentRow.planStatus === 0" size="mini" type="primary" plain icon="el-icon-plus" style="margin-left:8px;" @click="$emit('bind-warehouse')">绑定库区</el-button>
|
||
</div>
|
||
|
||
<WarehouseDetailPanel ref="whPanel"
|
||
:planId="currentRow.planId"
|
||
:planStatus="currentRow.planStatus"
|
||
@archive="$emit('archive')"
|
||
@process-disc="$emit('process-disc', $event)"
|
||
@submit-disc-approval="$emit('submit-disc-approval')"
|
||
@edit-warehouse="$emit('edit-warehouse', $event)"
|
||
@delete-warehouse="$emit('delete-warehouse', $event)"
|
||
/>
|
||
|
||
<div class="section-gap" />
|
||
<div class="section-title">备注 <span class="en-sub">· Remarks</span></div>
|
||
<div class="remark-content">{{ currentRow.remark || '无' }}</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { getCountPlan } from "@/api/flow/countPlan";
|
||
import CountFlowSection from "./CountFlowSection.vue";
|
||
import WarehouseDetailPanel from "./WarehouseDetailPanel.vue";
|
||
import { parseTime } from '@/utils/klp';
|
||
|
||
export default {
|
||
name: 'PlanDetailPanel',
|
||
components: { CountFlowSection, WarehouseDetailPanel },
|
||
props: {
|
||
planId: { type: [Number, String], default: null },
|
||
emptyText: { type: String, default: '请在左侧列表中选择一条盘库计划' },
|
||
subtitle: { type: String, default: 'Inventory Count Plan' }
|
||
},
|
||
data() {
|
||
return { loading: false, currentRow: null };
|
||
},
|
||
watch: {
|
||
planId: {
|
||
immediate: true,
|
||
handler(val) {
|
||
if (!val) { this.currentRow = null; return; }
|
||
this.loadDetail(val);
|
||
}
|
||
}
|
||
},
|
||
methods: {
|
||
formatTime(val, fmt) { if (!val) return ''; return parseTime(val, fmt); },
|
||
loadDetail(planId) {
|
||
this.loading = true; var self = this;
|
||
getCountPlan(planId).then(function(r) { self.currentRow = r.data; self.$emit('loaded', r.data); }).finally(function() { self.loading = false; });
|
||
},
|
||
refresh() { if (this.currentRow) this.loadDetail(this.currentRow.planId); if (this.$refs.whPanel) this.$refs.whPanel.refreshAll(); }
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.empty-tip { display: flex; align-items: center; justify-content: center; height: 100%; color: #909399; font-size: 14px; gap: 8px; }
|
||
.detail-content { margin: 0 auto; background: #fff; padding: 28px 32px 36px; box-shadow: 0 1px 4px rgba(0,0,0,0.06), 0 2px 12px rgba(0,0,0,0.04); min-height: 100%; }
|
||
.doc-header { margin-bottom: 18px; padding-bottom: 14px; border-bottom: 2px solid #1a3c6e; }
|
||
.doc-header-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
|
||
.doc-title-group { flex: 1; min-width: 0; }
|
||
.doc-title { font-size: 24px; font-weight: 700; color: #1a1a1a; line-height: 1.3; letter-spacing: 0.5px; }
|
||
.doc-subtitle { font-size: 12px; color: #8c8c8c; font-style: italic; letter-spacing: 0.8px; margin-top: 2px; }
|
||
.doc-header-right { flex-shrink: 0; }
|
||
.doc-status-row { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
|
||
.doc-status-label { font-size: 11px; color: #8c8c8c; letter-spacing: 0.3px; }
|
||
.detail-meta { display: flex; flex-wrap: wrap; gap: 16px; font-size: 12px; color: #909399; margin-bottom: 16px; padding-bottom: 12px; border-bottom: 1px solid #e0dcd6; }
|
||
.detail-meta span { display: inline-flex; align-items: center; gap: 4px; }
|
||
.detail-meta i { font-size: 13px; }
|
||
.section-title { font-size: 15px; font-weight: 700; color: #1a1a1a; margin: 22px 0 12px; padding: 0 0 10px; border-bottom: 1px solid #d4d0c8; display: flex; align-items: center; gap: 10px; letter-spacing: 0.3px; }
|
||
.section-title:first-child { margin-top: 0; }
|
||
.section-title .en-sub { font-size: 11px; font-weight: 400; color: #8c8c8c; letter-spacing: 0.5px; font-style: italic; }
|
||
.flow-actions { display: flex; gap: 10px; flex-wrap: wrap; }
|
||
.remark-content { padding: 12px 16px; background: #faf8f5; border: 1px solid #e8e4de; border-radius: 2px; font-size: 13px; line-height: 1.8; color: #1a1a1a; }
|
||
.section-gap { height: 16px; }
|
||
</style>
|