|
|
@@ -0,0 +1,677 @@
|
|
|
+<template>
|
|
|
+ <div class="item-publish-approval" v-loading="loading">
|
|
|
+ <headerTitle title="物品发布审批"></headerTitle>
|
|
|
+
|
|
|
+ <div class="section">
|
|
|
+ <div class="section-title">基本信息</div>
|
|
|
+ <el-descriptions :column="3" border>
|
|
|
+ <el-descriptions-item
|
|
|
+ v-for="item in basicFields"
|
|
|
+ :key="item.prop"
|
|
|
+ :label="item.label"
|
|
|
+ >
|
|
|
+ {{ formatValue(form, item) }}
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="section" v-if="dynamicFields.length">
|
|
|
+ <div class="section-title">扩展字段</div>
|
|
|
+ <el-descriptions :column="3" border>
|
|
|
+ <el-descriptions-item
|
|
|
+ v-for="item in dynamicFields"
|
|
|
+ :key="item.prop"
|
|
|
+ :label="item.label"
|
|
|
+ >
|
|
|
+ {{ formatValue(form.extField, item) }}
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="section" v-if="industryAttribute == 1">
|
|
|
+ <div class="section-title">药品信息</div>
|
|
|
+ <el-descriptions :column="3" border>
|
|
|
+ <el-descriptions-item
|
|
|
+ v-for="item in medicineFields"
|
|
|
+ :key="item.prop"
|
|
|
+ :label="item.label"
|
|
|
+ >
|
|
|
+ {{ formatValue(form, item) }}
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="section">
|
|
|
+ <div class="section-title">标签</div>
|
|
|
+ <el-descriptions :column="3" border>
|
|
|
+ <el-descriptions-item label="是否消耗品">
|
|
|
+ {{ yesNo(form.extTagField && form.extTagField.isConsumables) }}
|
|
|
+ </el-descriptions-item>
|
|
|
+ <el-descriptions-item label="需要序列号" v-if="clientEnvironmentId == 5">
|
|
|
+ {{ yesNo(form.extTagField && form.extTagField.needProductSequence) }}
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="section" v-if="imageList.length">
|
|
|
+ <div class="section-title">产品图片</div>
|
|
|
+ <el-image
|
|
|
+ v-for="(item, index) in imageList"
|
|
|
+ :key="item.id || item.url || index"
|
|
|
+ class="product-image"
|
|
|
+ :src="getFileUrl(item)"
|
|
|
+ :preview-src-list="previewList"
|
|
|
+ fit="cover"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="section">
|
|
|
+ <div class="section-title">仓储配置</div>
|
|
|
+ <el-descriptions :column="3" border>
|
|
|
+ <el-descriptions-item
|
|
|
+ v-for="item in warehouseFields"
|
|
|
+ :key="item.prop"
|
|
|
+ :label="item.label"
|
|
|
+ >
|
|
|
+ {{ formatValue(categoryWms, item) }}
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="section" v-if="packageDispositionVOList.length">
|
|
|
+ <div class="section-title">包装组</div>
|
|
|
+ <el-table :data="packageDispositionVOList" border size="small">
|
|
|
+ <el-table-column prop="code" label="编码" min-width="120" />
|
|
|
+ <el-table-column prop="name" label="名称" min-width="120" />
|
|
|
+ <el-table-column label="是否启用" min-width="90">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ {{ yesNo(scope.row.status) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="最小包装单元" min-width="150">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ {{ formatPackageUnit(scope.row, 'min') }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="内包装单元" min-width="150">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ {{ formatPackageUnit(scope.row, 'in') }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="外包装单元" min-width="150">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ {{ formatPackageUnit(scope.row, 'out') }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="section">
|
|
|
+ <div class="section-title">销售配置</div>
|
|
|
+ <el-descriptions :column="3" border>
|
|
|
+ <el-descriptions-item label="计价方式">
|
|
|
+ {{ pricingWayText(categorySales.pricingWay) }}
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="section">
|
|
|
+ <div class="section-title">采购信息</div>
|
|
|
+ <el-descriptions :column="3" border>
|
|
|
+ <el-descriptions-item
|
|
|
+ v-for="item in purchaseFields"
|
|
|
+ :key="item.prop"
|
|
|
+ :label="item.label"
|
|
|
+ >
|
|
|
+ {{ formatValue(categoryPurchase, item) }}
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="section">
|
|
|
+ <div class="section-title">生产信息</div>
|
|
|
+ <el-descriptions :column="3" border>
|
|
|
+ <el-descriptions-item
|
|
|
+ v-for="item in productionFields"
|
|
|
+ :key="item.prop"
|
|
|
+ :label="item.label"
|
|
|
+ >
|
|
|
+ {{ formatValue(categoryMes, item) }}
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="section">
|
|
|
+ <div class="section-title">计划</div>
|
|
|
+ <el-descriptions :column="3" border>
|
|
|
+ <el-descriptions-item
|
|
|
+ v-for="item in planFields"
|
|
|
+ :key="item.prop"
|
|
|
+ :label="item.label"
|
|
|
+ >
|
|
|
+ {{ formatValue(categoryAps, item) }}
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="section">
|
|
|
+ <div class="section-title">备注信息</div>
|
|
|
+ <el-descriptions :column="1" border>
|
|
|
+ <el-descriptions-item label="附件">
|
|
|
+ <fileMain v-model="remarkform.remarkAttach" type="view"></fileMain>
|
|
|
+ </el-descriptions-item>
|
|
|
+ <el-descriptions-item label="备注">
|
|
|
+ {{ remarkform.remark || '-' }}
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <relatedInfo
|
|
|
+ :category-id="businessId"
|
|
|
+ :category-level-id="form.categoryLevelId"
|
|
|
+ :category-level-group-id="form.categoryLevelGroupId"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ import fileMain from '@/components/addDoc/index.vue';
|
|
|
+ import relatedInfo from './relatedInfo.vue';
|
|
|
+ import {
|
|
|
+ fieldModel,
|
|
|
+ getCategoryDetails
|
|
|
+ } from '@/api/bpm/components/itemPublishApproval';
|
|
|
+ import { getByCode } from '@/api/system/dictionary-data';
|
|
|
+ import { parameterGetByCode } from '@/api/main';
|
|
|
+ import dictEnum from '@/enum/dict';
|
|
|
+
|
|
|
+ const DICT_CODE_MAP = {
|
|
|
+ 存货类型: 'inventory_type',
|
|
|
+ 包装单位: 'packing_unit',
|
|
|
+ 周期单位: 'periodic_unit',
|
|
|
+ 包装强度: 'packagingStrength',
|
|
|
+ 包装密度: 'packagingDensity',
|
|
|
+ 贮藏: 'layBy',
|
|
|
+ 执行标准: 'enforceStandards'
|
|
|
+ };
|
|
|
+
|
|
|
+ export default {
|
|
|
+ name: 'ItemPublishApprovalDetail',
|
|
|
+ components: { fileMain, relatedInfo },
|
|
|
+ props: {
|
|
|
+ taskDefinitionKey: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ taskId: {
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ businessId: {
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ id: {
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ businessCode: {
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ processDefinitionId: {
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ businessType: {
|
|
|
+ default: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ loading: false,
|
|
|
+ industryAttribute: '',
|
|
|
+ form: {
|
|
|
+ extField: {},
|
|
|
+ extTagField: {}
|
|
|
+ },
|
|
|
+ categoryAps: {},
|
|
|
+ categoryMes: {},
|
|
|
+ categoryPurchase: {},
|
|
|
+ categorySales: {},
|
|
|
+ categoryWms: {},
|
|
|
+ packageDispositionVOList: [],
|
|
|
+ remarkform: {
|
|
|
+ remarkAttach: [],
|
|
|
+ remark: ''
|
|
|
+ },
|
|
|
+ dictMaps: {},
|
|
|
+ dynamicFields: [],
|
|
|
+ basicFields: [
|
|
|
+ { label: '分类', prop: 'categoryLevelName' },
|
|
|
+ { label: '编码', prop: 'code' },
|
|
|
+ { label: '名称', prop: 'name' },
|
|
|
+ { label: '存货类型', prop: 'attributeType', dictName: '存货类型' },
|
|
|
+ { label: '属性类型', prop: 'componentAttribute', formatter: this.componentAttributeText },
|
|
|
+ { label: '生产类型', prop: 'produceType', formatter: this.produceTypeText },
|
|
|
+ { label: '加工类型', prop: 'isConsumable', formatter: this.processingTypeText },
|
|
|
+ { label: '牌号', prop: 'brandNum' },
|
|
|
+ { label: '型号', prop: 'modelType' },
|
|
|
+ { label: '规格', prop: 'specification' },
|
|
|
+ { label: '计量类型', prop: 'measureType', formatter: this.measureTypeText },
|
|
|
+ { label: '计量单位', prop: 'measuringUnit', dictName: '计量单位' },
|
|
|
+ { label: '重量单位', prop: 'weightUnit', dictName: '重量单位' },
|
|
|
+ { label: '包装单位', prop: 'packingUnit', dictName: '包装单位' },
|
|
|
+ { label: '面积', prop: 'area' },
|
|
|
+ { label: '面积单位', prop: 'areaUnit', dictName: '计量单位' },
|
|
|
+ { label: '图号/件号', prop: 'imgCode' },
|
|
|
+ { label: '毛重', prop: 'roughWeight' },
|
|
|
+ { label: '净重', prop: 'netWeight' },
|
|
|
+ { label: '体积', prop: 'volume', unitProp: 'volumeUnit', unitDictName: '体积单位' },
|
|
|
+ { label: '级别', prop: 'level' },
|
|
|
+ { label: '机型', prop: 'modelKey', dictName: '物品机型' },
|
|
|
+ { label: '颜色', prop: 'colorKey', dictName: '物品颜色' },
|
|
|
+ { label: '状态', prop: 'isEnabled', formatter: this.enabledText },
|
|
|
+ { label: '物联产品Key', prop: 'iotProductKey' }
|
|
|
+ ],
|
|
|
+ medicineFields: [
|
|
|
+ { label: '性味与归经', prop: 'propertiesChannelTropism' },
|
|
|
+ { label: '功能与主治', prop: 'actionsAndUses' },
|
|
|
+ { label: '用法与用量', prop: 'usageAndDosage' }
|
|
|
+ ],
|
|
|
+ warehouseFields: [
|
|
|
+ { label: '启用库存预警', prop: 'isWarn', formatter: this.yesNo },
|
|
|
+ { label: '盘点模式', prop: 'inventoryMode', formatter: this.inventoryModeText },
|
|
|
+ { label: '允许拆包', prop: 'isUnpack', formatter: this.yesNo },
|
|
|
+ {
|
|
|
+ label: '安全库存',
|
|
|
+ prop: 'secureInventory',
|
|
|
+ unitValue: () => this.form.measuringUnit,
|
|
|
+ unitDictName: '计量单位'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '最小库存',
|
|
|
+ prop: 'minInventory',
|
|
|
+ unitValue: () => this.form.measuringUnit,
|
|
|
+ unitDictName: '计量单位'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '最大库存',
|
|
|
+ prop: 'maxInventory',
|
|
|
+ unitValue: () => this.form.measuringUnit,
|
|
|
+ unitDictName: '计量单位'
|
|
|
+ },
|
|
|
+ { label: '质保预警参考', prop: 'warrantyWarnRefer', dictName: '质保预警参考' },
|
|
|
+ {
|
|
|
+ label: '保质期',
|
|
|
+ prop: 'warrantyPeriod',
|
|
|
+ unitProp: 'warrantyPeriodUnit',
|
|
|
+ unitDictName: '保质期单位'
|
|
|
+ },
|
|
|
+ { label: '默认仓库', prop: 'warehouseName' }
|
|
|
+ ],
|
|
|
+ purchaseFields: [
|
|
|
+ {
|
|
|
+ label: '周期',
|
|
|
+ prop: 'purchasingCycle',
|
|
|
+ unitProp: 'purchasingCycleUnit',
|
|
|
+ unitDictName: '周期单位'
|
|
|
+ },
|
|
|
+ { label: '倍数', prop: 'purchaseMultiplier' },
|
|
|
+ {
|
|
|
+ label: '最低订购量',
|
|
|
+ prop: 'minimumOrderQuantity',
|
|
|
+ unitProp: 'measuringUnit',
|
|
|
+ unitDictName: '计量单位'
|
|
|
+ },
|
|
|
+ { label: '产地', prop: 'purchaseOrigins', dictName: '产地' },
|
|
|
+ { label: '采购组织', prop: 'checkDepartName' },
|
|
|
+ { label: '采购员', prop: 'checkPersonName' }
|
|
|
+ ],
|
|
|
+ productionFields: [
|
|
|
+ { label: '是否齐套件', prop: 'isCompleteSet', formatter: this.yesNo },
|
|
|
+ { label: '消耗波动', prop: 'consumWave', suffix: '%' },
|
|
|
+ { label: '变动损耗率', prop: 'changeLossRate', suffix: '%' },
|
|
|
+ { label: '固定损耗数', prop: 'fixLossNum' },
|
|
|
+ { label: '排程类型', prop: 'apsType', dictName: '排程类型' },
|
|
|
+ { label: '生产周期', prop: 'productionDays', suffix: '天' },
|
|
|
+ { label: '允许改型', prop: 'isModify', formatter: this.yesNo },
|
|
|
+ { label: '允许返工返修', prop: 'isRework', formatter: this.yesNo },
|
|
|
+ { label: '是否返回料', prop: 'isRematerial', formatter: this.yesNo },
|
|
|
+ { label: '是否副产品', prop: 'isByProduct', formatter: this.yesNo },
|
|
|
+ { label: '是否废品', prop: 'isWaste', formatter: this.yesNo },
|
|
|
+ { label: '是否不良品', prop: 'isDefective', formatter: this.yesNo }
|
|
|
+ ],
|
|
|
+ planFields: [
|
|
|
+ { label: '固定提前期', prop: 'fixLeadTime' },
|
|
|
+ { label: '变动提前期', prop: 'changeLeadTime' },
|
|
|
+ { label: '检验提前期', prop: 'checkLeadTime' },
|
|
|
+ { label: '累计提前期', prop: 'cumLeadTime' },
|
|
|
+ { label: '提前期单位', prop: 'unit', dictName: '提前期单位' },
|
|
|
+ {
|
|
|
+ label: '订货间隔期',
|
|
|
+ prop: 'orderIntervalTime',
|
|
|
+ unitProp: 'orderIntervalUnit',
|
|
|
+ unitDictName: '提前期单位'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ };
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ clientEnvironmentId() {
|
|
|
+ return this.$store.state.user.info.clientEnvironmentId;
|
|
|
+ },
|
|
|
+ imageList() {
|
|
|
+ return this.normalizeList(this.form.imgUrl);
|
|
|
+ },
|
|
|
+ previewList() {
|
|
|
+ return this.imageList.map((item) => this.getFileUrl(item)).filter(Boolean);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ businessId: {
|
|
|
+ immediate: true,
|
|
|
+ handler(val) {
|
|
|
+ if (val) {
|
|
|
+ this.getDetail();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.loadStaticDictionaries();
|
|
|
+ this.loadIndustryAttribute();
|
|
|
+ this.getFieldModel();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ async getDetail() {
|
|
|
+ this.loading = true;
|
|
|
+ try {
|
|
|
+ const data = await getCategoryDetails(this.businessId);
|
|
|
+ const info = this.deepClone(data || {});
|
|
|
+ const category = info.category || {};
|
|
|
+ category.colorKey = this.normalizeJoinValue(category.colorKey);
|
|
|
+ category.modelKey = this.normalizeJoinValue(category.modelKey);
|
|
|
+ category.componentAttribute = this.normalizeList(category.componentAttribute);
|
|
|
+ category.produceType = this.normalizeList(category.produceType)[0] || category.produceType;
|
|
|
+ category.extField = category.extField || {};
|
|
|
+ category.extTagField = category.extTagField || {};
|
|
|
+
|
|
|
+ this.form = category;
|
|
|
+ const detailIndustryAttribute =
|
|
|
+ info.industryAttribute || category.industryAttribute;
|
|
|
+ if (
|
|
|
+ detailIndustryAttribute !== undefined &&
|
|
|
+ detailIndustryAttribute !== null &&
|
|
|
+ detailIndustryAttribute !== ''
|
|
|
+ ) {
|
|
|
+ this.industryAttribute = detailIndustryAttribute;
|
|
|
+ }
|
|
|
+ this.remarkform = {
|
|
|
+ remark: category.remark || '',
|
|
|
+ remarkAttach: this.normalizeList(category.remarkAttach)
|
|
|
+ };
|
|
|
+ this.categoryAps = this.normalizeObject(info.categoryAps);
|
|
|
+ this.categoryMes = this.normalizeObject(info.categoryMes);
|
|
|
+ this.categoryPurchase = this.normalizeObject(info.categoryPurchase);
|
|
|
+ this.categorySales = this.normalizeObject(info.categorySales);
|
|
|
+ this.categoryWms = this.normalizeObject(info.categoryWms);
|
|
|
+ this.packageDispositionVOList = this.buildPackageGroups(
|
|
|
+ this.normalizeList(info.packageDispositionVOList)
|
|
|
+ );
|
|
|
+ } finally {
|
|
|
+ this.loading = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async getFieldModel() {
|
|
|
+ try {
|
|
|
+ const list = await fieldModel({ relevance: 't_main_category' });
|
|
|
+ this.dynamicFields = (list || []).map((item) => ({
|
|
|
+ ...item,
|
|
|
+ dictName: item.modelType === 'dict' ? item.label : ''
|
|
|
+ }));
|
|
|
+ await Promise.all(
|
|
|
+ this.dynamicFields
|
|
|
+ .filter((item) => item.dictName)
|
|
|
+ .map((item) => this.loadDictionary(item.dictName))
|
|
|
+ );
|
|
|
+ } catch (error) {
|
|
|
+ this.dynamicFields = [];
|
|
|
+ }
|
|
|
+ },
|
|
|
+ deepClone(data) {
|
|
|
+ return JSON.parse(JSON.stringify(data));
|
|
|
+ },
|
|
|
+ normalizeObject(value) {
|
|
|
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
|
+ },
|
|
|
+ normalizeList(value) {
|
|
|
+ if (!value) return [];
|
|
|
+ if (Array.isArray(value)) return value;
|
|
|
+ if (typeof value === 'string') {
|
|
|
+ try {
|
|
|
+ const data = JSON.parse(value);
|
|
|
+ return Array.isArray(data) ? data : value.split(',').filter(Boolean);
|
|
|
+ } catch (error) {
|
|
|
+ return value.split(',').filter(Boolean);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return [value];
|
|
|
+ },
|
|
|
+ normalizeJoinValue(value) {
|
|
|
+ return this.normalizeList(value).join(',');
|
|
|
+ },
|
|
|
+ async loadStaticDictionaries() {
|
|
|
+ const names = [
|
|
|
+ '存货类型',
|
|
|
+ '计量单位',
|
|
|
+ '重量单位',
|
|
|
+ '包装单位',
|
|
|
+ '体积单位',
|
|
|
+ '物品机型',
|
|
|
+ '物品颜色',
|
|
|
+ '质保预警参考',
|
|
|
+ '保质期单位',
|
|
|
+ '周期单位',
|
|
|
+ '产地',
|
|
|
+ '排程类型',
|
|
|
+ '提前期单位'
|
|
|
+ ];
|
|
|
+ await Promise.all(names.map((name) => this.loadDictionary(name)));
|
|
|
+ },
|
|
|
+ async loadIndustryAttribute() {
|
|
|
+ try {
|
|
|
+ const data = await parameterGetByCode({ code: 'industry_attribute' });
|
|
|
+ if (data && data.value !== undefined && data.value !== null) {
|
|
|
+ this.industryAttribute = data.value;
|
|
|
+ }
|
|
|
+ } catch (error) {}
|
|
|
+ },
|
|
|
+ async loadDictionary(dictName) {
|
|
|
+ if (!dictName || this.dictMaps[dictName]) return;
|
|
|
+ const code = DICT_CODE_MAP[dictName] || dictEnum[dictName];
|
|
|
+ if (!code) return;
|
|
|
+ try {
|
|
|
+ const res = await getByCode(code);
|
|
|
+ const map = (res.data || []).reduce((result, item) => {
|
|
|
+ const entry = Object.entries(item)[0];
|
|
|
+ if (entry) result[String(entry[0])] = entry[1];
|
|
|
+ return result;
|
|
|
+ }, {});
|
|
|
+ this.$set(this.dictMaps, dictName, map);
|
|
|
+ } catch (error) {
|
|
|
+ this.$set(this.dictMaps, dictName, {});
|
|
|
+ }
|
|
|
+ },
|
|
|
+ dictValue(dictName, value) {
|
|
|
+ if (value === undefined || value === null || value === '') return '-';
|
|
|
+ const map = this.dictMaps[dictName] || {};
|
|
|
+ const values = Array.isArray(value)
|
|
|
+ ? value
|
|
|
+ : typeof value === 'string' && value.includes(',')
|
|
|
+ ? value.split(',').filter(Boolean)
|
|
|
+ : [value];
|
|
|
+ return values.map((item) => map[String(item)] || item).join(',');
|
|
|
+ },
|
|
|
+ formatValue(source, item) {
|
|
|
+ if (!source) return '-';
|
|
|
+ let value = source[item.prop];
|
|
|
+ if (item.formatter) {
|
|
|
+ return item.formatter(value);
|
|
|
+ }
|
|
|
+ if (item.dictName) {
|
|
|
+ value = this.dictValue(item.dictName, value);
|
|
|
+ }
|
|
|
+ if (Array.isArray(value)) {
|
|
|
+ value = value.join(',');
|
|
|
+ }
|
|
|
+ if (value === undefined || value === null || value === '') {
|
|
|
+ return '-';
|
|
|
+ }
|
|
|
+ const unitValue = item.unitProp
|
|
|
+ ? source[item.unitProp]
|
|
|
+ : item.unitValue
|
|
|
+ ? item.unitValue()
|
|
|
+ : '';
|
|
|
+ const formattedUnit = item.unitDictName
|
|
|
+ ? this.dictValue(item.unitDictName, unitValue)
|
|
|
+ : unitValue;
|
|
|
+ const unit = formattedUnit === '-' ? '' : formattedUnit;
|
|
|
+ return `${value}${unit || item.suffix ? ' ' + (unit || item.suffix) : ''}`;
|
|
|
+ },
|
|
|
+ buildPackageGroups(rows) {
|
|
|
+ if (!rows.length) return [];
|
|
|
+ if (rows.some((item) => item.minPackageCell !== undefined)) return rows;
|
|
|
+ const groups = {};
|
|
|
+ rows.forEach((item) => {
|
|
|
+ const key = item.code || item.name || item.id;
|
|
|
+ if (!groups[key]) {
|
|
|
+ groups[key] = {
|
|
|
+ code: item.code,
|
|
|
+ name: item.name,
|
|
|
+ status: item.status
|
|
|
+ };
|
|
|
+ }
|
|
|
+ const group = groups[key];
|
|
|
+ if (item.name) group.name = item.name;
|
|
|
+ if (String(item.sort) === '0') {
|
|
|
+ group.status = item.status;
|
|
|
+ } else if (String(item.sort) === '1') {
|
|
|
+ group.minPackageCell = item.packageCell;
|
|
|
+ group.packageUnit = item.packageUnit;
|
|
|
+ group.minConversionUnit = item.conversionUnit;
|
|
|
+ } else if (String(item.sort) === '2') {
|
|
|
+ group.inPackageCell = item.packageCell;
|
|
|
+ group.inPackageUnit = item.packageUnit;
|
|
|
+ group.inConversionUnit = item.conversionUnit;
|
|
|
+ } else if (String(item.sort) === '3') {
|
|
|
+ group.outPackageCell = item.packageCell;
|
|
|
+ group.outPackageUnit = item.packageUnit;
|
|
|
+ group.outConversionUnit = item.conversionUnit;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return Object.values(groups);
|
|
|
+ },
|
|
|
+ formatPackageUnit(row, type) {
|
|
|
+ const config = {
|
|
|
+ min: ['minPackageCell', 'packageUnit', 'minConversionUnit'],
|
|
|
+ in: ['inPackageCell', 'inPackageUnit', 'inConversionUnit'],
|
|
|
+ out: ['outPackageCell', 'outPackageUnit', 'outConversionUnit']
|
|
|
+ }[type];
|
|
|
+ const value = row[config[0]];
|
|
|
+ if (value === undefined || value === null || value === '') return '-';
|
|
|
+ const fromUnit = this.dictValue('计量单位', row[config[1]]);
|
|
|
+ const toUnit = this.dictValue('计量单位', row[config[2]]);
|
|
|
+ return `${value}${fromUnit === '-' ? '' : fromUnit}${
|
|
|
+ toUnit === '-' ? '' : '/' + toUnit
|
|
|
+ }`;
|
|
|
+ },
|
|
|
+ yesNo(value) {
|
|
|
+ if (value === undefined || value === null || value === '') return '-';
|
|
|
+ return Number(value) === 1 ? '是' : '否';
|
|
|
+ },
|
|
|
+ enabledText(value) {
|
|
|
+ if (value === undefined || value === null || value === '') return '-';
|
|
|
+ return Number(value) === 1 ? '启用' : '停用';
|
|
|
+ },
|
|
|
+ processingTypeText(value) {
|
|
|
+ if (value === undefined || value === null || value === '') return '-';
|
|
|
+ return Number(value) === 1 ? '批量' : '单件';
|
|
|
+ },
|
|
|
+ inventoryModeText(value) {
|
|
|
+ if (value === undefined || value === null || value === '') return '-';
|
|
|
+ return Number(value) === 1 ? '批量盘点' : '逐个盘点';
|
|
|
+ },
|
|
|
+ componentAttributeText(value) {
|
|
|
+ const map = {
|
|
|
+ 1: '自制件',
|
|
|
+ 2: '采购件',
|
|
|
+ 3: '外协件',
|
|
|
+ 4: '受托件'
|
|
|
+ };
|
|
|
+ const list = this.normalizeList(value);
|
|
|
+ return list.length ? list.map((item) => map[item] || item).join(',') : '-';
|
|
|
+ },
|
|
|
+ produceTypeText(value) {
|
|
|
+ const map = {
|
|
|
+ 1: '加工',
|
|
|
+ 3: '装配'
|
|
|
+ };
|
|
|
+ return map[value] || value || '-';
|
|
|
+ },
|
|
|
+ measureTypeText(value) {
|
|
|
+ const map = {
|
|
|
+ 1: '数量',
|
|
|
+ 2: '重量',
|
|
|
+ 3: '体积',
|
|
|
+ 4: '容积',
|
|
|
+ 5: '面积'
|
|
|
+ };
|
|
|
+ return map[value] || value || '-';
|
|
|
+ },
|
|
|
+ pricingWayText(value) {
|
|
|
+ const map = {
|
|
|
+ 1: '按数量计价',
|
|
|
+ 2: '按重量计价'
|
|
|
+ };
|
|
|
+ return map[value] || value || '-';
|
|
|
+ },
|
|
|
+ getFileUrl(file) {
|
|
|
+ if (!file) return '';
|
|
|
+ if (typeof file === 'string') return file;
|
|
|
+ return file.url || file.path || file.fileUrl || file.downloadUrl || '';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+ .item-publish-approval {
|
|
|
+ padding: 10px 0;
|
|
|
+
|
|
|
+ .section {
|
|
|
+ margin-bottom: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-title {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ display: inline-block;
|
|
|
+ width: 4px;
|
|
|
+ height: 16px;
|
|
|
+ margin-right: 8px;
|
|
|
+ background: #1890ff;
|
|
|
+ content: '';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .product-image {
|
|
|
+ width: 96px;
|
|
|
+ height: 96px;
|
|
|
+ margin-right: 10px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ border: 1px solid #ebeef5;
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|