| | |
| | | export function updateParameter(data) { |
| | | return request({ |
| | | url: '/basic/parameter/update', |
| | | method: 'post', |
| | | method: 'put', |
| | | data: data |
| | | }) |
| | | } |
| | |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // æ°å¢åºç¡åæ° |
| | | export function addBaseParam(data) { |
| | | return request({ |
| | | url: '/baseParam/add', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // ç¼è¾åºç¡åæ° |
| | | export function editBaseParam(data) { |
| | | return request({ |
| | | url: '/baseParam/edit', |
| | | method: 'put', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // æ¥è¯¢åºç¡åæ°å表 |
| | | export function getBaseParamList(query) { |
| | | return request({ |
| | | url: '/baseParam/list', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | | |
| | | // å é¤åºç¡åæ° |
| | | export function removeBaseParam(ids) { |
| | | return request({ |
| | | url: `/baseParam/remove/${Array.isArray(ids) ? ids.join(',') : ids}`, |
| | | method: 'delete' |
| | | }) |
| | | } |
| | |
| | | method: "post", |
| | | responseType: "blob", |
| | | }); |
| | | } |
| | | |
| | | // è·åå·¥åºåæ°å表 |
| | | export function getProcessParamList(processId) { |
| | | return request({ |
| | | url: `/productProcessParam/list/${processId}`, |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | // æ·»å å·¥åºåæ° |
| | | export function addProcessParam(data) { |
| | | return request({ |
| | | url: "/productProcessParam/add", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ç¼è¾å·¥åºåæ° |
| | | export function editProcessParam(data) { |
| | | return request({ |
| | | url: "/productProcessParam/edit", |
| | | method: "put", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // å é¤å·¥åºåæ° |
| | | export function deleteProcessParam(id) { |
| | | return request({ |
| | | url: `/productProcessParam/${id}`, |
| | | method: "delete", |
| | | }); |
| | | } |
| | |
| | | typeof dataTypeFn(scope.row[item.prop], item.formatData) === |
| | | 'string' |
| | | " |
| | | :title="formatters(scope.row[item.prop], item.formatData)" |
| | | :title="formatters(scope.row[item.prop], item.formatData, scope.row)" |
| | | :type="formatType(scope.row[item.prop], item.formatType)"> |
| | | {{ formatters(scope.row[item.prop], item.formatData) }} |
| | | {{ formatters(scope.row[item.prop], item.formatData, scope.row) }} |
| | | </el-tag> |
| | | <el-tag v-for="(tag, index) in dataTypeFn( |
| | | scope.row[item.prop], |
| | |
| | | 'object' |
| | | " |
| | | :key="index" |
| | | :title="formatters(scope.row[item.prop], item.formatData)" |
| | | :title="formatters(scope.row[item.prop], item.formatData, scope.row)" |
| | | :type="formatType(tag, item.formatType)"> |
| | | {{ item.tagGroup ? tag[item.tagGroup.label] ?? tag : tag }} |
| | | </el-tag> |
| | | <el-tag v-else |
| | | :title="formatters(scope.row[item.prop], item.formatData)" |
| | | :title="formatters(scope.row[item.prop], item.formatData, scope.row)" |
| | | :type="formatType(scope.row[item.prop], item.formatType)"> |
| | | {{ formatters(scope.row[item.prop], item.formatData) }} |
| | | {{ formatters(scope.row[item.prop], item.formatData, scope.row) }} |
| | | </el-tag> |
| | | </div> |
| | | <!-- æé® --> |
| | |
| | | style="width: 100%"> |
| | | <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span> |
| | | <span v-else>{{ |
| | | formatters(scope.row[item.prop], item.formatData) |
| | | formatters(scope.row[item.prop], item.formatData, scope.row) |
| | | }}</span> |
| | | </div> |
| | | </template> |
| | |
| | | return typeof val === "function" ? val(row) : val; |
| | | }; |
| | | |
| | | const formatters = (val, format) => { |
| | | return typeof format === "function" ? format(val) : val; |
| | | const formatters = (val, format, row) => { |
| | | return typeof format === "function" ? format(val, row) : val; |
| | | }; |
| | | |
| | | // Propsï¼ä½¿ç¨ defineProps çé TS å½¢å¼ï¼ |
| | |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "客æ·åç±»", |
| | | prop: "customerType", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | prop: "customerName", |
| | | width: 220, |
| | |
| | | label: "èç³»çµè¯", |
| | | prop: "contactPhone", |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "客æ·åç±»", |
| | | prop: "customerType", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "è·è¿è¿åº¦", |
| | |
| | | maintenanceTime: [ |
| | | { required: false, message: "è¯·éæ©", trigger: "change" }, |
| | | ], |
| | | basicBankAccount: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | bankAccount: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | bankCode: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | customerType: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | basicBankAccount: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | bankAccount: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | bankCode: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | customerType: [{ required: false, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const upload = reactive({ |
| | |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">åæ°åç§°ï¼</span> |
| | | <el-input v-model="searchForm.materialCode" |
| | | <el-input v-model="searchForm.paramName" |
| | | style="width: 200px" |
| | | placeholder="请è¾å
¥åæ°åç§°" |
| | | clearable /> |
| | | <span class="search_title ml10">å
³è产åç±»åï¼</span> |
| | | <!-- å
³è产åç±»åæç´¢ --> |
| | | <!-- <span class="search_title ml10">å
³è产åç±»åï¼</span> |
| | | <el-input v-model="searchForm.productName" |
| | | style="width: 200px" |
| | | style="width: 200px"d |
| | | placeholder="请è¾å
¥å
³è产åç±»å" |
| | | clearable /> |
| | | clearable /> --> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px">æç´¢</el-button> |
| | |
| | | <el-button type="primary" |
| | | @click="handleAdd" |
| | | style="margin-left: 10px">æ°å¢åæ°</el-button> |
| | | <el-button type="primary" |
| | | <!-- 产åç±»åç»´æ¤æé® --> |
| | | <!-- <el-button type="primary" |
| | | @click="handleProductTypeMaintenance" |
| | | style="margin-left: 10px">产åç±»åç»´æ¤</el-button> |
| | | style="margin-left: 10px">产åç±»åç»´æ¤</el-button> --> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable rowKey="materialCode" |
| | | <PIMTable rowKey="paramName" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | height="calc(100vh - 320px)" |
| | | height="calc(100vh - 280px)" |
| | | :tableLoading="tableLoading" |
| | | :isSelection="false" |
| | | :isShowPagination="false" |
| | | @pagination="pagination"> |
| | | </PIMTable> |
| | | </div> |
| | |
| | | :rules="rules" |
| | | ref="formRef" |
| | | label-width="120px"> |
| | | <el-form-item label="åæ°ç¼å·" |
| | | prop="parameterCode"> |
| | | <el-input v-model="formData.parameterCode" |
| | | placeholder="请è¾å
¥åæ°ç¼å·" /> |
| | | </el-form-item> |
| | | <el-form-item label="åæ°åç§°" |
| | | prop="parameterName"> |
| | | <el-input v-model="formData.parameterName" |
| | | prop="paramName"> |
| | | <el-input v-model="formData.paramName" |
| | | placeholder="请è¾å
¥åæ°åç§°" /> |
| | | </el-form-item> |
| | | <el-form-item label="åæ°æ¨¡å¼" |
| | | prop="parameterFormat"> |
| | | <el-select v-model="formData.parameterType2" |
| | | <el-form-item label="åæ°ç±»å" |
| | | prop="paramType"> |
| | | <el-select v-model="formData.paramType" |
| | | @change="handleParamTypeChange" |
| | | placeholder="è¯·éæ©åæ°ç±»å"> |
| | | <el-option label="æ°å¼æ ¼å¼" |
| | | value="1" /> |
| | | <el-option label="ææ¬æ ¼å¼" |
| | | value="2" /> |
| | | <el-option label="䏿é项" |
| | | value="3" /> |
| | | <el-option label="æ¶é´æ ¼å¼" |
| | | value="4" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å弿¨¡å¼" |
| | | prop="valueMode"> |
| | | <el-select v-model="formData.valueMode" |
| | | placeholder="è¯·éæ©å弿¨¡å¼"> |
| | | <el-option label="åå¼" |
| | | value="1" /> |
| | | <el-option label="åºé´" |
| | | value="2" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="åæ°ç±»å" |
| | | prop="parameterType"> |
| | | <el-select v-model="formData.parameterType" |
| | | @change="handleParameterTypeChange" |
| | | placeholder="è¯·éæ©åæ°ç±»å"> |
| | | <el-option label="æ°å¼æ ¼å¼" |
| | | value="æ°å¼æ ¼å¼" /> |
| | | <el-option label="ææ¬æ ¼å¼" |
| | | value="ææ¬æ ¼å¼" /> |
| | | <el-option label="䏿é项" |
| | | value="䏿é项" /> |
| | | <el-option label="æ¶é´æ ¼å¼" |
| | | value="æ¶é´æ ¼å¼" /> |
| | | </el-select> |
| | | <el-form-item label="åä½" |
| | | prop="unit"> |
| | | <el-input v-model="formData.unit" |
| | | placeholder="请è¾å
¥åä½" /> |
| | | </el-form-item> |
| | | <el-form-item v-if="formData.parameterType === '䏿é项'" |
| | | label="æ°æ®åå
¸" |
| | | prop="parameterFormat"> |
| | | <el-select v-model="formData.parameterFormat" |
| | | placeholder="è¯·éæ©æ°æ®åå
¸"> |
| | | <el-form-item label="å弿 ¼å¼" |
| | | v-if="formData.paramType == '1' || formData.paramType == '2'" |
| | | prop="paramFormat"> |
| | | <el-input v-model="formData.paramFormat" |
| | | placeholder="请è¾å
¥å弿 ¼å¼" /> |
| | | </el-form-item> |
| | | <el-form-item label="䏿åå
¸" |
| | | v-else-if="formData.paramType == '3'" |
| | | prop="paramFormat"> |
| | | <el-select v-model="formData.paramFormat" |
| | | placeholder="è¯·éæ©å弿¨¡å¼"> |
| | | <el-option v-for="item in dictTypes" |
| | | :key="item.dictType" |
| | | :label="item.dictName" |
| | | :value="item.dictType" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item v-else-if="formData.parameterType === 'æ¶é´æ ¼å¼'" |
| | | label="æ¶é´æ ¼å¼" |
| | | prop="parameterFormat"> |
| | | <el-select v-model="formData.parameterFormat" |
| | | placeholder="è¯·éæ©æ¶é´æ ¼å¼"> |
| | | <el-option label="YYYY-MM-DD HH:mm:ss" |
| | | value="YYYY-MM-DD HH:mm:ss" /> |
| | | <el-form-item label="æ¶é´æ ¼å¼" |
| | | v-else-if="formData.paramType == '4'" |
| | | prop="paramFormat"> |
| | | <el-select v-model="formData.paramFormat" |
| | | placeholder="è¯·éæ©å弿¨¡å¼"> |
| | | <el-option label="YYYY-MM-DD" |
| | | value="YYYY-MM-DD" /> |
| | | <el-option label="YYYY-MM-DD HH:mm:ss" |
| | | value="YYYY-MM-DD HH:mm:ss" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item v-else |
| | | label="åæ°æ ¼å¼" |
| | | prop="parameterFormat"> |
| | | <el-input v-model="formData.parameterFormat" |
| | | placeholder="请è¾å
¥åæ°æ ¼å¼" /> |
| | | </el-form-item> |
| | | <el-form-item label="å
³è产åç±»å" |
| | | prop="parameterValue"> |
| | | <el-select v-model="formData.parameterValue" |
| | | placeholder="è¯·éæ©å
³è产åç±»å"> |
| | | <el-option v-for="item in productTypes" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="æ åå¼" |
| | | v-if="formData.parameterType2 === '1'" |
| | | prop="standardValue"> |
| | | <el-input v-model="formData.standardValue" |
| | | placeholder="请è¾å
¥æ åå¼" /> |
| | | </el-form-item> |
| | | <el-form-item label="æå¤§å¼" |
| | | v-if="formData.parameterType2 === '2'" |
| | | prop="standardValue"> |
| | | <el-input v-model="formData.standardValue" |
| | | placeholder="请è¾å
¥æ åå¼" /> |
| | | </el-form-item> |
| | | <el-form-item label="æå°å¼" |
| | | v-if="formData.parameterType2 === '2'" |
| | | prop="standardValue"> |
| | | <el-input v-model="formData.standardValue" |
| | | placeholder="请è¾å
¥æ åå¼" /> |
| | | </el-form-item> |
| | | <el-form-item label="åä½" |
| | | prop="unit"> |
| | | <el-input v-model="formData.unit" |
| | | placeholder="请è¾å
¥åä½" /> |
| | | <el-form-item label="夿³¨" |
| | | prop="remark"> |
| | | <el-input v-model="formData.remark" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥å¤æ³¨" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | |
| | | </template> |
| | | </el-dialog> |
| | | <!-- 产åç±»åç»´æ¤å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="productTypeDialogVisible" |
| | | <!-- <el-dialog v-model="productTypeDialogVisible" |
| | | title="产åç±»åç»´æ¤" |
| | | width="600px"> |
| | | <div class="product-type-header"> |
| | |
| | | <el-table :data="productTypeList" |
| | | border |
| | | style="width: 100%; margin-top: 10px; margin-bottom: 20px"> |
| | | <!-- <el-table-column prop="typeCode" |
| | | <el-table-column prop="typeCode" |
| | | label="ç±»åç¼ç " |
| | | width="150" /> --> |
| | | width="150" /> |
| | | <el-table-column prop="typeName" |
| | | label="ç±»ååç§°" /> |
| | | <el-table-column label="æä½" |
| | |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-dialog> |
| | | </el-dialog> --> |
| | | <!-- æ°å¢/ç¼è¾äº§åç±»åå¯¹è¯æ¡ --> |
| | | <el-dialog v-model="productTypeFormVisible" |
| | | <!-- <el-dialog v-model="productTypeFormVisible" |
| | | :title="productTypeDialogTitle" |
| | | width="400px"> |
| | | <el-form :model="productTypeForm" |
| | | :rules="productTypeRules" |
| | | ref="productTypeFormRef" |
| | | label-width="100px"> |
| | | <!-- <el-form-item label="ç±»åç¼ç " |
| | | <el-form-item label="ç±»åç¼ç " |
| | | prop="typeCode"> |
| | | <el-input v-model="productTypeForm.typeCode" |
| | | placeholder="请è¾å
¥ç±»åç¼ç " /> |
| | | </el-form-item> --> |
| | | </el-form-item> |
| | | <el-form-item label="ç±»ååç§°" |
| | | prop="typeName"> |
| | | <el-input v-model="productTypeForm.typeName" |
| | |
| | | @click="handleProductTypeSubmit">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </el-dialog> --> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | addParameter, |
| | | updateParameter, |
| | | delParameter, |
| | | getProductTypes as getProductTypesApi, |
| | | addBaseParam, |
| | | editBaseParam, |
| | | getBaseParamList, |
| | | removeBaseParam, |
| | | // getProductTypes as getProductTypesApi, |
| | | } from "@/api/basicData/parameterMaintenance.js"; |
| | | import { listType } from "@/api/system/dict/type"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "åæ°ç¼å·", |
| | | prop: "parameterCode", |
| | | className: "code-cell", |
| | | }, |
| | | { |
| | | label: "åæ°åç§°", |
| | | prop: "parameterName", |
| | | }, |
| | | { |
| | | label: "åæ°æ¨¡å¼", |
| | | prop: "parameterType2", |
| | | prop: "paramName", |
| | | }, |
| | | { |
| | | label: "åæ°ç±»å", |
| | | prop: "parameterType", |
| | | prop: "paramType", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | const typeMap = { |
| | | æ°å¼æ ¼å¼: "primary", |
| | | ææ¬æ ¼å¼: "info", |
| | | 䏿é项: "warning", |
| | | æ¶é´æ ¼å¼: "success", |
| | | 1: "primary", |
| | | 2: "info", |
| | | 3: "warning", |
| | | 4: "success", |
| | | }; |
| | | return typeMap[params] || "default"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "åæ°æ ¼å¼", |
| | | prop: "parameterFormat", |
| | | }, |
| | | { |
| | | label: "å
³è产åç±»å", |
| | | prop: "parameterValue", |
| | | }, |
| | | { |
| | | label: "æ åå¼", |
| | | prop: "standardValue", |
| | | className: row => { |
| | | return row.parameterType == "æ°å¼æ ¼å¼" ? "quantity-cell" : ""; |
| | | formatData: val => { |
| | | const labelMap = { |
| | | 1: "æ°å¼æ ¼å¼", |
| | | 2: "ææ¬æ ¼å¼", |
| | | 3: "䏿é项", |
| | | 4: "æ¶é´æ ¼å¼", |
| | | }; |
| | | return labelMap[val] || val; |
| | | }, |
| | | }, |
| | | { |
| | | label: "æå¤§å¼", |
| | | prop: "standardValue", |
| | | className: row => { |
| | | return row.parameterType == "æ°å¼æ ¼å¼" ? "quantity-cell" : ""; |
| | | label: "å弿¨¡å¼", |
| | | prop: "valueMode", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | return params === 2 ? "warning" : "success"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "æå°å¼", |
| | | prop: "standardValue", |
| | | className: row => { |
| | | return row.parameterType == "æ°å¼æ ¼å¼" ? "quantity-cell" : ""; |
| | | formatData: val => { |
| | | return val === 2 ? "åºé´" : "åå¼"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "å弿 ¼å¼", |
| | | prop: "paramFormat", |
| | | formatData: (val, row) => { |
| | | if (row.paramType == "3") { |
| | | const dict = dictTypes.value.find(item => item.dictType === val); |
| | | return dict ? "åå
¸:" + dict.dictName : val; |
| | | } |
| | | return val; |
| | | }, |
| | | }, |
| | | { |
| | | label: "夿³¨", |
| | | prop: "remark", |
| | | }, |
| | | { |
| | | label: "å建æ¶é´", |
| | | prop: "createTime", |
| | | }, |
| | | { |
| | | label: "æä½", |
| | |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | materialCode: "", |
| | | paramName: "", |
| | | productName: "", |
| | | }); |
| | | |
| | |
| | | const dialogTitle = ref(""); |
| | | const formRef = ref(null); |
| | | const formData = reactive({ |
| | | parameterCode: "", |
| | | parameterName: "", |
| | | parameterType2: "1", |
| | | parameterType: "", |
| | | parameterFormat: "", |
| | | parameterValue: "", |
| | | standardValue: "", |
| | | id: null, |
| | | paramName: "", |
| | | paramType: "", |
| | | valueMode: "1", |
| | | unit: "", |
| | | remark: "", |
| | | }); |
| | | const rules = reactive({ |
| | | parameterCode: [ |
| | | { required: true, message: "请è¾å
¥åæ°ç¼å·", trigger: "blur" }, |
| | | paramName: [{ required: true, message: "请è¾å
¥åæ°åç§°", trigger: "blur" }], |
| | | paramType: [{ required: true, message: "è¯·éæ©åæ°ç±»å", trigger: "change" }], |
| | | valueMode: [{ required: true, message: "è¯·éæ©å弿¨¡å¼", trigger: "change" }], |
| | | unit: [ |
| | | { |
| | | required: false, |
| | | message: "请è¾å
¥åä½", |
| | | trigger: "blur", |
| | | validator: (rule, value, callback) => { |
| | | if (formData.paramType === "1" && !value) { |
| | | callback(new Error("æ°å¼ç±»åå¿
须填ååä½")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | parameterName: [ |
| | | { required: true, message: "请è¾å
¥åæ°åç§°", trigger: "blur" }, |
| | | ], |
| | | parameterType: [ |
| | | { required: true, message: "è¯·éæ©åæ°ç±»å", trigger: "change" }, |
| | | ], |
| | | parameterFormat: [ |
| | | { required: true, message: "è¯·éæ©åæ°æ ¼å¼", trigger: "change" }, |
| | | ], |
| | | parameterValue: [ |
| | | { required: true, message: "è¯·éæ©å
³è产åç±»å", trigger: "change" }, |
| | | ], |
| | | standardValue: [{ required: true, message: "请è¾å
¥æ åå¼", trigger: "blur" }], |
| | | unit: [{ required: true, message: "请è¾å
¥åä½", trigger: "blur" }], |
| | | }); |
| | | const productTypes = ref([]); |
| | | // const productTypes = ref([]); |
| | | const isEdit = ref(false); |
| | | |
| | | // 产åç±»åç»´æ¤ç¸å
³ |
| | | const productTypeDialogVisible = ref(false); |
| | | const productTypeFormVisible = ref(false); |
| | | const productTypeDialogTitle = ref(""); |
| | | const productTypeFormRef = ref(null); |
| | | const productTypeList = ref([]); |
| | | const productTypeForm = reactive({ |
| | | id: null, |
| | | // typeCode: "", |
| | | typeName: "", |
| | | }); |
| | | const productTypeRules = reactive({ |
| | | // typeCode: [{ required: true, message: "请è¾å
¥ç±»åç¼ç ", trigger: "blur" }], |
| | | typeName: [{ required: true, message: "请è¾å
¥ç±»ååç§°", trigger: "blur" }], |
| | | }); |
| | | const isProductTypeEdit = ref(false); |
| | | const handleParameterTypeChange = () => { |
| | | if (formData.parameterType === "æ°å¼æ ¼å¼") { |
| | | formData.parameterFormat = "#.0000"; |
| | | } else if (formData.parameterType === "æ¶é´æ ¼å¼") { |
| | | formData.parameterFormat = "YYYY-MM-DD HH:mm:ss"; |
| | | // 产åç±»åç»´æ¤ç¸å
³ - 已注é |
| | | // const productTypeDialogVisible = ref(false); |
| | | // const productTypeFormVisible = ref(false); |
| | | // const productTypeDialogTitle = ref(""); |
| | | // const productTypeFormRef = ref(null); |
| | | // const productTypeList = ref([]); |
| | | // const productTypeForm = reactive({ |
| | | // id: null, |
| | | // typeCode: "", |
| | | // typeName: "", |
| | | // }); |
| | | // const productTypeRules = reactive({ |
| | | // typeCode: [{ required: true, message: "请è¾å
¥ç±»åç¼ç ", trigger: "blur" }], |
| | | // typeName: [{ required: true, message: "请è¾å
¥ç±»ååç§°", trigger: "blur" }], |
| | | // }); |
| | | // const isProductTypeEdit = ref(false); |
| | | const handleParamTypeChange = () => { |
| | | if (formData.paramType === "1") { |
| | | formData.paramFormat = "#.0000"; |
| | | } else if (formData.paramType === "4") { |
| | | formData.paramFormat = "YYYY-MM-DD HH:mm:ss"; |
| | | } else { |
| | | formData.parameterFormat = ""; |
| | | formData.paramFormat = ""; |
| | | } |
| | | // 触ååä½å段éªè¯ |
| | | if (formRef.value) { |
| | | formRef.value.validateField("unit"); |
| | | } |
| | | }; |
| | | // 产åç±»åç»´æ¤æé®ç¹å»äºä»¶ |
| | | const handleProductTypeMaintenance = () => { |
| | | productTypeDialogVisible.value = true; |
| | | getProductTypeList(); |
| | | }; |
| | | // 产åç±»åç»´æ¤æé®ç¹å»äºä»¶ - 已注é |
| | | // const handleProductTypeMaintenance = () => { |
| | | // productTypeDialogVisible.value = true; |
| | | // getProductTypeList(); |
| | | // }; |
| | | |
| | | // è·å产åç±»åå表 |
| | | const getProductTypeList = () => { |
| | | productTypeList.value = [ |
| | | { id: 1, typeCode: "TYPE001", typeName: "3.5ç å" }, |
| | | { id: 2, typeCode: "TYPE002", typeName: "5.0ç å" }, |
| | | { id: 3, typeCode: "TYPE003", typeName: "æ¿æ" }, |
| | | ]; |
| | | }; |
| | | // è·å产åç±»åå表 - 已注é |
| | | // const getProductTypeList = () => { |
| | | // productTypeList.value = [ |
| | | // { id: 1, typeCode: "TYPE001", typeName: "3.5ç å" }, |
| | | // { id: 2, typeCode: "TYPE002", typeName: "5.0ç å" }, |
| | | // { id: 3, typeCode: "TYPE003", typeName: "æ¿æ" }, |
| | | // ]; |
| | | // }; |
| | | |
| | | // æ°å¢äº§åç±»å |
| | | const handleAddProductType = () => { |
| | | isProductTypeEdit.value = false; |
| | | productTypeDialogTitle.value = "æ°å¢äº§åç±»å"; |
| | | productTypeForm.id = null; |
| | | productTypeForm.typeCode = ""; |
| | | productTypeForm.typeName = ""; |
| | | productTypeFormVisible.value = true; |
| | | }; |
| | | // æ°å¢äº§åç±»å - 已注é |
| | | // const handleAddProductType = () => { |
| | | // isProductTypeEdit.value = false; |
| | | // productTypeDialogTitle.value = "æ°å¢äº§åç±»å"; |
| | | // productTypeForm.id = null; |
| | | // productTypeForm.typeCode = ""; |
| | | // productTypeForm.typeName = ""; |
| | | // productTypeFormVisible.value = true; |
| | | // }; |
| | | |
| | | // ç¼è¾äº§åç±»å |
| | | const handleEditProductType = row => { |
| | | isProductTypeEdit.value = true; |
| | | productTypeDialogTitle.value = "ç¼è¾äº§åç±»å"; |
| | | productTypeForm.id = row.id; |
| | | productTypeForm.typeCode = row.typeCode; |
| | | productTypeForm.typeName = row.typeName; |
| | | productTypeFormVisible.value = true; |
| | | }; |
| | | // ç¼è¾äº§åç±»å - 已注é |
| | | // const handleEditProductType = row => { |
| | | // isProductTypeEdit.value = true; |
| | | // productTypeDialogTitle.value = "ç¼è¾äº§åç±»å"; |
| | | // productTypeForm.id = row.id; |
| | | // productTypeForm.typeCode = row.typeCode; |
| | | // productTypeForm.typeName = row.typeName; |
| | | // productTypeFormVisible.value = true; |
| | | // }; |
| | | |
| | | // å é¤äº§åç±»å |
| | | const handleDeleteProductType = row => { |
| | | ElMessageBox.confirm("ç¡®å®è¦å é¤è¯¥äº§åç±»ååï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | ElMessage.success("å 餿å"); |
| | | getProductTypeList(); |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | // å é¤äº§åç±»å - 已注é |
| | | // const handleDeleteProductType = row => { |
| | | // ElMessageBox.confirm("ç¡®å®è¦å é¤è¯¥äº§åç±»ååï¼", "æç¤º", { |
| | | // confirmButtonText: "ç¡®å®", |
| | | // cancelButtonText: "åæ¶", |
| | | // type: "warning", |
| | | // }) |
| | | // .then(() => { |
| | | // ElMessage.success("å 餿å"); |
| | | // getProductTypeList(); |
| | | // }) |
| | | // .catch(() => {}); |
| | | // }; |
| | | |
| | | // æäº¤äº§åç±»å表å |
| | | const handleProductTypeSubmit = () => { |
| | | productTypeFormRef.value.validate(valid => { |
| | | if (valid) { |
| | | ElMessage.success(isProductTypeEdit.value ? "ç¼è¾æå" : "æ°å¢æå"); |
| | | productTypeFormVisible.value = false; |
| | | getProductTypeList(); |
| | | } |
| | | }); |
| | | }; |
| | | // æäº¤äº§åç±»å表å - 已注é |
| | | // const handleProductTypeSubmit = () => { |
| | | // productTypeFormRef.value.validate(valid => { |
| | | // if (valid) { |
| | | // ElMessage.success(isProductTypeEdit.value ? "ç¼è¾æå" : "æ°å¢æå"); |
| | | // productTypeFormVisible.value = false; |
| | | // getProductTypeList(); |
| | | // } |
| | | // }); |
| | | // }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | |
| | | |
| | | /** éç½®æé®æä½ */ |
| | | const handleReset = () => { |
| | | searchForm.materialCode = ""; |
| | | searchForm.paramName = ""; |
| | | searchForm.productName = ""; |
| | | page.current = 1; |
| | | getList(); |
| | |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | // 注éæAPIè°ç¨ï¼ä½¿ç¨åæ°æ® |
| | | /*const params = { ...searchForm, ...page }; |
| | | parameterListPage(params) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data; |
| | | page.total = res.total || 0; |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | });*/ |
| | | |
| | | // åæ°æ® |
| | | setTimeout(() => { |
| | | tableLoading.value = false; |
| | | tableData.value = [ |
| | | { |
| | | id: 1, |
| | | parameterCode: "PARAM001", |
| | | parameterName: "é¿åº¦", |
| | | parameterType2: "1", |
| | | parameterType: "æ°å¼æ ¼å¼", |
| | | parameterFormat: "", |
| | | parameterValue: "type1", |
| | | standardValue: "100", |
| | | unit: "mm", |
| | | }, |
| | | { |
| | | id: 2, |
| | | parameterCode: "PARAM002", |
| | | parameterName: "温度", |
| | | parameterType2: "2", |
| | | parameterType: "æ°å¼æ ¼å¼", |
| | | parameterFormat: "", |
| | | parameterValue: "type1", |
| | | standardValue: "25", |
| | | unit: "â", |
| | | }, |
| | | { |
| | | id: 3, |
| | | parameterCode: "PARAM003", |
| | | parameterName: "é¢è²", |
| | | parameterType2: "1", |
| | | parameterType: "ææ¬æ ¼å¼", |
| | | parameterFormat: "", |
| | | parameterValue: "type2", |
| | | standardValue: "红è²", |
| | | unit: "", |
| | | }, |
| | | { |
| | | id: 4, |
| | | parameterCode: "PARAM004", |
| | | parameterName: "ç¶æ", |
| | | parameterType2: "1", |
| | | parameterType: "䏿é项", |
| | | parameterFormat: "status", |
| | | parameterValue: "type3", |
| | | standardValue: "æ£å¸¸", |
| | | unit: "", |
| | | }, |
| | | { |
| | | id: 5, |
| | | parameterCode: "PARAM005", |
| | | parameterName: "å建æ¶é´", |
| | | parameterType2: "1", |
| | | parameterType: "æ¶é´æ ¼å¼", |
| | | parameterFormat: "YYYY-MM-DD HH:mm:ss", |
| | | parameterValue: "type2", |
| | | standardValue: "2024-01-01 00:00:00", |
| | | unit: "", |
| | | }, |
| | | ]; |
| | | page.total = 5; |
| | | }, 500); |
| | | // è°ç¨æ°æ¥å£ /baseParam/list |
| | | getBaseParamList({ paramName: searchForm.paramName }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | if (res.code === 200) { |
| | | tableData.value = res.data || []; |
| | | page.total = res.data?.length || 0; |
| | | } else { |
| | | ElMessage.error(res.msg || "æ¥è¯¢å¤±è´¥"); |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | ElMessage.error("æ¥è¯¢å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // è·å产åç±»åå表 |
| | | const getProductTypes = () => { |
| | | // 注éæAPIè°ç¨ï¼ä½¿ç¨åæ°æ® |
| | | /*getProductTypesApi() |
| | | .then(res => { |
| | | productTypes.value = res.data || []; |
| | | }) |
| | | .catch(() => { |
| | | // 失败æ¶ä½¿ç¨æ¨¡ææ°æ® |
| | | productTypes.value = [ |
| | | { label: "3.5ç å", value: "type1" }, |
| | | { label: "5.0ç å", value: "type2" }, |
| | | { label: "æ¿æ", value: "type3" }, |
| | | ]; |
| | | });*/ |
| | | |
| | | // åæ°æ® |
| | | productTypes.value = [ |
| | | { label: "3.5ç å", value: "type1" }, |
| | | { label: "5.0ç å", value: "type2" }, |
| | | { label: "æ¿æ", value: "type3" }, |
| | | ]; |
| | | }; |
| | | // è·å产åç±»åå表 - 已注é |
| | | // const getProductTypes = () => { |
| | | // productTypes.value = [ |
| | | // { label: "3.5ç å", value: "type1" }, |
| | | // { label: "5.0ç å", value: "type2" }, |
| | | // { label: "æ¿æ", value: "type3" }, |
| | | // ]; |
| | | // }; |
| | | |
| | | // æ°å¢æé®ç¹å»äºä»¶ |
| | | const handleAdd = () => { |
| | | isEdit.value = false; |
| | | dialogTitle.value = "æ°å¢åæ°"; |
| | | // é置表å |
| | | formData.parameterCode = ""; |
| | | formData.parameterName = ""; |
| | | formData.parameterType2 = "1"; |
| | | formData.parameterType = ""; |
| | | formData.parameterFormat = ""; |
| | | formData.parameterValue = ""; |
| | | formData.standardValue = ""; |
| | | formData.id = null; |
| | | formData.paramName = ""; |
| | | formData.paramType = ""; |
| | | formData.valueMode = "1"; |
| | | formData.unit = ""; |
| | | formData.remark = ""; |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | |
| | | const handleEdit = row => { |
| | | isEdit.value = true; |
| | | dialogTitle.value = "ç¼è¾åæ°"; |
| | | // å¡«å
è¡¨åæ°æ® |
| | | formData.parameterCode = row.parameterCode; |
| | | formData.parameterName = row.parameterName; |
| | | formData.parameterType2 = row.parameterType2 || "1"; |
| | | formData.parameterType = row.parameterType; |
| | | formData.parameterFormat = row.parameterFormat; |
| | | formData.parameterValue = row.parameterValue; |
| | | formData.standardValue = row.standardValue; |
| | | formData.unit = row.unit; |
| | | // å¡«å
è¡¨åæ°æ® - å°æ°åç±»å转æ¢ä¸ºå符串类å以å¹é
表åç»å® |
| | | formData.id = row.id; |
| | | formData.paramName = row.paramName || ""; |
| | | formData.paramType = row.paramType !== undefined ? String(row.paramType) : ""; |
| | | formData.valueMode = |
| | | row.valueMode !== undefined ? String(row.valueMode) : "1"; |
| | | formData.unit = row.unit || ""; |
| | | formData.remark = row.remark || ""; |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | // 注éæAPIè°ç¨ï¼ä½¿ç¨åæ°æ® |
| | | /*delParameter(row.id) |
| | | .then(res => { |
| | | ElMessage.success("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error("å é¤å¤±è´¥"); |
| | | });*/ |
| | | |
| | | // åæ°æ®æ¨¡æ |
| | | ElMessage.success("å 餿å"); |
| | | getList(); |
| | | // è°ç¨æ°æ¥å£ /baseParam/remove/{id} |
| | | removeBaseParam(row.id) |
| | | .then(res => { |
| | | ElMessage.success("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error("å é¤å¤±è´¥"); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | // åæ¶å é¤ |
| | |
| | | const handleSubmit = () => { |
| | | formRef.value.validate(valid => { |
| | | if (valid) { |
| | | // 注éæAPIè°ç¨ï¼ä½¿ç¨åæ°æ® |
| | | /*const api = isEdit.value ? updateParameter : addParameter; |
| | | api(formData) |
| | | .then(res => { |
| | | ElMessage.success(isEdit.value ? "ç¼è¾æå" : "æ°å¢æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error(isEdit.value ? "ç¼è¾å¤±è´¥" : "æ°å¢å¤±è´¥"); |
| | | });*/ |
| | | |
| | | // åæ°æ®æ¨¡æ |
| | | ElMessage.success(isEdit.value ? "ç¼è¾æå" : "æ°å¢æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | if (isEdit.value) { |
| | | // ç¼è¾ä½¿ç¨æ°æ¥å£ /baseParam/edit |
| | | editBaseParam(formData) |
| | | .then(res => { |
| | | ElMessage.success("ç¼è¾æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | // ElMessage.error("ç¼è¾å¤±è´¥"); |
| | | }); |
| | | } else { |
| | | // æ°å¢ä½¿ç¨æ°æ¥å£ /baseParam/add |
| | | addBaseParam(formData) |
| | | .then(res => { |
| | | ElMessage.success("æ°å¢æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error("æ°å¢å¤±è´¥"); |
| | | }); |
| | | } |
| | | } else { |
| | | return false; |
| | | } |
| | |
| | | onMounted(() => { |
| | | getDictTypes(); |
| | | getList(); |
| | | getProductTypes(); |
| | | // getProductTypes(); |
| | | }); |
| | | </script> |
| | | |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" title="éæ©äº§å" width="900px" destroy-on-close :close-on-click-modal="false"> |
| | | <el-form :inline="true" :model="query" class="mb-2"> |
| | | <el-form-item label="产å大类"> |
| | | <el-input v-model="query.productName" placeholder="è¾å
¥äº§å大类" clearable @keyup.enter="onSearch" /> |
| | | <el-dialog v-model="visible" |
| | | title="éæ©äº§å" |
| | | width="1000px" |
| | | destroy-on-close |
| | | :close-on-click-modal="false"> |
| | | <el-form :inline="true" |
| | | :model="query" |
| | | class="mb-2 search-form"> |
| | | <el-form-item label="产ååç§°"> |
| | | <el-input v-model="query.productName" |
| | | size="small" |
| | | placeholder="è¾å
¥äº§ååç§°" |
| | | clearable |
| | | @keyup.enter="onSearch" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="åå·åç§°"> |
| | | <el-input v-model="query.model" placeholder="è¾å
¥åå·åç§°" clearable @keyup.enter="onSearch" /> |
| | | <el-form-item label="è§æ ¼"> |
| | | <el-input v-model="query.model" |
| | | size="small" |
| | | placeholder="è¾å
¥è§æ ¼" |
| | | clearable |
| | | @keyup.enter="onSearch" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button type="primary" @click="onSearch">æç´¢</el-button> |
| | | <el-button @click="onReset">éç½®</el-button> |
| | | <el-form-item label="ç©æç¼ç "> |
| | | <el-input v-model="query.materialCode" |
| | | size="small" |
| | | placeholder="è¾å
¥ç©æç¼ç " |
| | | clearable |
| | | @keyup.enter="onSearch" /> |
| | | </el-form-item> |
| | | <el-form-item style="200px"> |
| | | <el-button type="primary" |
| | | size="small" |
| | | @click="onSearch">æç´¢</el-button> |
| | | <el-button size="small" |
| | | @click="onReset">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- å表 --> |
| | | <el-table ref="tableRef" v-loading="loading" :data="tableData" height="420" highlight-current-row row-key="id" |
| | | @selection-change="handleSelectionChange" @select="handleSelect"> |
| | | <el-table-column type="selection" width="55" /> |
| | | <el-table-column type="index" label="åºå·" width="60" /> |
| | | <el-table-column prop="productName" label="产å大类" min-width="160" /> |
| | | <el-table-column prop="model" label="åå·åç§°" min-width="200" /> |
| | | <el-table-column prop="unit" label="åä½" min-width="160" /> |
| | | <el-table ref="tableRef" |
| | | v-loading="loading" |
| | | :data="tableData" |
| | | height="420" |
| | | highlight-current-row |
| | | row-key="id" |
| | | @selection-change="handleSelectionChange" |
| | | @select="handleSelect"> |
| | | <el-table-column type="selection" |
| | | width="55" /> |
| | | <el-table-column type="index" |
| | | label="åºå·" |
| | | width="60" /> |
| | | <el-table-column prop="productName" |
| | | label="产ååç§°" |
| | | min-width="160" /> |
| | | <el-table-column prop="materialCode" |
| | | label="ç©æç¼ç " |
| | | min-width="200" /> |
| | | <el-table-column prop="model" |
| | | label="è§æ ¼" |
| | | min-width="200" /> |
| | | <el-table-column prop="unit" |
| | | label="åä½" |
| | | min-width="160" /> |
| | | </el-table> |
| | | |
| | | <div class="mt-3 flex justify-end"> |
| | | <el-pagination background layout="total, sizes, prev, pager, next, jumper" :total="total" |
| | | v-model:page-size="page.pageSize" v-model:current-page="page.pageNum" :page-sizes="[10, 20, 50, 100]" |
| | | @size-change="onPageChange" @current-change="onPageChange" /> |
| | | <el-pagination background |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :total="total" |
| | | v-model:page-size="page.pageSize" |
| | | v-model:current-page="page.pageNum" |
| | | :page-sizes="[10, 20, 50, 100]" |
| | | @size-change="onPageChange" |
| | | @current-change="onPageChange" /> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <el-button @click="close()">åæ¶</el-button> |
| | | <el-button type="primary" :disabled="multipleSelection.length === 0" @click="onConfirm"> |
| | | <el-button type="primary" |
| | | :disabled="multipleSelection.length === 0" |
| | | @click="onConfirm"> |
| | | ç¡®å® |
| | | </el-button> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { computed, onMounted, reactive, ref, watch, nextTick } from "vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import { productModelList } from '@/api/basicData/productModel' |
| | | import { computed, onMounted, reactive, ref, watch, nextTick } from "vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import { modelListPage } from "@/api/basicData/newProduct"; |
| | | |
| | | export type ProductRow = { |
| | | id: number; |
| | | productName: string; |
| | | model: string; |
| | | unit?: string; |
| | | }; |
| | | export type ProductRow = { |
| | | id: number; |
| | | model: string; |
| | | materialCode: string; |
| | | unit?: string; |
| | | productName?: string; |
| | | }; |
| | | |
| | | const props = defineProps<{ |
| | | modelValue: boolean; |
| | | single?: boolean; // æ¯å¦åªè½éæ©ä¸ä¸ªï¼é»è®¤falseï¼å¯éæ©å¤ä¸ªï¼ |
| | | }>(); |
| | | const props = defineProps<{ |
| | | modelValue: boolean; |
| | | single?: boolean; // æ¯å¦åªè½éæ©ä¸ä¸ªï¼é»è®¤falseï¼å¯éæ©å¤ä¸ªï¼ |
| | | }>(); |
| | | |
| | | const emit = defineEmits(['update:modelValue', 'confirm']); |
| | | const emit = defineEmits(["update:modelValue", "confirm"]); |
| | | |
| | | const visible = computed({ |
| | | get: () => props.modelValue, |
| | | set: (v) => emit("update:modelValue", v), |
| | | }); |
| | | const visible = computed({ |
| | | get: () => props.modelValue, |
| | | set: v => emit("update:modelValue", v), |
| | | }); |
| | | |
| | | const query = reactive({ |
| | | productName: "", |
| | | model: "", |
| | | }); |
| | | const query = reactive({ |
| | | model: "", |
| | | materialCode: "", |
| | | productName: "", |
| | | }); |
| | | |
| | | const page = reactive({ |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }); |
| | | const page = reactive({ |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }); |
| | | |
| | | const loading = ref(false); |
| | | const tableData = ref<ProductRow[]>([]); |
| | | const total = ref(0); |
| | | const multipleSelection = ref<ProductRow[]>([]); |
| | | const tableRef = ref(); |
| | | const loading = ref(false); |
| | | const tableData = ref<ProductRow[]>([]); |
| | | const total = ref(0); |
| | | const multipleSelection = ref<ProductRow[]>([]); |
| | | const tableRef = ref(); |
| | | |
| | | function close() { |
| | | visible.value = false; |
| | | } |
| | | |
| | | const handleSelectionChange = (val: ProductRow[]) => { |
| | | if (props.single && val.length > 1) { |
| | | // 妿éå¶ä¸ºåä¸ªéæ©ï¼åªä¿çæåä¸ä¸ªéä¸ç |
| | | const lastSelected = val[val.length - 1]; |
| | | multipleSelection.value = [lastSelected]; |
| | | // æ¸
ç©ºè¡¨æ ¼éä¸ç¶æï¼ç¶åéæ°é䏿åä¸ä¸ª |
| | | nextTick(() => { |
| | | if (tableRef.value) { |
| | | tableRef.value.clearSelection(); |
| | | tableRef.value.toggleRowSelection(lastSelected, true); |
| | | } |
| | | }); |
| | | } else { |
| | | multipleSelection.value = val; |
| | | function close() { |
| | | visible.value = false; |
| | | } |
| | | } |
| | | |
| | | // å¤çåä¸ªéæ© |
| | | const handleSelect = (selection: ProductRow[], row: ProductRow) => { |
| | | if (props.single) { |
| | | // 妿éå¶ä¸ºåä¸ªï¼æ¸
空å
¶ä»éæ©ï¼åªä¿çå½åè¡ |
| | | if (selection.includes(row)) { |
| | | // éä¸å½åè¡æ¶ï¼æ¸
空å
¶ä»éä¸ |
| | | multipleSelection.value = [row]; |
| | | const handleSelectionChange = (val: ProductRow[]) => { |
| | | if (props.single && val.length > 1) { |
| | | // 妿éå¶ä¸ºåä¸ªéæ©ï¼åªä¿çæåä¸ä¸ªéä¸ç |
| | | const lastSelected = val[val.length - 1]; |
| | | multipleSelection.value = [lastSelected]; |
| | | // æ¸
ç©ºè¡¨æ ¼éä¸ç¶æï¼ç¶åéæ°é䏿åä¸ä¸ª |
| | | nextTick(() => { |
| | | if (tableRef.value) { |
| | | tableData.value.forEach((item) => { |
| | | if (item.id !== row.id) { |
| | | tableRef.value.toggleRowSelection(item, false); |
| | | } |
| | | }); |
| | | tableRef.value.clearSelection(); |
| | | tableRef.value.toggleRowSelection(lastSelected, true); |
| | | } |
| | | }); |
| | | } else { |
| | | multipleSelection.value = val; |
| | | } |
| | | }; |
| | | |
| | | // å¤çåä¸ªéæ© |
| | | const handleSelect = (selection: ProductRow[], row: ProductRow) => { |
| | | if (props.single) { |
| | | // 妿éå¶ä¸ºåä¸ªï¼æ¸
空å
¶ä»éæ©ï¼åªä¿çå½åè¡ |
| | | if (selection.includes(row)) { |
| | | // éä¸å½åè¡æ¶ï¼æ¸
空å
¶ä»éä¸ |
| | | multipleSelection.value = [row]; |
| | | nextTick(() => { |
| | | if (tableRef.value) { |
| | | tableData.value.forEach(item => { |
| | | if (item.id !== row.id) { |
| | | tableRef.value.toggleRowSelection(item, false); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | function onSearch() { |
| | | page.pageNum = 1; |
| | | loadData(); |
| | | } |
| | | |
| | | function onReset() { |
| | | query.model = ""; |
| | | query.materialCode = ""; |
| | | query.productName = ""; |
| | | page.pageNum = 1; |
| | | loadData(); |
| | | } |
| | | |
| | | function onPageChange() { |
| | | loadData(); |
| | | } |
| | | |
| | | function onConfirm() { |
| | | if (multipleSelection.value.length === 0) { |
| | | ElMessage.warning("è¯·éæ©ä¸æ¡äº§å"); |
| | | return; |
| | | } |
| | | if (props.single && multipleSelection.value.length > 1) { |
| | | ElMessage.warning("åªè½éæ©ä¸ä¸ªäº§å"); |
| | | return; |
| | | } |
| | | emit( |
| | | "confirm", |
| | | props.single ? [multipleSelection.value[0]] : multipleSelection.value |
| | | ); |
| | | close(); |
| | | } |
| | | |
| | | async function loadData() { |
| | | loading.value = true; |
| | | try { |
| | | multipleSelection.value = []; // 翻页/æç´¢åæ¸
ç©ºéæ©æ´ç¬¦å颿 |
| | | const res: any = await modelListPage({ |
| | | model: query.model.trim(), |
| | | materialCode: query.materialCode.trim(), |
| | | productName: query.productName.trim(), |
| | | type: 1, |
| | | current: page.pageNum, |
| | | size: page.pageSize, |
| | | }); |
| | | tableData.value = res.data.records; |
| | | total.value = res.data.total; |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | } |
| | | } |
| | | |
| | | function onSearch() { |
| | | page.pageNum = 1; |
| | | loadData(); |
| | | } |
| | | // çå¬å¼¹çªæå¼ï¼éç½®éæ© |
| | | watch( |
| | | () => props.modelValue, |
| | | visible => { |
| | | if (visible) { |
| | | multipleSelection.value = []; |
| | | } |
| | | } |
| | | ); |
| | | |
| | | function onReset() { |
| | | query.productName = ""; |
| | | query.model = ""; |
| | | page.pageNum = 1; |
| | | loadData(); |
| | | } |
| | | |
| | | function onPageChange() { |
| | | loadData(); |
| | | } |
| | | |
| | | function onConfirm() { |
| | | if (multipleSelection.value.length === 0) { |
| | | ElMessage.warning("è¯·éæ©ä¸æ¡äº§å"); |
| | | return; |
| | | } |
| | | if (props.single && multipleSelection.value.length > 1) { |
| | | ElMessage.warning("åªè½éæ©ä¸ä¸ªäº§å"); |
| | | return; |
| | | } |
| | | emit("confirm", props.single ? [multipleSelection.value[0]] : multipleSelection.value); |
| | | close(); |
| | | } |
| | | |
| | | async function loadData() { |
| | | loading.value = true; |
| | | try { |
| | | multipleSelection.value = []; // 翻页/æç´¢åæ¸
ç©ºéæ©æ´ç¬¦å颿 |
| | | const res: any = await productModelList({ |
| | | productName: query.productName.trim(), |
| | | model: query.model.trim(), |
| | | current: page.pageNum, |
| | | size: page.pageSize, |
| | | }); |
| | | tableData.value = res.records; |
| | | total.value = res.total; |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | } |
| | | |
| | | // çå¬å¼¹çªæå¼ï¼éç½®éæ© |
| | | watch(() => props.modelValue, (visible) => { |
| | | if (visible) { |
| | | multipleSelection.value = []; |
| | | } |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | loadData() |
| | | }) |
| | | onMounted(() => { |
| | | loadData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .search-form { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .search-form .el-form-item { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .search-form .el-input { |
| | | width: 180px; |
| | | } |
| | | .el-form--inline .el-form-item { |
| | | margin-right: 5px; |
| | | } |
| | | .justify-end { |
| | | margin-top: 10px; |
| | | } |
| | | </style> |
| | |
| | | </el-button> |
| | | <ImportExcel :product-id="currentId" |
| | | @uploadSuccess="getModelList" /> |
| | | <el-input v-model="specification" |
| | | <el-input v-model="model" |
| | | placeholder="è§æ ¼åå·" |
| | | style="width: 150px" |
| | | clearable |
| | |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="产ååç§°ï¼" |
| | | prop="materialName"> |
| | | <el-input v-model="form.materialName" |
| | | prop="productName"> |
| | | <el-input v-model="form.productName" |
| | | placeholder="请è¾å
¥äº§ååç§°" |
| | | maxlength="20" |
| | | show-word-limit |
| | |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="åºæ¬åä½ï¼" |
| | | prop="baseUnit"> |
| | | <el-input v-model="form.baseUnit" |
| | | prop="unit"> |
| | | <el-input v-model="form.unit" |
| | | placeholder="请è¾å
¥åºæ¬åä½" |
| | | clearable |
| | | @keydown.enter.prevent /> |
| | |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="è§æ ¼åå·ï¼" |
| | | prop="specification"> |
| | | <el-input v-model="modelForm.specification" |
| | | prop="model"> |
| | | <el-input v-model="modelForm.model" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | clearable |
| | | @keydown.enter.prevent /> |
| | |
| | | const expandedKeys = ref([]); |
| | | const inventoryCategoryList = ref([]); |
| | | const materialTypeList = ref([]); |
| | | const specification = ref(""); |
| | | const model = ref(""); |
| | | const materialCode = ref(""); |
| | | |
| | | const getloadData = () => { |
| | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "materialName", |
| | | prop: "productName", |
| | | }, |
| | | { |
| | | label: "è§æ ¼", |
| | | prop: "specification", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "ç©æç¼ç ", |
| | |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "baseUnit", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | dataType: "action", |
| | |
| | | form: { |
| | | materialTypeId: null, |
| | | inventoryCategoryId: null, |
| | | materialName: "", |
| | | baseUnit: "", |
| | | productName: "", |
| | | unit: "", |
| | | remark: "", |
| | | }, |
| | | rules: { |
| | | materialName: [ |
| | | productName: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | { max: 20, message: "产ååç§°ä¸è½è¶
è¿20个å符", trigger: "blur" }, |
| | | ], |
| | | inventoryCategoryId: [ |
| | | { required: true, message: "è¯·éæ©", trigger: "change" }, |
| | | ], |
| | | baseUnit: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | unit: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | }, |
| | | modelForm: { |
| | | specification: "", |
| | | model: "", |
| | | supplyType: "", |
| | | materialCode: "", |
| | | id: null, |
| | | }, |
| | | modelRules: { |
| | | specification: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | model: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | supplyType: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | materialCode: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | }, |
| | |
| | | |
| | | treeLoad.value = true; |
| | | // è°ç¨ productTreeListQuery æ¥å£è¿è¡æç´¢ |
| | | productTreeListQuery({ materialName: search.value }) |
| | | productTreeListQuery({ productName: search.value }) |
| | | .then(res => { |
| | | // å¤çè¿åçæ°æ® |
| | | const newList = []; |
| | |
| | | item.children = (category.materialList || []).map(item => ({ |
| | | id: item.id, |
| | | isLeaf: true, |
| | | label: item.materialName, |
| | | label: item.productName, |
| | | inventoryCategoryId: item.inventoryCategoryId, |
| | | materialTypeId: item.materialTypeId, |
| | | remark: item.remark, |
| | | baseUnit: item.baseUnit, |
| | | unit: item.unit, |
| | | })); |
| | | break; |
| | | } |
| | |
| | | // children: (category.materialList || []).map(item => ({ |
| | | // id: item.id, |
| | | // isLeaf: true, |
| | | // label: item.materialName, |
| | | // label: item.productName, |
| | | // inventoryCategoryId: item.inventoryCategoryId, |
| | | // materialTypeId: item.materialTypeId, |
| | | // remark: item.remark, |
| | | // baseUnit: item.baseUnit, |
| | | // unit: item.unit, |
| | | // })), |
| | | // }; |
| | | // newList.push(categoryNode); |
| | |
| | | productDia.value = true; |
| | | // é置表å |
| | | form.value = { |
| | | materialName: "", |
| | | productName: "", |
| | | inventoryCategoryId: null, |
| | | baseUnit: "", |
| | | unit: "", |
| | | remark: "", |
| | | materialTypeId: null, |
| | | }; |
| | | console.log(data); |
| | | if (type === "edit" && data) { |
| | | // ç¼è¾æ¨¡å¼ï¼åå¡«æ°æ® |
| | | form.value.materialName = data.label || ""; |
| | | form.value.productName = data.label || ""; |
| | | form.value.inventoryCategoryId = data.inventoryCategoryId || null; |
| | | form.value.baseUnit = data.baseUnit || ""; |
| | | form.value.unit = data.unit || ""; |
| | | form.value.remark = data.remark || ""; |
| | | form.value.materialTypeId = data.materialTypeId || null; |
| | | form.value.id = data.id || null; |
| | |
| | | modelOperationType.value = type; |
| | | modelDia.value = true; |
| | | // éç½®ææå段 |
| | | modelForm.value.specification = ""; |
| | | modelForm.value.model = ""; |
| | | modelForm.value.supplyType = ""; |
| | | modelForm.value.id = null; |
| | | modelForm.value.materialCode = null; |
| | | |
| | | if (type === "edit" && data) { |
| | | // ç¼è¾æ¨¡å¼ï¼åå¡«æ°æ® |
| | | modelForm.value.specification = data.specification || ""; |
| | | modelForm.value.model = data.model || ""; |
| | | modelForm.value.supplyType = data.supplyType || ""; |
| | | modelForm.value.id = data.skuId || null; |
| | | modelForm.value.id = data.id || null; |
| | | modelForm.value.materialCode = data.materialCode || null; |
| | | } |
| | | }; |
| | |
| | | // const params = { |
| | | // materialTypeId: null, |
| | | // inventoryCategoryId: form.value.inventoryCategoryId, |
| | | // materialName: form.value.materialName, |
| | | // baseUnit: form.value.baseUnit, |
| | | // productName: form.value.productName, |
| | | // unit: form.value.unit, |
| | | // remark: form.value.remark, |
| | | // }; |
| | | |
| | |
| | | const children = materialList.map(item => ({ |
| | | id: item.id, |
| | | isLeaf: true, |
| | | label: item.materialName, |
| | | label: item.productName, |
| | | inventoryCategoryId: item.inventoryCategoryId, |
| | | materialTypeId: item.materialTypeId, |
| | | remark: item.remark, |
| | | baseUnit: item.baseUnit, |
| | | unit: item.unit, |
| | | })); |
| | | // æ´æ°èç¹çåèç¹ |
| | | val.children = children; |
| | |
| | | if (valid) { |
| | | // æå»ºæäº¤åæ° |
| | | const params = { |
| | | materialId: currentId.value, |
| | | specification: modelForm.value.specification, |
| | | productId: currentId.value, |
| | | model: modelForm.value.model, |
| | | materialCode: modelForm.value.materialCode, |
| | | supplyType: modelForm.value.supplyType, |
| | | }; |
| | |
| | | } |
| | | tableLoading.value = true; |
| | | modelListPage({ |
| | | materialId: currentId.value, |
| | | productId: currentId.value, |
| | | current: page.current, |
| | | size: page.size, |
| | | specification: specification.value, |
| | | model: model.value, |
| | | materialCode: materialCode.value, |
| | | }).then(res => { |
| | | console.log("res", res); |
| | |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map(item => item.skuId); |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="æ°å¢åºå" |
| | | width="800" |
| | | @close="closeModal" |
| | | > |
| | | <el-form label-width="140px" :model="formState" label-position="top" ref="formRef"> |
| | | <el-form-item |
| | | label="产ååç§°" |
| | | prop="productModelId" |
| | | :rules="[ |
| | | <el-dialog v-model="isShow" |
| | | title="æ°å¢åºå" |
| | | width="800" |
| | | @close="closeModal"> |
| | | <el-form label-width="140px" |
| | | :model="formState" |
| | | label-position="top" |
| | | ref="formRef"> |
| | | <el-form-item label="产ååç§°" |
| | | prop="productModelId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©äº§å', |
| | | trigger: 'change', |
| | | } |
| | | ]" |
| | | > |
| | | <el-button type="primary" @click="showProductSelectDialog = true"> |
| | | ]"> |
| | | <el-button type="primary" |
| | | @click="showProductSelectDialog = true"> |
| | | {{ formState.productName ? formState.productName : 'éæ©äº§å' }} |
| | | </el-button> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="è§æ ¼" |
| | | prop="productModelName" |
| | | > |
| | | <el-input v-model="formState.productModelName" disabled /> |
| | | <el-form-item label="è§æ ¼" |
| | | prop="productModelName"> |
| | | <el-input v-model="formState.productModelName" |
| | | disabled /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="åä½" |
| | | prop="unit" |
| | | > |
| | | <el-input v-model="formState.unit" disabled /> |
| | | <el-form-item label="åä½" |
| | | prop="unit"> |
| | | <el-input v-model="formState.unit" |
| | | disabled /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="åºåæ°é" |
| | | prop="qualitity" |
| | | > |
| | | <el-input-number v-model="formState.qualitity" :step="1" :min="1" style="width: 100%" /> |
| | | <el-form-item label="åºåæ°é" |
| | | prop="qualitity"> |
| | | <el-input-number v-model="formState.qualitity" |
| | | :step="1" |
| | | :min="1" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | v-if="type === 'qualified'" |
| | | label="åºåé¢è¦æ°é" |
| | | prop="warnNum" |
| | | > |
| | | <el-input-number v-model="formState.warnNum" :step="1" :min="0" :max="formState.qualitity" style="width: 100%" /> |
| | | <el-form-item v-if="type === 'qualified'" |
| | | label="åºåé¢è¦æ°é" |
| | | prop="warnNum"> |
| | | <el-input-number v-model="formState.warnNum" |
| | | :step="1" |
| | | :min="0" |
| | | :max="formState.qualitity" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input v-model="formState.remark" type="textarea" /> |
| | | <el-form-item label="夿³¨" |
| | | prop="remark"> |
| | | <el-input v-model="formState.remark" |
| | | type="textarea" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- 产åéæ©å¼¹çª --> |
| | | <ProductSelectDialog |
| | | v-model="showProductSelectDialog" |
| | | @confirm="handleProductSelect" |
| | | single |
| | | /> |
| | | <ProductSelectDialog v-model="showProductSelectDialog" |
| | | @confirm="handleProductSelect" |
| | | single /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="handleSubmit">确认</el-button> |
| | | <el-button type="primary" |
| | | @click="handleSubmit">确认</el-button> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, computed, getCurrentInstance} from "vue"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import {createStockInventory} from "@/api/inventoryManagement/stockInventory.js"; |
| | | import {createStockUnInventory} from "@/api/inventoryManagement/stockUninventory.js"; |
| | | import { ref, computed, getCurrentInstance } from "vue"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import { createStockInventory } from "@/api/inventoryManagement/stockInventory.js"; |
| | | import { createStockUnInventory } from "@/api/inventoryManagement/stockUninventory.js"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | |
| | | type: { |
| | | type: String, |
| | | required: true, |
| | | default: 'qualified', |
| | | }, |
| | | }); |
| | | type: { |
| | | type: String, |
| | | required: true, |
| | | default: "qualified", |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | const emit = defineEmits(["update:visible", "completed"]); |
| | | |
| | | // ååºå¼æ°æ®ï¼æ¿ä»£é项å¼ç dataï¼ |
| | | const formState = ref({ |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | unit: "", |
| | | qualitity: 0, |
| | | warnNum: 0, |
| | | remark: '', |
| | | }); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | }, |
| | | }); |
| | | |
| | | const showProductSelectDialog = ref(false); |
| | | |
| | | let { proxy } = getCurrentInstance() |
| | | |
| | | const closeModal = () => { |
| | | // éç½®è¡¨åæ°æ® |
| | | formState.value = { |
| | | // ååºå¼æ°æ®ï¼æ¿ä»£é项å¼ç dataï¼ |
| | | const formState = ref({ |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | description: '', |
| | | unit: "", |
| | | qualitity: 0, |
| | | warnNum: 0, |
| | | remark: "", |
| | | }); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit("update:visible", val); |
| | | }, |
| | | }); |
| | | |
| | | const showProductSelectDialog = ref(false); |
| | | |
| | | let { proxy } = getCurrentInstance(); |
| | | |
| | | const closeModal = () => { |
| | | // éç½®è¡¨åæ°æ® |
| | | formState.value = { |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | description: "", |
| | | }; |
| | | isShow.value = false; |
| | | }; |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | // 产åéæ©å¤ç |
| | | const handleProductSelect = async (products) => { |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | formState.value.productId = product.productId; |
| | | formState.value.productName = product.productName; |
| | | formState.value.productModelName = product.model; |
| | | formState.value.productModelId = product.id; |
| | | formState.value.unit = product.unit; |
| | | showProductSelectDialog.value = false; |
| | | // 触å表åéªè¯æ´æ° |
| | | proxy.$refs["formRef"]?.validateField('productModelId'); |
| | | } |
| | | }; |
| | | // 产åéæ©å¤ç |
| | | const handleProductSelect = async products => { |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | formState.value.productId = product.id; |
| | | formState.value.productName = product.productName; |
| | | formState.value.productModelName = product.model; |
| | | |
| | | const handleSubmit = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | // éªè¯æ¯å¦éæ©äºäº§ååè§æ ¼ |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©äº§å"); |
| | | return; |
| | | } |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©è§æ ¼"); |
| | | return; |
| | | } |
| | | if (props.type === 'qualified') { |
| | | createStockInventory(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit('completed'); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }) |
| | | } else { |
| | | createStockUnInventory(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit('completed'); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }) |
| | | } |
| | | |
| | | formState.value.productModelId = product.id; |
| | | formState.value.unit = product.unit; |
| | | showProductSelectDialog.value = false; |
| | | // 触å表åéªè¯æ´æ° |
| | | proxy.$refs["formRef"]?.validateField("productModelId"); |
| | | } |
| | | }) |
| | | }; |
| | | }; |
| | | |
| | | const handleSubmit = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | // éªè¯æ¯å¦éæ©äºäº§ååè§æ ¼ |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©äº§å"); |
| | | return; |
| | | } |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©è§æ ¼"); |
| | | return; |
| | | } |
| | | if (props.type === "qualified") { |
| | | createStockInventory(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit("completed"); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }); |
| | | } else { |
| | | createStockUnInventory(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit("completed"); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow, |
| | | }); |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow, |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="é¢ç¨" |
| | | width="800" |
| | | @close="closeModal" |
| | | > |
| | | <el-form label-width="140px" :model="formState" label-position="top" ref="formRef"> |
| | | <el-form-item |
| | | label="产ååç§°" |
| | | prop="productModelId" |
| | | :rules="[ |
| | | <el-dialog v-model="isShow" |
| | | title="é¢ç¨" |
| | | width="800" |
| | | @close="closeModal"> |
| | | <el-form label-width="140px" |
| | | :model="formState" |
| | | label-position="top" |
| | | ref="formRef"> |
| | | <el-form-item label="产ååç§°" |
| | | prop="productModelId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©äº§å', |
| | | trigger: 'change', |
| | | } |
| | | ]" |
| | | > |
| | | <el-button type="primary" @click="showProductSelectDialog = true" disabled> |
| | | ]"> |
| | | <el-button type="primary" |
| | | @click="showProductSelectDialog = true" |
| | | disabled> |
| | | {{ formState.productName ? formState.productName : 'éæ©äº§å' }} |
| | | </el-button> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="è§æ ¼" |
| | | prop="productModelName" |
| | | > |
| | | <el-input v-model="formState.model" disabled /> |
| | | <el-form-item label="è§æ ¼" |
| | | prop="productModelName"> |
| | | <el-input v-model="formState.model" |
| | | disabled /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="åä½" |
| | | prop="unit" |
| | | > |
| | | <el-input v-model="formState.unit" disabled /> |
| | | <el-form-item label="åä½" |
| | | prop="unit"> |
| | | <el-input v-model="formState.unit" |
| | | disabled /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="æ°é" |
| | | prop="qualitity" |
| | | > |
| | | <el-input-number v-model="formState.qualitity" :step="1" :min="1" :max="maxQuality" style="width: 100%" /> |
| | | <el-form-item label="æ°é" |
| | | prop="qualitity"> |
| | | <el-input-number v-model="formState.qualitity" |
| | | :step="1" |
| | | :min="1" |
| | | :max="maxQuality" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input v-model="formState.remark" type="textarea" /> |
| | | <el-form-item label="夿³¨" |
| | | prop="remark"> |
| | | <el-input v-model="formState.remark" |
| | | type="textarea" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- 产åéæ©å¼¹çª --> |
| | | <ProductSelectDialog |
| | | v-model="showProductSelectDialog" |
| | | @confirm="handleProductSelect" |
| | | single |
| | | /> |
| | | <ProductSelectDialog v-model="showProductSelectDialog" |
| | | @confirm="handleProductSelect" |
| | | single /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="handleSubmit">确认</el-button> |
| | | <el-button type="primary" |
| | | @click="handleSubmit">确认</el-button> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, computed, getCurrentInstance} from "vue"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import {subtractStockInventory} from "@/api/inventoryManagement/stockInventory.js"; |
| | | import {subtractStockUnInventory} from "@/api/inventoryManagement/stockUninventory.js"; |
| | | import { ref, computed, getCurrentInstance } from "vue"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import { subtractStockInventory } from "@/api/inventoryManagement/stockInventory.js"; |
| | | import { subtractStockUnInventory } from "@/api/inventoryManagement/stockUninventory.js"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | record: { |
| | | type: Object, |
| | | default: () => {}, |
| | | }, |
| | | type: { |
| | | type: String, |
| | | required: true, |
| | | default: 'qualified', |
| | | }, |
| | | }); |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | record: { |
| | | type: Object, |
| | | default: () => {}, |
| | | }, |
| | | type: { |
| | | type: String, |
| | | required: true, |
| | | default: "qualified", |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | const emit = defineEmits(["update:visible", "completed"]); |
| | | |
| | | onMounted(() => { |
| | | initFormData() |
| | | }) |
| | | onMounted(() => { |
| | | initFormData(); |
| | | }); |
| | | |
| | | const maxQuality = computed(() => { |
| | | return props.record.unLockedQuantity ? props.record.unLockedQuantity : 0; |
| | | }) |
| | | const maxQuality = computed(() => { |
| | | return props.record.unLockedQuantity ? props.record.unLockedQuantity : 0; |
| | | }); |
| | | |
| | | const initFormData = () => { |
| | | if (props.record) { |
| | | formState.value = { |
| | | ...props.record, |
| | | const initFormData = () => { |
| | | if (props.record) { |
| | | formState.value = { |
| | | ...props.record, |
| | | }; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // ååºå¼æ°æ®ï¼æ¿ä»£é项å¼ç dataï¼ |
| | | const formState = ref({ |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | productName: "", |
| | | model: "", |
| | | unit: "", |
| | | qualitity: 0, |
| | | remark: '', |
| | | }); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | }, |
| | | }); |
| | | |
| | | const showProductSelectDialog = ref(false); |
| | | |
| | | let { proxy } = getCurrentInstance() |
| | | |
| | | const closeModal = () => { |
| | | // éç½®è¡¨åæ°æ® |
| | | formState.value = { |
| | | // ååºå¼æ°æ®ï¼æ¿ä»£é项å¼ç dataï¼ |
| | | const formState = ref({ |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | description: '', |
| | | model: "", |
| | | unit: "", |
| | | qualitity: 0, |
| | | remark: "", |
| | | }); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit("update:visible", val); |
| | | }, |
| | | }); |
| | | |
| | | const showProductSelectDialog = ref(false); |
| | | |
| | | let { proxy } = getCurrentInstance(); |
| | | |
| | | const closeModal = () => { |
| | | // éç½®è¡¨åæ°æ® |
| | | formState.value = { |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | description: "", |
| | | }; |
| | | isShow.value = false; |
| | | }; |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | // 产åéæ©å¤ç |
| | | const handleProductSelect = async (products) => { |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | console.log(product) |
| | | formState.value.productId = product.productId; |
| | | formState.value.productName = product.productName; |
| | | formState.value.productModelName = product.model; |
| | | formState.value.productModelId = product.id; |
| | | formState.value.unit = product.unit; |
| | | showProductSelectDialog.value = false; |
| | | // 触å表åéªè¯æ´æ° |
| | | proxy.$refs["formRef"]?.validateField('productModelId'); |
| | | } |
| | | }; |
| | | |
| | | const handleSubmit = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | // éªè¯æ¯å¦éæ©äºäº§ååè§æ ¼ |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©äº§å"); |
| | | return; |
| | | } |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©è§æ ¼"); |
| | | return; |
| | | } |
| | | if (props.type === 'qualified') { |
| | | subtractStockInventory(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit('completed'); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }) |
| | | } else { |
| | | subtractStockUnInventory(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit('completed'); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }) |
| | | } |
| | | // 产åéæ©å¤ç |
| | | const handleProductSelect = async products => { |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | console.log(product); |
| | | formState.value.productId = product.id; |
| | | formState.value.productName = product.productName; |
| | | formState.value.productModelName = product.model; |
| | | formState.value.productModelId = product.id; |
| | | formState.value.unit = product.unit; |
| | | showProductSelectDialog.value = false; |
| | | // 触å表åéªè¯æ´æ° |
| | | proxy.$refs["formRef"]?.validateField("productModelId"); |
| | | } |
| | | }) |
| | | }; |
| | | }; |
| | | |
| | | const handleSubmit = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | // éªè¯æ¯å¦éæ©äºäº§ååè§æ ¼ |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©äº§å"); |
| | | return; |
| | | } |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©è§æ ¼"); |
| | | return; |
| | | } |
| | | if (props.type === "qualified") { |
| | | subtractStockInventory(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit("completed"); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }); |
| | | } else { |
| | | subtractStockUnInventory(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit("completed"); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow, |
| | | }); |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow, |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" :inline="true"> |
| | | <el-form-item label="è§æ ¼åç§°:"> |
| | | <el-input v-model="searchForm.model" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | <div class="route-header"> |
| | | <div class="add-route-btn" |
| | | @click="handleAddRoute"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon> |
| | | <span>æ°å¢å·¥èºè·¯çº¿</span> |
| | | </div> |
| | | </div> |
| | | <div class="route-card-list"> |
| | | <div v-for="route in routeList" |
| | | :key="route.id" |
| | | class="route-card"> |
| | | <div class="card-header"> |
| | | <div class="route-info"> |
| | | <span class="route-name"><el-icon style="margin-right: 8px;line-height: 30px;"> |
| | | <ScaleToOriginal /> |
| | | </el-icon>{{ route.routeName }}<el-tag style="margin-left: 8px" |
| | | :type="route.status == 1 ? 'warning' : 'success'">{{ route.status == 1 ? 'è稿' : 'æ¹å' }}</el-tag></span> |
| | | <span class="route-code">{{ route.routeCode }}</span> |
| | | </div> |
| | | <div class="route-actions"> |
| | | <el-button v-if="route.status === '1'" |
| | | link |
| | | type="success" |
| | | @click="handleApproveRoute(route)"> |
| | | <el-icon> |
| | | <Check /> |
| | | </el-icon> |
| | | æ¹å |
| | | </el-button> |
| | | <el-button v-if="route.status === '2'" |
| | | link |
| | | type="warning" |
| | | @click="handleRevokeApproveRoute(route)"> |
| | | <el-icon> |
| | | <Close /> |
| | | </el-icon> |
| | | æ¤éæ¹å |
| | | </el-button> |
| | | <el-button link |
| | | type="primary" |
| | | @click="handleEditRoute(route)"> |
| | | <el-icon> |
| | | <Edit /> |
| | | </el-icon> |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button link |
| | | type="danger" |
| | | @click="handleDeleteRoute(route)"> |
| | | <el-icon> |
| | | <Delete /> |
| | | </el-icon> |
| | | å é¤ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <div class="card-body"> |
| | | <div class="route-meta"> |
| | | <span class="meta-item"> |
| | | <el-icon> |
| | | <Box /> |
| | | </el-icon> |
| | | <span class="meta-label">产å:</span> |
| | | <span class="meta-value">{{ route.productName }} - {{ route.productModelName }}</span> |
| | | </span> |
| | | <span class="meta-item"> |
| | | <el-icon> |
| | | <Document /> |
| | | </el-icon> |
| | | <span class="meta-label">BOM:</span> |
| | | <span class="meta-value">{{ route.bomId || '-' }}</span> |
| | | </span> |
| | | <span class="meta-item"> |
| | | <el-icon> |
| | | <Document /> |
| | | </el-icon> |
| | | <span class="meta-label">路线æè¿°:</span> |
| | | <span class="meta-value">{{ route.routeDesc || 'ææ æè¿°' }}</span> |
| | | </span> |
| | | </div> |
| | | <div class="expand-btn-wrapper"> |
| | | <el-button class="expand-btn" |
| | | :class="{ expanded: route.expanded }" |
| | | type="primary" |
| | | text |
| | | @click="toggleExpand(route)"> |
| | | <span class="btn-text">{{ route.expanded ? 'æ¶èµ·å·¥åºè·¯çº¿' : 'å±å¼å·¥åºè·¯çº¿' }}</span> |
| | | <el-icon class="expand-icon"> |
| | | <component :is="route.expanded ? 'ArrowUp' : 'ArrowDown'" /> |
| | | </el-icon> |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <div v-if="route.expanded" |
| | | class="process-route"> |
| | | <div class="process-flow"> |
| | | <div v-for="(process, index) in route.processList" |
| | | :key="process.id" |
| | | class="process-flow-item" |
| | | draggable="true" |
| | | @dragstart="handleDragStart($event, index, route.id)" |
| | | @dragover="handleDragOver($event)" |
| | | @drop="handleDrop($event, index, route.id)" |
| | | @dragend="handleDragEnd"> |
| | | <div class="process-node" |
| | | :class="{ expanded: process.expanded }"> |
| | | <div class="process-node-header"> |
| | | <div class="process-number">{{ index + 1 }}</div> |
| | | <div class="process-actions"> |
| | | <el-button link |
| | | type="danger" |
| | | @click="handleDeleteProcess(route.id, process)"> |
| | | <el-icon> |
| | | <Delete /> |
| | | </el-icon> |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <div class="process-node-body"> |
| | | <div class="process-code">{{ process.processCode }}</div> |
| | | <div class="process-name">{{ process.processName }}</div> |
| | | <div class="process-desc">{{ process.processDesc || 'ææ æè¿°' }}</div> |
| | | </div> |
| | | <div class="process-node-footer"> |
| | | <!-- <el-tag size="small" |
| | | :type="process.status === '1' ? 'success' : 'info'"> |
| | | {{ process.status === '1' ? 'å¯ç¨' : 'åç¨' }} |
| | | </el-tag> --> |
| | | <el-button type="primary" |
| | | link |
| | | size="small" |
| | | @click="toggleProcessParams(process)"> |
| | | {{ process.expanded ? 'æ¶èµ·åæ°' : 'å±å¼åæ°' }} |
| | | ({{ process.paramList?.length || 0 }}) |
| | | </el-button> |
| | | </div> |
| | | <div v-if="process.expanded" |
| | | class="process-params-section"> |
| | | <div class="params-header"> |
| | | <span>åæ°å表</span> |
| | | <el-button type="primary" |
| | | link |
| | | size="small" |
| | | @click="handleAddParam(route.id, process)"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon>æ°å¢ |
| | | </el-button> |
| | | </div> |
| | | <div class="params-list"> |
| | | <div v-for="param in process.paramList" |
| | | :key="param.id" |
| | | class="param-item"> |
| | | <div class="param-info"> |
| | | <span class="param-code">{{ param.parameterCode }}</span> |
| | | <span class="param-name">{{ param.parameterName }}</span> |
| | | <!-- <el-tag size="small" |
| | | style="margin-right: 20px;" |
| | | :type="getParamTypeTag(param.parameterType)"> |
| | | {{ param.parameterType }} |
| | | </el-tag> --> |
| | | <span class="param-value">æ åå¼ï¼{{ param.standardValue }} {{ param.unit }}</span> |
| | | </div> |
| | | <div class="param-actions"> |
| | | <el-button link |
| | | type="primary" |
| | | size="small" |
| | | @click="handleEditParam(route.id, process, param)"> |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button link |
| | | type="danger" |
| | | size="small" |
| | | @click="handleDeleteParam(route.id, process, param)"> |
| | | å é¤ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <el-empty v-if="!process.paramList || process.paramList.length === 0" |
| | | description="ææ åæ°" |
| | | :image-size="50" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div v-if="index < route.processList.length - 1" |
| | | class="flow-arrow"> |
| | | <el-icon> |
| | | <Right /> |
| | | </el-icon> |
| | | </div> |
| | | </div> |
| | | <div class="add-process-node" |
| | | @click="handleSelectProcess(route, index)"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon> |
| | | <span>æ°å¢å·¥åº</span> |
| | | </div> |
| | | </div> |
| | | <el-empty v-if="!route.processList || route.processList.length === 0" |
| | | description="ææ å·¥åº" |
| | | :image-size="80" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- å·¥èºè·¯çº¿æ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="routeDialogVisible" |
| | | :title="isRouteEdit ? 'ç¼è¾å·¥èºè·¯çº¿' : 'æ°å¢å·¥èºè·¯çº¿'" |
| | | width="500px"> |
| | | <el-form :model="routeForm" |
| | | :rules="routeRules" |
| | | ref="routeFormRef" |
| | | label-width="120px"> |
| | | <el-form-item label="产ååç§°" |
| | | prop="productModelId"> |
| | | <el-button type="primary" |
| | | @click="showProductSelectDialog = true"> |
| | | {{ routeForm.productName && routeForm.productModelName |
| | | ? `${routeForm.productName} - ${routeForm.productModelName}` |
| | | : 'éæ©äº§å' }} |
| | | </el-button> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery">æç´¢</el-button> |
| | | <el-form-item label="BOM" |
| | | prop="bomId"> |
| | | <el-select v-model="routeForm.bomId" |
| | | placeholder="è¯·éæ©BOM" |
| | | clearable |
| | | :disabled="!routeForm.productModelId || bomOptions.length === 0" |
| | | style="width: 100%"> |
| | | <el-option v-for="item in bomOptions" |
| | | :key="item.id" |
| | | :label="item.bomNo || `BOM-${item.id}`" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="路线ç¼ç " |
| | | prop="routeCode"> |
| | | <el-input v-model="routeForm.routeCode" |
| | | placeholder="请è¾å
¥è·¯çº¿ç¼ç " /> |
| | | </el-form-item> |
| | | <el-form-item label="路线åç§°" |
| | | prop="routeName"> |
| | | <el-input v-model="routeForm.routeName" |
| | | placeholder="请è¾å
¥è·¯çº¿åç§°" /> |
| | | </el-form-item> |
| | | <el-form-item label="路线æè¿°" |
| | | prop="routeDesc"> |
| | | <el-input v-model="routeForm.routeDesc" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥è·¯çº¿æè¿°" /> |
| | | </el-form-item> |
| | | <!-- <el-form-item label="ç¶æ" |
| | | prop="status"> |
| | | <el-radio-group v-model="routeForm.status"> |
| | | <el-radio label="1">å¯ç¨</el-radio> |
| | | <el-radio label="0">åç¨</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> --> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="routeDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" |
| | | @click="handleRouteSubmit">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- 产åéæ©å¼¹çª --> |
| | | <ProductSelectDialog v-model="showProductSelectDialog" |
| | | @confirm="handleProductSelect" |
| | | single /> |
| | | <!-- å·¥åºæ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="processDialogVisible" |
| | | :title="isProcessEdit ? 'ç¼è¾å·¥åº' : 'æ°å¢å·¥åº'" |
| | | width="500px"> |
| | | <el-form :model="processForm" |
| | | :rules="processRules" |
| | | ref="processFormRef" |
| | | label-width="120px"> |
| | | <el-form-item label="å·¥åºç¼ç " |
| | | prop="processCode"> |
| | | <el-input v-model="processForm.processCode" |
| | | placeholder="请è¾å
¥å·¥åºç¼ç " /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥åºåç§°" |
| | | prop="processName"> |
| | | <el-input v-model="processForm.processName" |
| | | placeholder="请è¾å
¥å·¥åºåç§°" /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥åºæè¿°" |
| | | prop="processDesc"> |
| | | <el-input v-model="processForm.processDesc" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥å·¥åºæè¿°" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç¶æ" |
| | | prop="status"> |
| | | <el-radio-group v-model="processForm.status"> |
| | | <el-radio label="1">å¯ç¨</el-radio> |
| | | <el-radio label="0">åç¨</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="table_list"> |
| | | <div style="text-align: right" class="mb10"> |
| | | <el-button type="primary" @click="showNewModal">æ°å¢å·¥èºè·¯çº¿</el-button> |
| | | <el-button type="danger" @click="handleDelete" :disabled="selectedRows.length === 0" plain>å é¤å·¥èºè·¯çº¿</el-button> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="processDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" |
| | | @click="handleProcessSubmit">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- 鿩工åºå¯¹è¯æ¡ --> |
| | | <el-dialog v-model="selectProcessDialogVisible" |
| | | title="鿩工åº" |
| | | width="1000px"> |
| | | <div class="process-select-container"> |
| | | <!-- 左侧工åºå表 --> |
| | | <div class="process-list-area"> |
| | | <div class="area-title">å¯éå·¥åº</div> |
| | | <div class="search-box"> |
| | | <el-input v-model="processSearchKeyword" |
| | | placeholder="请è¾å
¥å·¥åºåç§°æç´¢" |
| | | clearable |
| | | size="small" |
| | | @input="handleProcessSearch"> |
| | | <template #prefix> |
| | | <el-icon> |
| | | <Search /> |
| | | </el-icon> |
| | | </template> |
| | | </el-input> |
| | | </div> |
| | | <el-table :data="filteredProcessList" |
| | | height="360" |
| | | border |
| | | highlight-current-row |
| | | @current-change="handleProcessSelect"> |
| | | <el-table-column prop="processCode" |
| | | label="å·¥åºç¼å·" |
| | | width="100" /> |
| | | <el-table-column prop="processName" |
| | | label="å·¥åºåç§°" /> |
| | | <el-table-column prop="processDesc" |
| | | label="å·¥åºæè¿°" /> |
| | | <el-table-column prop="status" |
| | | label="ç¶æ" |
| | | width="80"> |
| | | <template #default="scope"> |
| | | <el-tag size="small" |
| | | :type="scope.row.status === '1' ? 'success' : 'info'"> |
| | | {{ scope.row.status === '1' ? 'å¯ç¨' : 'åç¨' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | <!-- å³ä¾§å·¥åºè¯¦æ
--> |
| | | <div class="process-detail-area"> |
| | | <div class="area-title">å·¥åºè¯¦æ
</div> |
| | | <el-form v-if="selectedProcessItem" |
| | | :model="selectedProcessItem" |
| | | label-width="100px" |
| | | class="process-detail-form"> |
| | | <el-form-item label="å·¥åºç¼å·"> |
| | | <span class="detail-text">{{ selectedProcessItem.processCode }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥åºåç§°"> |
| | | <span class="detail-text">{{ selectedProcessItem.processName }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥åºæè¿°"> |
| | | <span class="detail-text">{{ selectedProcessItem.processDesc || '-' }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="ç¶æ"> |
| | | <el-tag size="small" |
| | | :type="selectedProcessItem.status === '1' ? 'success' : 'info'"> |
| | | {{ selectedProcessItem.status === '1' ? 'å¯ç¨' : 'åç¨' }} |
| | | </el-tag> |
| | | </el-form-item> |
| | | <el-form-item label="åæ°æ°é"> |
| | | <span class="detail-text">{{ selectedProcessItem.paramCount || 0 }}个</span> |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-empty v-else |
| | | description="请ä»å·¦ä¾§éæ©å·¥åº" /> |
| | | </div> |
| | | </div> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | /> |
| | | </div> |
| | | <new-process |
| | | v-if="isShowNewModal" |
| | | v-model:visible="isShowNewModal" |
| | | @completed="getList" |
| | | /> |
| | | |
| | | <edit-process |
| | | v-if="isShowEditModal" |
| | | v-model:visible="isShowEditModal" |
| | | :record="record" |
| | | @completed="getList" |
| | | /> |
| | | |
| | | <route-item-form |
| | | v-if="isShowItemModal" |
| | | v-model:visible="isShowItemModal" |
| | | :record="record" |
| | | @completed="getList" |
| | | /> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="selectProcessDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" |
| | | :disabled="!selectedProcessItem" |
| | | @click="handleProcessSelectSubmit">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- åæ°æ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="paramDialogVisible" |
| | | :title="isParamEdit ? 'ç¼è¾åæ°' : 'æ°å¢åæ°'" |
| | | width="500px"> |
| | | <el-form :model="paramForm" |
| | | :rules="paramRules" |
| | | ref="paramFormRef" |
| | | label-width="120px"> |
| | | <el-form-item label="åæ°ç¼å·" |
| | | prop="parameterCode"> |
| | | <el-input v-model="paramForm.parameterCode" |
| | | placeholder="请è¾å
¥åæ°ç¼å·" /> |
| | | </el-form-item> |
| | | <el-form-item label="åæ°åç§°" |
| | | prop="parameterName"> |
| | | <el-input v-model="paramForm.parameterName" |
| | | placeholder="请è¾å
¥åæ°åç§°" /> |
| | | </el-form-item> |
| | | <el-form-item label="åæ°æ¨¡å¼" |
| | | prop="parameterType2"> |
| | | <el-select v-model="paramForm.parameterType2" |
| | | placeholder="è¯·éæ©åæ°æ¨¡å¼"> |
| | | <el-option label="åå¼" |
| | | value="1" /> |
| | | <el-option label="åºé´" |
| | | value="2" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="åæ°ç±»å" |
| | | prop="parameterType"> |
| | | <el-select v-model="paramForm.parameterType" |
| | | @change="handleParamTypeChange" |
| | | placeholder="è¯·éæ©åæ°ç±»å"> |
| | | <el-option label="æ°å¼æ ¼å¼" |
| | | value="æ°å¼æ ¼å¼" /> |
| | | <el-option label="ææ¬æ ¼å¼" |
| | | value="ææ¬æ ¼å¼" /> |
| | | <el-option label="䏿é项" |
| | | value="䏿é项" /> |
| | | <el-option label="æ¶é´æ ¼å¼" |
| | | value="æ¶é´æ ¼å¼" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item v-if="paramForm.parameterType === '䏿é项'" |
| | | label="æ°æ®åå
¸" |
| | | prop="parameterFormat"> |
| | | <el-select v-model="paramForm.parameterFormat" |
| | | placeholder="è¯·éæ©æ°æ®åå
¸"> |
| | | <el-option v-for="item in dictTypes" |
| | | :key="item.dictType" |
| | | :label="item.dictName" |
| | | :value="item.dictType" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item v-else-if="paramForm.parameterType === 'æ¶é´æ ¼å¼'" |
| | | label="æ¶é´æ ¼å¼" |
| | | prop="parameterFormat"> |
| | | <el-select v-model="paramForm.parameterFormat" |
| | | placeholder="è¯·éæ©æ¶é´æ ¼å¼"> |
| | | <el-option label="YYYY-MM-DD HH:mm:ss" |
| | | value="YYYY-MM-DD HH:mm:ss" /> |
| | | <el-option label="YYYY-MM-DD" |
| | | value="YYYY-MM-DD" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item v-else |
| | | label="åæ°æ ¼å¼" |
| | | prop="parameterFormat"> |
| | | <el-input v-model="paramForm.parameterFormat" |
| | | placeholder="请è¾å
¥åæ°æ ¼å¼" /> |
| | | </el-form-item> |
| | | <el-form-item label="æ åå¼" |
| | | prop="standardValue"> |
| | | <el-input v-model="paramForm.standardValue" |
| | | placeholder="请è¾å
¥æ åå¼" /> |
| | | </el-form-item> |
| | | <el-form-item label="åä½" |
| | | prop="unit"> |
| | | <el-input v-model="paramForm.unit" |
| | | placeholder="请è¾å
¥åä½" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="paramDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" |
| | | @click="handleParamSubmit">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {onMounted, ref} from "vue"; |
| | | import NewProcess from "@/views/productionManagement/processRoute/New.vue"; |
| | | import EditProcess from "@/views/productionManagement/processRoute/Edit.vue"; |
| | | import RouteItemForm from "@/views/productionManagement/processRoute/ItemsForm.vue"; |
| | | import {listPage, del} from "@/api/productionManagement/processRoute.js"; |
| | | import { useRouter } from 'vue-router' |
| | | import { ref, reactive, getCurrentInstance } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { |
| | | Plus, |
| | | Edit, |
| | | Delete, |
| | | ArrowUp, |
| | | ArrowDown, |
| | | Right, |
| | | Search, |
| | | Check, |
| | | Close, |
| | | Box, |
| | | Document, |
| | | } from "@element-plus/icons-vue"; |
| | | import { listType } from "@/api/system/dict/type"; |
| | | import { getByModel } from "@/api/productionManagement/productBom.js"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | |
| | | const router = useRouter() |
| | | const data = reactive({ |
| | | searchForm: { |
| | | model: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "å·¥èºè·¯çº¿ç¼å·", |
| | | prop: "processRouteCode", |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | }, |
| | | { |
| | | label: "è§æ ¼åç§°", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "BOMç¼å·", |
| | | prop: "bomNo", |
| | | }, |
| | | { |
| | | label: "æè¿°", |
| | | prop: "description", |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | operation: [ |
| | | // å·¥èºè·¯çº¿å表 |
| | | const routeList = ref([]); |
| | | const dictTypes = ref([]); |
| | | |
| | | // è·åå
¨å±å®ä¾ |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | // 产åéæ©åBOMç¸å
³ |
| | | const showProductSelectDialog = ref(false); |
| | | const bomOptions = ref([]); |
| | | |
| | | // å·¥èºè·¯çº¿å¯¹è¯æ¡ |
| | | const routeDialogVisible = ref(false); |
| | | const isRouteEdit = ref(false); |
| | | const routeFormRef = ref(null); |
| | | const routeForm = reactive({ |
| | | id: null, |
| | | productModelId: null, |
| | | productName: "", |
| | | productModelName: "", |
| | | bomId: null, |
| | | routeCode: "", |
| | | routeName: "", |
| | | routeDesc: "", |
| | | status: "1", |
| | | }); |
| | | const routeRules = { |
| | | productModelId: [ |
| | | { required: true, message: "è¯·éæ©äº§å", trigger: "change" }, |
| | | ], |
| | | bomId: [{ required: true, message: "è¯·éæ©BOM", trigger: "change" }], |
| | | routeCode: [{ required: true, message: "请è¾å
¥è·¯çº¿ç¼ç ", trigger: "blur" }], |
| | | routeName: [{ required: true, message: "请è¾å
¥è·¯çº¿åç§°", trigger: "blur" }], |
| | | }; |
| | | |
| | | // å·¥åºå¯¹è¯æ¡ |
| | | const processDialogVisible = ref(false); |
| | | const isProcessEdit = ref(false); |
| | | const processFormRef = ref(null); |
| | | const currentRouteId = ref(null); |
| | | const processForm = reactive({ |
| | | id: null, |
| | | processCode: "", |
| | | processName: "", |
| | | processDesc: "", |
| | | status: "1", |
| | | }); |
| | | const processRules = { |
| | | processCode: [{ required: true, message: "请è¾å
¥å·¥åºç¼ç ", trigger: "blur" }], |
| | | processName: [{ required: true, message: "请è¾å
¥å·¥åºåç§°", trigger: "blur" }], |
| | | }; |
| | | |
| | | // 鿩工åºå¯¹è¯æ¡ |
| | | const selectProcessDialogVisible = ref(false); |
| | | const availableProcessList = ref([]); |
| | | const filteredProcessList = ref([]); |
| | | const selectedProcessItem = ref(null); |
| | | const processSearchKeyword = ref(""); |
| | | const currentRouteIndex = ref(null); |
| | | |
| | | // åæ°å¯¹è¯æ¡ |
| | | const paramDialogVisible = ref(false); |
| | | const isParamEdit = ref(false); |
| | | const paramFormRef = ref(null); |
| | | const currentProcessId = ref(null); |
| | | const paramForm = reactive({ |
| | | id: null, |
| | | parameterCode: "", |
| | | parameterName: "", |
| | | parameterType2: "1", |
| | | parameterType: "", |
| | | parameterFormat: "", |
| | | standardValue: "", |
| | | unit: "", |
| | | }); |
| | | const paramRules = { |
| | | parameterCode: [ |
| | | { required: true, message: "请è¾å
¥åæ°ç¼å·", trigger: "blur" }, |
| | | ], |
| | | parameterName: [ |
| | | { required: true, message: "请è¾å
¥åæ°åç§°", trigger: "blur" }, |
| | | ], |
| | | parameterType: [ |
| | | { required: true, message: "è¯·éæ©åæ°ç±»å", trigger: "change" }, |
| | | ], |
| | | }; |
| | | |
| | | // ææ½ç¸å
³ |
| | | const draggedItem = ref(null); |
| | | const draggedRouteId = ref(null); |
| | | |
| | | // è·åå·¥èºè·¯çº¿å表 |
| | | const getRouteList = () => { |
| | | routeList.value = [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | showEditModal(row); |
| | | } |
| | | id: 1, |
| | | productModelId: 1, |
| | | productName: "æ åç å", |
| | | productModelName: "3.5å", |
| | | bomId: 1, |
| | | routeCode: "ROUTE001", |
| | | routeName: "æ åç åç产线", |
| | | routeDesc: "æ åç åç产æµç¨", |
| | | status: "1", |
| | | expanded: false, |
| | | processList: [ |
| | | { |
| | | id: 1, |
| | | processCode: "PROC001", |
| | | processName: "åæé
æ¯", |
| | | processDesc: "åææé
æ¯å·¥åº", |
| | | status: "1", |
| | | expanded: false, |
| | | paramList: [ |
| | | { |
| | | id: 1, |
| | | parameterCode: "P001", |
| | | parameterName: "æ°´æ³¥æ¯ä¾", |
| | | parameterType2: "1", |
| | | parameterType: "æ°å¼æ ¼å¼", |
| | | parameterFormat: "", |
| | | standardValue: "30", |
| | | unit: "%", |
| | | }, |
| | | { |
| | | id: 2, |
| | | parameterCode: "P002", |
| | | parameterName: "ç æ¯ä¾", |
| | | parameterType2: "1", |
| | | parameterType: "æ°å¼æ ¼å¼", |
| | | parameterFormat: "", |
| | | standardValue: "60", |
| | | unit: "%", |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | id: 2, |
| | | processCode: "PROC002", |
| | | processName: "æ
ææ··å", |
| | | processDesc: "æ
ææ··åå·¥åº", |
| | | status: "1", |
| | | expanded: false, |
| | | paramList: [ |
| | | { |
| | | id: 3, |
| | | parameterCode: "P003", |
| | | parameterName: "æ
ææ¶é´", |
| | | parameterType2: "1", |
| | | parameterType: "æ°å¼æ ¼å¼", |
| | | parameterFormat: "", |
| | | standardValue: "5", |
| | | unit: "åé", |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | id: 3, |
| | | processCode: "PROC003", |
| | | processName: "æµçæå", |
| | | processDesc: "æµçæåå·¥åº", |
| | | status: "1", |
| | | expanded: false, |
| | | paramList: [], |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | name: "路线项ç®", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | showItemModal(row); |
| | | } |
| | | id: 2, |
| | | productModelId: 2, |
| | | productName: "æ¿æ", |
| | | productModelName: "5.0å", |
| | | bomId: 2, |
| | | routeCode: "ROUTE002", |
| | | routeName: "æ¿æç产线", |
| | | routeDesc: "æ¿æç产æµç¨", |
| | | status: "1", |
| | | expanded: false, |
| | | processList: [ |
| | | { |
| | | id: 4, |
| | | processCode: "PROC004", |
| | | processName: "åå²å å·¥", |
| | | processDesc: "åå²å 工工åº", |
| | | status: "1", |
| | | expanded: false, |
| | | paramList: [ |
| | | { |
| | | id: 4, |
| | | parameterCode: "P004", |
| | | parameterName: "åå²å°ºå¯¸", |
| | | parameterType2: "1", |
| | | parameterType: "ææ¬æ ¼å¼", |
| | | parameterFormat: "", |
| | | standardValue: "600x200x100", |
| | | unit: "mm", |
| | | }, |
| | | ], |
| | | }, |
| | | ], |
| | | }, |
| | | ]; |
| | | }; |
| | | |
| | | // å±å¼/æ¶èµ·å·¥èºè·¯çº¿ |
| | | const toggleExpand = route => { |
| | | route.expanded = !route.expanded; |
| | | }; |
| | | |
| | | // å±å¼/æ¶èµ·å·¥åºåæ° |
| | | const toggleProcessParams = process => { |
| | | process.expanded = !process.expanded; |
| | | }; |
| | | |
| | | // å·¥èºè·¯çº¿æä½ |
| | | const handleAddRoute = () => { |
| | | isRouteEdit.value = false; |
| | | routeForm.id = null; |
| | | routeForm.productModelId = null; |
| | | routeForm.productName = ""; |
| | | routeForm.productModelName = ""; |
| | | routeForm.bomId = null; |
| | | routeForm.routeCode = ""; |
| | | routeForm.routeName = ""; |
| | | routeForm.routeDesc = ""; |
| | | routeForm.status = "1"; |
| | | bomOptions.value = []; |
| | | routeDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleEditRoute = route => { |
| | | isRouteEdit.value = true; |
| | | routeForm.id = route.id; |
| | | routeForm.productModelId = route.productModelId; |
| | | routeForm.productName = route.productName; |
| | | routeForm.productModelName = route.productModelName; |
| | | routeForm.bomId = route.bomId; |
| | | routeForm.routeCode = route.routeCode; |
| | | routeForm.routeName = route.routeName; |
| | | routeForm.routeDesc = route.routeDesc; |
| | | routeForm.status = route.status; |
| | | routeDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleDeleteRoute = route => { |
| | | ElMessageBox.confirm("ç¡®å®è¦å é¤è¯¥å·¥èºè·¯çº¿åï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | ElMessage.success("å 餿å"); |
| | | getRouteList(); |
| | | }); |
| | | }; |
| | | |
| | | const handleRouteSubmit = () => { |
| | | routeFormRef.value.validate(valid => { |
| | | if (valid) { |
| | | ElMessage.success(isRouteEdit.value ? "ç¼è¾æå" : "æ°å¢æå"); |
| | | routeDialogVisible.value = false; |
| | | getRouteList(); |
| | | } |
| | | ] |
| | | } |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const isShowNewModal = ref(false); |
| | | const isShowEditModal = ref(false); |
| | | const isShowItemModal = ref(false); |
| | | const record = ref({}); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const { proxy } = getCurrentInstance() |
| | | }); |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | // 产åéæ©å¤ç |
| | | const handleProductSelect = async products => { |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | // å
æ¥è¯¢BOMå表ï¼å¿
éï¼ |
| | | try { |
| | | const res = await getByModel(product.id); |
| | | // å¤çè¿åçBOMæ°æ®ï¼å¯è½æ¯æ°ç»ã对象æå
å«dataåæ®µ |
| | | let bomList = []; |
| | | if (Array.isArray(res)) { |
| | | bomList = res; |
| | | } else if (res && res.data) { |
| | | bomList = Array.isArray(res.data) ? res.data : [res.data]; |
| | | } else if (res && typeof res === "object") { |
| | | bomList = [res]; |
| | | } |
| | | |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined |
| | | listPage(params).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records.map(item => ({ |
| | | ...item, |
| | | })); |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æå¼æ°å¢å¼¹æ¡ |
| | | const showNewModal = () => { |
| | | isShowNewModal.value = true |
| | | }; |
| | | |
| | | const showEditModal = (row) => { |
| | | isShowEditModal.value = true |
| | | record.value = row |
| | | }; |
| | | |
| | | const showItemModal = (row) => { |
| | | router.push({ |
| | | path: '/productionManagement/processRouteItem', |
| | | query: { |
| | | id: row.id, |
| | | processRouteCode: row.processRouteCode || '', |
| | | productName: row.productName || '', |
| | | model: row.model || '', |
| | | bomNo: row.bomNo || '', |
| | | description: row.description || '', |
| | | type: 'route', |
| | | if (bomList.length > 0) { |
| | | routeForm.productModelId = product.id; |
| | | routeForm.productName = product.productName; |
| | | routeForm.productModelName = product.model; |
| | | routeForm.bomId = undefined; // éç½®BOMéæ© |
| | | bomOptions.value = bomList; |
| | | showProductSelectDialog.value = false; |
| | | // 触å表åéªè¯æ´æ° |
| | | proxy.$refs["routeFormRef"]?.validateField("productModelId"); |
| | | } else { |
| | | proxy.$modal.msgError("è¯¥äº§åæ²¡æBOMï¼è¯·å
å建BOM"); |
| | | } |
| | | } catch (error) { |
| | | // 妿æ¥å£è¿å404æå
¶ä»é误ï¼è¯´ææ²¡æBOM |
| | | proxy.$modal.msgError("è¯¥äº§åæ²¡æBOMï¼è¯·å
å建BOM"); |
| | | } |
| | | } |
| | | }) |
| | | }; |
| | | }; |
| | | |
| | | // å é¤ |
| | | function handleDelete() { |
| | | const ids = selectedRows.value.map((item) => item.id); |
| | | proxy.$modal |
| | | .confirm('æ¯å¦ç¡®è®¤å é¤å·²å¾éçæ°æ®é¡¹ï¼') |
| | | .then(function () { |
| | | return del(ids); |
| | | }) |
| | | .then(() => { |
| | | getList(); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | }) |
| | | .catch(() => {}); |
| | | } |
| | | const handleApproveRoute = route => { |
| | | ElMessageBox.confirm("ç¡®å®è¦æ¹å该工èºè·¯çº¿åï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "info", |
| | | }).then(() => { |
| | | route.status = "2"; |
| | | ElMessage.success("æ¹åæå"); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | const handleRevokeApproveRoute = route => { |
| | | ElMessageBox.confirm("ç¡®å®è¦æ¤éæ¹å该工èºè·¯çº¿åï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | route.status = "1"; |
| | | ElMessage.success("æ¤éæ¹åæå"); |
| | | }); |
| | | }; |
| | | |
| | | // å·¥åºæä½ |
| | | const handleSelectProcess = (route, index) => { |
| | | currentRouteId.value = route.id; |
| | | currentRouteIndex.value = index; |
| | | // è·åå¯éå·¥åºå表ï¼åæ°æ®ï¼ |
| | | availableProcessList.value = [ |
| | | { |
| | | id: 1, |
| | | processCode: "PROC001", |
| | | processName: "åæé
æ¯", |
| | | processDesc: "åææé
æ¯å·¥åº", |
| | | status: "1", |
| | | paramCount: 3, |
| | | }, |
| | | { |
| | | id: 2, |
| | | processCode: "PROC002", |
| | | processName: "æ
ææ··å", |
| | | processDesc: "æ
ææ··åå·¥åº", |
| | | status: "1", |
| | | paramCount: 2, |
| | | }, |
| | | { |
| | | id: 3, |
| | | processCode: "PROC003", |
| | | processName: "æµçæå", |
| | | processDesc: "æµçæåå·¥åº", |
| | | status: "1", |
| | | paramCount: 4, |
| | | }, |
| | | { |
| | | id: 4, |
| | | processCode: "PROC004", |
| | | processName: "è¸åå
»æ¤", |
| | | processDesc: "è¸åå
»æ¤å·¥åº", |
| | | status: "0", |
| | | paramCount: 2, |
| | | }, |
| | | { |
| | | id: 5, |
| | | processCode: "PROC005", |
| | | processName: "åå²å å·¥", |
| | | processDesc: "åå²å 工工åº", |
| | | status: "1", |
| | | paramCount: 3, |
| | | }, |
| | | ]; |
| | | filteredProcessList.value = availableProcessList.value; |
| | | processSearchKeyword.value = ""; |
| | | selectedProcessItem.value = null; |
| | | selectProcessDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleEditProcess = (routeId, process) => { |
| | | currentRouteId.value = routeId; |
| | | isProcessEdit.value = true; |
| | | processForm.id = process.id; |
| | | processForm.processCode = process.processCode; |
| | | processForm.processName = process.processName; |
| | | processForm.processDesc = process.processDesc; |
| | | processForm.status = process.status; |
| | | processDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleDeleteProcess = (routeId, process) => { |
| | | ElMessageBox.confirm("ç¡®å®è¦å é¤è¯¥å·¥åºåï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | ElMessage.success("å 餿å"); |
| | | getRouteList(); |
| | | }); |
| | | }; |
| | | |
| | | const handleProcessSubmit = () => { |
| | | processFormRef.value.validate(valid => { |
| | | if (valid) { |
| | | ElMessage.success(isProcessEdit.value ? "ç¼è¾æå" : "æ°å¢æå"); |
| | | processDialogVisible.value = false; |
| | | getRouteList(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // 鿩工åºç¸å
³æ¹æ³ |
| | | const handleProcessSearch = () => { |
| | | const keyword = processSearchKeyword.value.trim().toLowerCase(); |
| | | if (!keyword) { |
| | | filteredProcessList.value = availableProcessList.value; |
| | | } else { |
| | | filteredProcessList.value = availableProcessList.value.filter(item => |
| | | item.processName.toLowerCase().includes(keyword) |
| | | ); |
| | | } |
| | | }; |
| | | |
| | | const handleProcessSelect = row => { |
| | | selectedProcessItem.value = row; |
| | | }; |
| | | |
| | | const handleProcessSelectSubmit = () => { |
| | | if (!selectedProcessItem.value) { |
| | | ElMessage.warning("请å
éæ©ä¸ä¸ªå·¥åº"); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥å·¥åºæ¯å¦å·²åå¨ |
| | | const route = routeList.value[currentRouteIndex.value]; |
| | | const exists = route.processList.some( |
| | | p => p.id === selectedProcessItem.value.id |
| | | ); |
| | | if (exists) { |
| | | ElMessage.warning("该工åºå·²åå¨äºå·¥èºè·¯çº¿ä¸"); |
| | | return; |
| | | } |
| | | |
| | | // æ·»å å·¥åºå°å·¥èºè·¯çº¿ |
| | | const newProcess = { |
| | | id: Date.now(), |
| | | processCode: selectedProcessItem.value.processCode, |
| | | processName: selectedProcessItem.value.processName, |
| | | processDesc: selectedProcessItem.value.processDesc, |
| | | status: selectedProcessItem.value.status, |
| | | paramList: [], |
| | | expanded: false, |
| | | }; |
| | | |
| | | route.processList.push(newProcess); |
| | | ElMessage.success("æ·»å å·¥åºæå"); |
| | | selectProcessDialogVisible.value = false; |
| | | }; |
| | | |
| | | // åæ°æä½ |
| | | const handleAddParam = (routeId, process) => { |
| | | currentRouteId.value = routeId; |
| | | currentProcessId.value = process.id; |
| | | isParamEdit.value = false; |
| | | paramForm.id = null; |
| | | paramForm.parameterCode = ""; |
| | | paramForm.parameterName = ""; |
| | | paramForm.parameterType2 = "1"; |
| | | paramForm.parameterType = ""; |
| | | paramForm.parameterFormat = ""; |
| | | paramForm.standardValue = ""; |
| | | paramForm.unit = ""; |
| | | paramDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleEditParam = (routeId, process, param) => { |
| | | currentRouteId.value = routeId; |
| | | currentProcessId.value = process.id; |
| | | isParamEdit.value = true; |
| | | paramForm.id = param.id; |
| | | paramForm.parameterCode = param.parameterCode; |
| | | paramForm.parameterName = param.parameterName; |
| | | paramForm.parameterType2 = param.parameterType2 || "1"; |
| | | paramForm.parameterType = param.parameterType; |
| | | paramForm.parameterFormat = param.parameterFormat; |
| | | paramForm.standardValue = param.standardValue; |
| | | paramForm.unit = param.unit; |
| | | paramDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleDeleteParam = (routeId, process, param) => { |
| | | ElMessageBox.confirm("ç¡®å®è¦å é¤è¯¥åæ°åï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | ElMessage.success("å 餿å"); |
| | | getRouteList(); |
| | | }); |
| | | }; |
| | | |
| | | const handleParamSubmit = () => { |
| | | paramFormRef.value.validate(valid => { |
| | | if (valid) { |
| | | ElMessage.success(isParamEdit.value ? "ç¼è¾æå" : "æ°å¢æå"); |
| | | paramDialogVisible.value = false; |
| | | getRouteList(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleParamTypeChange = () => { |
| | | if (paramForm.parameterType === "æ°å¼æ ¼å¼") { |
| | | paramForm.parameterFormat = "#.0000"; |
| | | } else if (paramForm.parameterType === "æ¶é´æ ¼å¼") { |
| | | paramForm.parameterFormat = "YYYY-MM-DD HH:mm:ss"; |
| | | } else { |
| | | paramForm.parameterFormat = ""; |
| | | } |
| | | }; |
| | | |
| | | const getParamTypeTag = type => { |
| | | const typeMap = { |
| | | æ°å¼æ ¼å¼: "primary", |
| | | ææ¬æ ¼å¼: "info", |
| | | 䏿é项: "warning", |
| | | æ¶é´æ ¼å¼: "success", |
| | | }; |
| | | return typeMap[type] || "default"; |
| | | }; |
| | | |
| | | // ææ½æåº |
| | | const handleDragStart = (event, index, routeId) => { |
| | | draggedItem.value = index; |
| | | draggedRouteId.value = routeId; |
| | | event.dataTransfer.effectAllowed = "move"; |
| | | }; |
| | | |
| | | const handleDragOver = event => { |
| | | event.preventDefault(); |
| | | event.dataTransfer.dropEffect = "move"; |
| | | }; |
| | | |
| | | const handleDrop = (event, dropIndex, routeId) => { |
| | | event.preventDefault(); |
| | | if (draggedItem.value === null || draggedItem.value === dropIndex) return; |
| | | |
| | | const route = routeList.value.find(r => r.id === routeId); |
| | | if (route && route.processList) { |
| | | const draggedProcess = route.processList[draggedItem.value]; |
| | | route.processList.splice(draggedItem.value, 1); |
| | | route.processList.splice(dropIndex, 0, draggedProcess); |
| | | ElMessage.success("æåºæå"); |
| | | } |
| | | }; |
| | | |
| | | const handleDragEnd = () => { |
| | | draggedItem.value = null; |
| | | draggedRouteId.value = null; |
| | | }; |
| | | |
| | | // è·åæ°æ®åå
¸ |
| | | const getDictTypes = () => { |
| | | listType({ pageNum: 1, pageSize: 1000 }).then(res => { |
| | | dictTypes.value = res.rows || []; |
| | | }); |
| | | }; |
| | | |
| | | getRouteList(); |
| | | getDictTypes(); |
| | | </script> |
| | | |
| | | <style scoped></style> |
| | | <style scoped lang="scss"> |
| | | .app-container { |
| | | padding: 20px; |
| | | background-color: #f0f2f5; |
| | | min-height: calc(100vh - 84px); |
| | | } |
| | | |
| | | .route-header { |
| | | margin-bottom: 20px; |
| | | |
| | | .add-route-btn { |
| | | width: 100%; |
| | | display: inline-flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | min-width: 120px; |
| | | height: 100px; |
| | | border: 2px dashed #dcdfe6; |
| | | border-radius: 12px; |
| | | background: #fafafa; |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | color: #909399; |
| | | padding: 0 20px; |
| | | |
| | | .el-icon { |
| | | font-size: 24px; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | span { |
| | | font-size: 13px; |
| | | } |
| | | |
| | | &:hover { |
| | | border-color: #409eff; |
| | | background: #ecf5ff; |
| | | color: #409eff; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .route-card-list { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .route-card { |
| | | background: #fff; |
| | | border-radius: 8px; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | overflow: hidden; |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 20px 40px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | background: #f8f9fa; |
| | | |
| | | .route-info { |
| | | display: flex; |
| | | // flex-direction: column; |
| | | // justify-content: center; |
| | | // items-align: center; |
| | | gap: 4px; |
| | | |
| | | .route-code { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | font-family: "Courier New", monospace; |
| | | line-height: 30px; |
| | | } |
| | | |
| | | .route-name { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | } |
| | | |
| | | .route-actions { |
| | | display: flex; |
| | | gap: 8px; |
| | | |
| | | // .el-button { |
| | | // color: #409eff; |
| | | // } |
| | | } |
| | | } |
| | | |
| | | .card-body { |
| | | padding: 16px 40px; |
| | | |
| | | .route-desc { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .route-meta { |
| | | display: flex; |
| | | gap: 24px; |
| | | margin-bottom: 12px; |
| | | padding: 10px 14px; |
| | | background: linear-gradient(135deg, #f5f7fa 0%, #e8ecf1 100%); |
| | | border-radius: 8px; |
| | | border-left: 3px solid #409eff; |
| | | |
| | | .meta-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | font-size: 13px; |
| | | margin-right: 40px; |
| | | |
| | | .el-icon { |
| | | font-size: 14px; |
| | | color: #409eff; |
| | | } |
| | | |
| | | .meta-label { |
| | | color: #909399; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .meta-value { |
| | | color: #303133; |
| | | font-weight: 600; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .expand-btn-wrapper { |
| | | display: flex; |
| | | justify-content: center; |
| | | margin-top: 8px; |
| | | |
| | | .expand-btn { |
| | | padding: 8px 20px; |
| | | border-radius: 20px; |
| | | background: linear-gradient(135deg, #ecf5ff 0%, #d9ecff 100%); |
| | | border: 1px solid #b3d8ff; |
| | | transition: all 0.3s ease; |
| | | |
| | | .btn-text { |
| | | font-size: 13px; |
| | | font-weight: 500; |
| | | color: #409eff; |
| | | margin-right: 6px; |
| | | } |
| | | |
| | | .expand-icon { |
| | | font-size: 14px; |
| | | color: #409eff; |
| | | transition: transform 0.3s ease; |
| | | } |
| | | |
| | | &:hover { |
| | | background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%); |
| | | border-color: #409eff; |
| | | box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3); |
| | | |
| | | .btn-text, |
| | | .expand-icon { |
| | | color: #fff; |
| | | } |
| | | } |
| | | |
| | | &.expanded { |
| | | background: linear-gradient(135deg, #f0f9eb 0%, #e1f3d8 100%); |
| | | border-color: #a5d69a; |
| | | |
| | | .btn-text, |
| | | .expand-icon { |
| | | color: #67c23a; |
| | | } |
| | | |
| | | &:hover { |
| | | background: linear-gradient(135deg, #67c23a 0%, #85ce61 100%); |
| | | border-color: #67c23a; |
| | | box-shadow: 0 4px 12px rgba(103, 194, 58, 0.3); |
| | | |
| | | .btn-text, |
| | | .expand-icon { |
| | | color: #fff; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .process-route { |
| | | padding: 0 20px 20px; |
| | | background: #f5f7fa; |
| | | border-top: 1px solid #ebeef5; |
| | | |
| | | .process-flow { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | gap: 8px; |
| | | padding: 20px 0; |
| | | overflow-x: auto; |
| | | overflow-y: hidden; |
| | | |
| | | .process-flow-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | |
| | | .process-node { |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | padding: 16px; |
| | | border: 2px solid #ebeef5; |
| | | cursor: move; |
| | | transition: all 0.3s ease; |
| | | // min-width: 180px; |
| | | // max-width: 220px; |
| | | width: 300px; |
| | | |
| | | &.expanded { |
| | | width: 400px; |
| | | } |
| | | |
| | | &:hover { |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| | | transform: translateY(-2px); |
| | | border-color: #409eff; |
| | | } |
| | | |
| | | &:active { |
| | | cursor: grabbing; |
| | | } |
| | | |
| | | .process-node-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 12px; |
| | | |
| | | .process-number { |
| | | width: 28px; |
| | | height: 28px; |
| | | border-radius: 50%; |
| | | background: #409eff; |
| | | color: #ffffff; |
| | | font-size: 12px; |
| | | font-weight: 600; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .process-actions { |
| | | display: flex; |
| | | gap: 4px; |
| | | } |
| | | } |
| | | |
| | | .process-node-body { |
| | | text-align: center; |
| | | margin-bottom: 12px; |
| | | |
| | | .process-code { |
| | | font-size: 11px; |
| | | color: #909399; |
| | | font-family: "Courier New", monospace; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .process-name { |
| | | font-size: 15px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | margin-bottom: 6px; |
| | | } |
| | | |
| | | .process-desc { |
| | | font-size: 12px; |
| | | color: #606266; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | display: -webkit-box; |
| | | -webkit-line-clamp: 2; |
| | | -webkit-box-orient: vertical; |
| | | } |
| | | } |
| | | |
| | | .process-node-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | padding-top: 10px; |
| | | border-top: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .process-params-section { |
| | | margin-top: 12px; |
| | | padding-top: 12px; |
| | | border-top: 1px solid #ebeef5; |
| | | |
| | | .params-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 8px; |
| | | font-size: 13px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .params-list { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 6px; |
| | | max-height: 200px; |
| | | overflow-y: auto; |
| | | |
| | | .param-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 6px 8px; |
| | | background: #fafafa; |
| | | border-radius: 4px; |
| | | border-left: 2px solid #409eff; |
| | | font-size: 12px; |
| | | |
| | | .param-info { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | gap: 6px; |
| | | flex: 1; |
| | | min-width: 0; |
| | | |
| | | .param-code { |
| | | font-size: 11px; |
| | | color: #e6a23c; |
| | | font-family: "Courier New", monospace; |
| | | margin-right: 20px; |
| | | } |
| | | |
| | | .param-name { |
| | | font-size: 12px; |
| | | color: #303133; |
| | | font-weight: 500; |
| | | margin-right: 20px; |
| | | } |
| | | |
| | | .param-value { |
| | | font-size: 11px; |
| | | color: #606266; |
| | | } |
| | | } |
| | | |
| | | .param-actions { |
| | | display: flex; |
| | | gap: 4px; |
| | | flex-shrink: 0; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .flow-arrow { |
| | | display: flex; |
| | | align-items: center; |
| | | color: #c0c4cc; |
| | | font-size: 24px; |
| | | padding: 0 4px; |
| | | |
| | | .el-icon { |
| | | font-size: 20px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .add-process-node { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | min-width: 100px; |
| | | height: 175px; |
| | | border: 2px dashed #dcdfe6; |
| | | border-radius: 12px; |
| | | background: #fafafa; |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | color: #909399; |
| | | // margin-left: 10px; |
| | | |
| | | .el-icon { |
| | | font-size: 24px; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | span { |
| | | font-size: 13px; |
| | | } |
| | | |
| | | &:hover { |
| | | border-color: #409eff; |
| | | background: #ecf5ff; |
| | | color: #409eff; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // ææ½æ¶çæ ·å¼ |
| | | .process-flow-item.dragging { |
| | | opacity: 0.5; |
| | | transform: scale(0.98); |
| | | } |
| | | |
| | | // 鿩工åºå¯¹è¯æ¡æ ·å¼ |
| | | .process-select-container { |
| | | display: flex; |
| | | gap: 20px; |
| | | height: 450px; |
| | | |
| | | .process-list-area { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .area-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | margin-bottom: 12px; |
| | | padding-bottom: 8px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .search-box { |
| | | margin-bottom: 12px; |
| | | |
| | | .el-input { |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .process-detail-area { |
| | | width: 380px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | background: #f5f7fa; |
| | | border-radius: 8px; |
| | | padding: 16px; |
| | | |
| | | .area-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | margin-bottom: 16px; |
| | | padding-bottom: 8px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .process-detail-form { |
| | | .el-form-item { |
| | | margin-bottom: 12px; |
| | | |
| | | .el-form-item__label { |
| | | color: #606266; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | |
| | | .detail-text { |
| | | color: #303133; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | </el-table> |
| | | <product-select-dialog v-if="dataValue.showProductDialog" |
| | | v-model:model-value="dataValue.showProductDialog" |
| | | single |
| | | @confirm="handleProduct" /> |
| | | </div> |
| | | </template> |
| | |
| | | |
| | | // æ ¡éªå½æ° |
| | | const validateItem = (item: any, isTopLevel = false) => { |
| | | console.log(item, "item"); |
| | | // æ ¡éªå½å项çå¿
å¡«åæ®µ |
| | | if (!item.model) { |
| | | ElMessage.error("è¯·éæ©è§æ ¼"); |
| | |
| | | @click="cancelEdit" |
| | | style="margin-bottom: 10px">åæ¶ |
| | | </el-button> |
| | | |
| | | <el-table |
| | | :data="tableData" |
| | | border |
| | | :preserve-expanded-content="false" |
| | | style="width: 100%" |
| | | > |
| | | <el-table :data="tableData" |
| | | border |
| | | :preserve-expanded-content="false" |
| | | style="width: 100%"> |
| | | <el-table-column type="expand"> |
| | | <template #default="props"> |
| | | <el-form ref="form" |
| | |
| | | </el-form> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="产åç¼ç " prop="productCode" /> |
| | | <el-table-column label="产ååç§°" prop="productName" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="model" /> |
| | | <el-table-column label="åä½" prop="unit" /> |
| | | <el-table-column label="产åç¼ç " |
| | | prop="productCode" /> |
| | | <el-table-column label="产ååç§°" |
| | | prop="productName" /> |
| | | <el-table-column label="è§æ ¼åå·" |
| | | prop="model" /> |
| | | <el-table-column label="åä½" |
| | | prop="unit" /> |
| | | </el-table> |
| | | |
| | | <product-select-dialog v-if="dataValue.showProductDialog" |
| | | v-model:model-value="dataValue.showProductDialog" |
| | | single |
| | | @confirm="handleProduct" /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | |
| | | model: props.record.model, |
| | | unit: props.record.unit, |
| | | productCode: props.record.productCode, |
| | | } |
| | | ] |
| | | }, |
| | | ]; |
| | | |
| | | const openDialog = index => { |
| | | dataValue.currentRowIndex = index; |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div style="text-align: right; margin-bottom: 10px;"> |
| | | <el-button type="info" plain icon="Upload" @click="handleImport" |
| | | v-hasPermi="['product:bom:import']">导å
¥</el-button> |
| | | <el-button type="warning" plain icon="Download" @click="handleExport" :disabled="selectedRows.length !== 1" |
| | | v-hasPermi="['product:bom:export']">导åº</el-button> |
| | | <el-button type="primary" @click="handleAdd">æ°å¢</el-button> |
| | | <el-button type="danger" plain @click="handleBatchDelete" :disabled="selectedRows.length === 0">å é¤</el-button> |
| | | <el-button type="info" |
| | | plain |
| | | icon="Upload" |
| | | @click="handleImport" |
| | | v-hasPermi="['product:bom:import']">导å
¥</el-button> |
| | | <el-button type="warning" |
| | | plain |
| | | icon="Download" |
| | | @click="handleExport" |
| | | :disabled="selectedRows.length !== 1" |
| | | v-hasPermi="['product:bom:export']">导åº</el-button> |
| | | <el-button type="primary" |
| | | @click="handleAdd">æ°å¢</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleBatchDelete" |
| | | :disabled="selectedRows.length === 0">å é¤</el-button> |
| | | </div> |
| | | <PIMTable rowKey="id" :column="tableColumn" :tableData="tableData" :page="page" :isSelection="true" |
| | | @selection-change="handleSelectionChange" :tableLoading="tableLoading" @pagination="pagination"> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination"> |
| | | <template #detail="{ row }"> |
| | | <el-button type="primary" text @click="showDetail(row)">{{ row.bomNo }} |
| | | <el-button type="primary" |
| | | text |
| | | @click="showDetail(row)">{{ row.bomNo }} |
| | | </el-button> |
| | | </template> |
| | | </PIMTable> |
| | | <StructureEdit v-if="showEdit" v-model:show-model="showEdit" :record="currentRow" /> |
| | | |
| | | <StructureEdit v-if="showEdit" |
| | | v-model:show-model="showEdit" |
| | | :record="currentRow" /> |
| | | <!-- æ°å¢/ç¼è¾å¼¹çª --> |
| | | <el-dialog v-model="dialogVisible" :title="operationType === 'add' ? 'æ°å¢BOM' : 'ç¼è¾BOM'" width="600px" |
| | | @close="closeDialog"> |
| | | <el-form ref="formRef" :model="form" :rules="rules" label-width="120px"> |
| | | <el-form-item label="产ååç§°" prop="productModelId"> |
| | | <el-button type="primary" @click="showProductSelectDialog = true"> |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="operationType === 'add' ? 'æ°å¢BOM' : 'ç¼è¾BOM'" |
| | | width="600px" |
| | | @close="closeDialog"> |
| | | <el-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="120px"> |
| | | <el-form-item label="产ååç§°" |
| | | prop="productModelId"> |
| | | <el-button type="primary" |
| | | @click="showProductSelectDialog = true"> |
| | | {{ form.productName || 'éæ©äº§å' }} |
| | | </el-button> |
| | | </el-form-item> |
| | | <el-form-item label="çæ¬å·" prop="version"> |
| | | <el-input v-model="form.version" placeholder="请è¾å
¥çæ¬å·" clearable /> |
| | | <el-form-item label="çæ¬å·" |
| | | prop="version"> |
| | | <el-input v-model="form.version" |
| | | placeholder="请è¾å
¥çæ¬å·" |
| | | clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请è¾å
¥å¤æ³¨" clearable /> |
| | | <el-form-item label="夿³¨" |
| | | prop="remark"> |
| | | <el-input v-model="form.remark" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥å¤æ³¨" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="closeDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleSubmit">ç¡®å®</el-button> |
| | | <el-button type="primary" |
| | | @click="handleSubmit">ç¡®å®</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 产åéæ©å¼¹çª --> |
| | | <ProductSelectDialog v-model="showProductSelectDialog" @confirm="handleProductSelect" single /> |
| | | |
| | | <ProductSelectDialog v-model="showProductSelectDialog" |
| | | @confirm="handleProductSelect" |
| | | single /> |
| | | <!-- BOM导å
¥å¯¹è¯æ¡ --> |
| | | <ImportDialog ref="uploadRef" v-model="upload.open" :title="upload.title" :action="upload.url" |
| | | :headers="upload.headers" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" |
| | | :on-success="handleFileSuccess" :show-download-template="true" @confirm="submitFileForm" |
| | | @download-template="handleDownloadTemplate" @close="handleImportClose" /> |
| | | <ImportDialog ref="uploadRef" |
| | | v-model="upload.open" |
| | | :title="upload.title" |
| | | :action="upload.url" |
| | | :headers="upload.headers" |
| | | :disabled="upload.isUploading" |
| | | :on-progress="handleFileUploadProgress" |
| | | :on-success="handleFileSuccess" |
| | | :show-download-template="true" |
| | | @confirm="submitFileForm" |
| | | @download-template="handleDownloadTemplate" |
| | | @close="handleImportClose" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, toRefs, onMounted, getCurrentInstance, defineAsyncComponent } from "vue"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import { listPage, add, update, batchDelete, exportBom, downloadTemplate } from "@/api/productionManagement/productBom.js"; |
| | | import { useRouter } from 'vue-router' |
| | | import { ElMessageBox } from 'element-plus' |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import ImportDialog from "@/components/Dialog/ImportDialog.vue"; |
| | | import { |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | onMounted, |
| | | getCurrentInstance, |
| | | defineAsyncComponent, |
| | | } from "vue"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import { |
| | | listPage, |
| | | add, |
| | | update, |
| | | batchDelete, |
| | | exportBom, |
| | | downloadTemplate, |
| | | } from "@/api/productionManagement/productBom.js"; |
| | | import { useRouter } from "vue-router"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import ImportDialog from "@/components/Dialog/ImportDialog.vue"; |
| | | |
| | | const router = useRouter() |
| | | const { proxy } = getCurrentInstance() |
| | | const StructureEdit = defineAsyncComponent(() => import('@/views/productionManagement/productStructure/StructureEdit.vue')) |
| | | const router = useRouter(); |
| | | const { proxy } = getCurrentInstance(); |
| | | const StructureEdit = defineAsyncComponent(() => |
| | | import("@/views/productionManagement/productStructure/StructureEdit.vue") |
| | | ); |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "BOMç¼å·", |
| | | prop: "bomNo", |
| | | dataType: 'slot', |
| | | slot: "detail", |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "BOMç¼å·", |
| | | prop: "bomNo", |
| | | dataType: "slot", |
| | | slot: "detail", |
| | | minWidth: 140, |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | |
| | | minWidth: 160 |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "productModelName", |
| | | minWidth: 140 |
| | | }, |
| | | { |
| | | label: "çæ¬å·", |
| | | prop: "version", |
| | | width: 100 |
| | | }, |
| | | { |
| | | label: "夿³¨", |
| | | prop: "remark", |
| | | minWidth: 160 |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 150, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | handleEdit(row) |
| | | } |
| | | }, |
| | | { |
| | | name: "å é¤", |
| | | type: "danger", |
| | | link: true, |
| | | clickFun: (row) => { |
| | | handleDelete(row) |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | ]); |
| | | minWidth: 160, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "productModelName", |
| | | minWidth: 140, |
| | | }, |
| | | { |
| | | label: "çæ¬å·", |
| | | prop: "version", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "夿³¨", |
| | | prop: "remark", |
| | | minWidth: 160, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 150, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: row => { |
| | | handleEdit(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "å é¤", |
| | | type: "danger", |
| | | link: true, |
| | | clickFun: row => { |
| | | handleDelete(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const showEdit = ref(false); |
| | | const selectedRows = ref([]); |
| | | const currentRow = ref({}); |
| | | const dialogVisible = ref(false); |
| | | const operationType = ref('add'); // add | edit |
| | | const formRef = ref(null); |
| | | const showProductSelectDialog = ref(false); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const showEdit = ref(false); |
| | | const selectedRows = ref([]); |
| | | const currentRow = ref({}); |
| | | const dialogVisible = ref(false); |
| | | const operationType = ref("add"); // add | edit |
| | | const formRef = ref(null); |
| | | const showProductSelectDialog = ref(false); |
| | | |
| | | // BOM导å
¥åæ° |
| | | const upload = reactive({ |
| | | // æ¯å¦æ¾ç¤ºå¼¹åºå±ï¼BOM导å
¥ï¼ |
| | | open: false, |
| | | // å¼¹åºå±æ é¢ï¼BOM导å
¥ï¼ |
| | | title: "", |
| | | // æ¯å¦ç¦ç¨ä¸ä¼ |
| | | isUploading: false, |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/productBom/uploadBom" |
| | | }); |
| | | |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | id: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | productModelId: "", |
| | | remark: "", |
| | | version: "" |
| | | }, |
| | | rules: { |
| | | productModelId: [{ required: true, message: "è¯·éæ©äº§å", trigger: "change" }], |
| | | version: [{ required: true, message: "请è¾å
¥çæ¬å·", trigger: "blur" }] |
| | | } |
| | | }); |
| | | |
| | | const { form, rules } = toRefs(data); |
| | | |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // å页 |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listPage({ |
| | | current: page.current, |
| | | size: page.size, |
| | | }) |
| | | .then((res) => { |
| | | const records = res?.data?.records || []; |
| | | tableData.value = records; |
| | | page.total = res?.data?.total || 0; |
| | | }) |
| | | .catch((err) => { |
| | | console.error("è·åå表失败ï¼", err); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // æ°å¢ |
| | | const handleAdd = () => { |
| | | operationType.value = 'add'; |
| | | Object.assign(form.value, { |
| | | id: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | productModelId: "", |
| | | remark: "", |
| | | version: "" |
| | | // BOM导å
¥åæ° |
| | | const upload = reactive({ |
| | | // æ¯å¦æ¾ç¤ºå¼¹åºå±ï¼BOM导å
¥ï¼ |
| | | open: false, |
| | | // å¼¹åºå±æ é¢ï¼BOM导å
¥ï¼ |
| | | title: "", |
| | | // æ¯å¦ç¦ç¨ä¸ä¼ |
| | | isUploading: false, |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/productBom/uploadBom", |
| | | }); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // ç¼è¾ |
| | | const handleEdit = (row) => { |
| | | operationType.value = 'edit'; |
| | | Object.assign(form.value, { |
| | | id: row.id, |
| | | productName: row.productName || "", |
| | | productModelName: row.productModelName || "", |
| | | productModelId: row.productModelId || "", |
| | | remark: row.remark || "", |
| | | version: row.version || "" |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // å é¤ï¼åæ¡ï¼ |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm('确认å é¤è¯¥BOMï¼', 'æç¤º', { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }) |
| | | .then(() => { |
| | | batchDelete([row.id]) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess('å 餿å'); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError('å é¤å¤±è´¥'); |
| | | }); |
| | | }) |
| | | .catch(() => { }); |
| | | }; |
| | | |
| | | // æ¹éå é¤ |
| | | const handleBatchDelete = () => { |
| | | if (!selectedRows.value.length) { |
| | | proxy.$modal.msgWarning('è¯·éæ©æ°æ®'); |
| | | return; |
| | | } |
| | | const ids = selectedRows.value.map(item => item.id); |
| | | ElMessageBox.confirm('éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼', 'å é¤æç¤º', { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }) |
| | | .then(() => { |
| | | batchDelete(ids) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess('å 餿å'); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError('å é¤å¤±è´¥'); |
| | | }); |
| | | }) |
| | | .catch(() => { }); |
| | | }; |
| | | |
| | | // 产åéæ© |
| | | const handleProductSelect = (products) => { |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | form.value.productModelId = product.id; |
| | | form.value.productName = product.productName; |
| | | form.value.productModelName = product.model; |
| | | } |
| | | showProductSelectDialog.value = false; |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const handleSubmit = () => { |
| | | formRef.value.validate((valid) => { |
| | | if (valid) { |
| | | const payload = { ...form.value }; |
| | | if (operationType.value === 'add') { |
| | | add(payload) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess('æ°å¢æå'); |
| | | closeDialog(); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError('æ°å¢å¤±è´¥'); |
| | | }); |
| | | } else { |
| | | update(payload) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess('ä¿®æ¹æå'); |
| | | closeDialog(); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError('ä¿®æ¹å¤±è´¥'); |
| | | }); |
| | | } |
| | | } |
| | | const data = reactive({ |
| | | form: { |
| | | id: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | productModelId: "", |
| | | remark: "", |
| | | version: "", |
| | | }, |
| | | rules: { |
| | | productModelId: [ |
| | | { required: true, message: "è¯·éæ©äº§å", trigger: "change" }, |
| | | ], |
| | | version: [{ required: true, message: "请è¾å
¥çæ¬å·", trigger: "blur" }], |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éå¼¹çª |
| | | const closeDialog = () => { |
| | | dialogVisible.value = false; |
| | | formRef.value?.resetFields(); |
| | | }; |
| | | const { form, rules } = toRefs(data); |
| | | |
| | | // 导å
¥æé®æä½ |
| | | const handleImport = () => { |
| | | upload.title = "BOM导å
¥"; |
| | | upload.open = true; |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // å
³é导å
¥å¯¹è¯æ¡æ¶æ¸
餿件 |
| | | const handleImportClose = () => { |
| | | proxy.$refs["uploadRef"].clearFiles(); |
| | | }; |
| | | |
| | | // æä»¶ä¸ä¼ ä¸å¤ç |
| | | const handleFileUploadProgress = (event, file, fileList) => { |
| | | upload.isUploading = true; |
| | | }; |
| | | |
| | | // æä»¶ä¸ä¼ æåå¤ç |
| | | const handleFileSuccess = (response, file, fileList) => { |
| | | upload.open = false; |
| | | upload.isUploading = false; |
| | | proxy.$refs["uploadRef"].clearFiles(); |
| | | if (response.code === 200) { |
| | | proxy.$modal.msgSuccess(response.msg || "导å
¥æå"); |
| | | // å页 |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | } else { |
| | | proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导å
¥ç»æ", { dangerouslyUseHTMLString: true }); |
| | | } |
| | | }; |
| | | }; |
| | | |
| | | // æäº¤ä¸ä¼ æä»¶ |
| | | const submitFileForm = () => { |
| | | proxy.$refs["uploadRef"].submit(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listPage({ |
| | | current: page.current, |
| | | size: page.size, |
| | | }) |
| | | .then(res => { |
| | | const records = res?.data?.records || []; |
| | | tableData.value = records; |
| | | page.total = res?.data?.total || 0; |
| | | }) |
| | | .catch(err => { |
| | | console.error("è·åå表失败ï¼", err); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // å¯¼åºæé®æä½ |
| | | const handleExport = () => { |
| | | if (selectedRows.value.length !== 1) { |
| | | proxy.$modal.msgWarning("è¯·éæ©ä¸æ¡æ°æ®è¿è¡å¯¼åº"); |
| | | return; |
| | | } |
| | | // æ°å¢ |
| | | const handleAdd = () => { |
| | | operationType.value = "add"; |
| | | Object.assign(form.value, { |
| | | id: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | productModelId: "", |
| | | remark: "", |
| | | version: "", |
| | | }); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const bomId = selectedRows.value[0].id; |
| | | const fileName = `BOM_${selectedRows.value[0].bomNo || bomId}.xlsx`; |
| | | // ç¼è¾ |
| | | const handleEdit = row => { |
| | | operationType.value = "edit"; |
| | | Object.assign(form.value, { |
| | | id: row.id, |
| | | productName: row.productName || "", |
| | | productModelName: row.productModelName || "", |
| | | productModelId: row.productModelId || "", |
| | | remark: row.remark || "", |
| | | version: row.version || "", |
| | | }); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | exportBom(bomId).then(res => { |
| | | // è¿åçæ°æ®æ¯å¦ä¸ºç©º |
| | | if (!res) { |
| | | proxy.$modal.msgError("导åºå¤±è´¥ï¼è¿åæ°æ®ä¸ºç©º"); |
| | | // å é¤ï¼åæ¡ï¼ |
| | | const handleDelete = row => { |
| | | ElMessageBox.confirm("确认å é¤è¯¥BOMï¼", "æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | batchDelete([row.id]) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("å é¤å¤±è´¥"); |
| | | }); |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | // æ¹éå é¤ |
| | | const handleBatchDelete = () => { |
| | | if (!selectedRows.value.length) { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | const ids = selectedRows.value.map(item => item.id); |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | batchDelete(ids) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("å é¤å¤±è´¥"); |
| | | }); |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | // 产åéæ© |
| | | const handleProductSelect = products => { |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | form.value.productModelId = product.id; |
| | | form.value.productName = product.productName; |
| | | form.value.productModelName = product.model; |
| | | } |
| | | showProductSelectDialog.value = false; |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const handleSubmit = () => { |
| | | formRef.value.validate(valid => { |
| | | if (valid) { |
| | | const payload = { ...form.value }; |
| | | if (operationType.value === "add") { |
| | | add(payload) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("æ°å¢æå"); |
| | | closeDialog(); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("æ°å¢å¤±è´¥"); |
| | | }); |
| | | } else { |
| | | update(payload) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("ä¿®æ¹æå"); |
| | | closeDialog(); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("ä¿®æ¹å¤±è´¥"); |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // å
³éå¼¹çª |
| | | const closeDialog = () => { |
| | | dialogVisible.value = false; |
| | | formRef.value?.resetFields(); |
| | | }; |
| | | |
| | | // 导å
¥æé®æä½ |
| | | const handleImport = () => { |
| | | upload.title = "BOM导å
¥"; |
| | | upload.open = true; |
| | | }; |
| | | |
| | | // å
³é导å
¥å¯¹è¯æ¡æ¶æ¸
餿件 |
| | | const handleImportClose = () => { |
| | | proxy.$refs["uploadRef"].clearFiles(); |
| | | }; |
| | | |
| | | // æä»¶ä¸ä¼ ä¸å¤ç |
| | | const handleFileUploadProgress = (event, file, fileList) => { |
| | | upload.isUploading = true; |
| | | }; |
| | | |
| | | // æä»¶ä¸ä¼ æåå¤ç |
| | | const handleFileSuccess = (response, file, fileList) => { |
| | | upload.open = false; |
| | | upload.isUploading = false; |
| | | proxy.$refs["uploadRef"].clearFiles(); |
| | | if (response.code === 200) { |
| | | proxy.$modal.msgSuccess(response.msg || "导å
¥æå"); |
| | | getList(); |
| | | } else { |
| | | proxy.$alert( |
| | | "<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + |
| | | response.msg + |
| | | "</div>", |
| | | "导å
¥ç»æ", |
| | | { dangerouslyUseHTMLString: true } |
| | | ); |
| | | } |
| | | }; |
| | | |
| | | // æäº¤ä¸ä¼ æä»¶ |
| | | const submitFileForm = () => { |
| | | proxy.$refs["uploadRef"].submit(); |
| | | }; |
| | | |
| | | // å¯¼åºæé®æä½ |
| | | const handleExport = () => { |
| | | if (selectedRows.value.length !== 1) { |
| | | proxy.$modal.msgWarning("è¯·éæ©ä¸æ¡æ°æ®è¿è¡å¯¼åº"); |
| | | return; |
| | | } |
| | | |
| | | const blob = new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); |
| | | const downloadElement = document.createElement('a'); |
| | | const bomId = selectedRows.value[0].id; |
| | | const fileName = `BOM_${selectedRows.value[0].bomNo || bomId}.xlsx`; |
| | | |
| | | exportBom(bomId) |
| | | .then(res => { |
| | | // è¿åçæ°æ®æ¯å¦ä¸ºç©º |
| | | if (!res) { |
| | | proxy.$modal.msgError("导åºå¤±è´¥ï¼è¿åæ°æ®ä¸ºç©º"); |
| | | return; |
| | | } |
| | | |
| | | const blob = new Blob([res], { |
| | | type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", |
| | | }); |
| | | const downloadElement = document.createElement("a"); |
| | | const href = window.URL.createObjectURL(blob); |
| | | |
| | | downloadElement.style.display = "none"; |
| | | downloadElement.href = href; |
| | | downloadElement.download = fileName; |
| | | |
| | | document.body.appendChild(downloadElement); |
| | | downloadElement.click(); |
| | | |
| | | document.body.removeChild(downloadElement); |
| | | window.URL.revokeObjectURL(href); |
| | | |
| | | proxy.$modal.msgSuccess("å¯¼åºæå"); |
| | | }) |
| | | .catch(err => { |
| | | console.error("导åºå¼å¸¸ï¼", err); |
| | | proxy.$modal.msgError("ç³»ç»å¼å¸¸ï¼å¯¼åºå¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // ä¸è½½æ¨¡æ¿ |
| | | const handleDownloadTemplate = async () => { |
| | | const res = await downloadTemplate(); |
| | | // è¿åçæ°æ®æ¯å¦ä¸ºç©º |
| | | if (!res) { |
| | | proxy.$modal.msgError("ä¸è½½å¤±è´¥ï¼è¿åæ°æ®ä¸ºç©º"); |
| | | return; |
| | | } |
| | | |
| | | const blob = new Blob([res], { |
| | | type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", |
| | | }); |
| | | const downloadElement = document.createElement("a"); |
| | | const href = window.URL.createObjectURL(blob); |
| | | |
| | | downloadElement.style.display = 'none'; |
| | | downloadElement.href = href; |
| | | downloadElement.download = fileName; |
| | | downloadElement.download = "BOM模æ¿.xlsx"; |
| | | |
| | | document.body.appendChild(downloadElement); |
| | | downloadElement.click(); |
| | |
| | | document.body.removeChild(downloadElement); |
| | | window.URL.revokeObjectURL(href); |
| | | |
| | | proxy.$modal.msgSuccess("å¯¼åºæå"); |
| | | }).catch(err => { |
| | | console.error("导åºå¼å¸¸ï¼", err); |
| | | proxy.$modal.msgError("ç³»ç»å¼å¸¸ï¼å¯¼åºå¤±è´¥"); |
| | | proxy.$modal.msgSuccess("ä¸è½½æå"); |
| | | }; |
| | | |
| | | // æ¥ç详æ
|
| | | const showDetail = row => { |
| | | router.push({ |
| | | path: "/productionManagement/productStructureDetail", |
| | | query: { |
| | | id: row.id, |
| | | bomNo: row.bomNo || "", |
| | | productName: row.productName || "", |
| | | productModelName: row.productModelName || "", |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | }; |
| | | |
| | | // ä¸è½½æ¨¡æ¿ |
| | | const handleDownloadTemplate = async () => { |
| | | const res = await downloadTemplate(); |
| | | // è¿åçæ°æ®æ¯å¦ä¸ºç©º |
| | | if (!res) { |
| | | proxy.$modal.msgError("ä¸è½½å¤±è´¥ï¼è¿åæ°æ®ä¸ºç©º"); |
| | | return; |
| | | } |
| | | |
| | | const blob = new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); |
| | | const downloadElement = document.createElement('a'); |
| | | const href = window.URL.createObjectURL(blob); |
| | | |
| | | downloadElement.href = href; |
| | | downloadElement.download = "BOM模æ¿.xlsx"; |
| | | |
| | | document.body.appendChild(downloadElement); |
| | | downloadElement.click(); |
| | | |
| | | document.body.removeChild(downloadElement); |
| | | window.URL.revokeObjectURL(href); |
| | | |
| | | proxy.$modal.msgSuccess("ä¸è½½æå"); |
| | | }; |
| | | |
| | | // æ¥ç详æ
|
| | | const showDetail = (row) => { |
| | | router.push({ |
| | | path: '/productionManagement/productStructureDetail', |
| | | query: { |
| | | id: row.id, |
| | | bomNo: row.bomNo || '', |
| | | productName: row.productName || '', |
| | | productModelName: row.productModelName || '' |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="æ°å¢ç产订å" |
| | | width="800" |
| | | @close="closeModal" |
| | | > |
| | | <el-form label-width="140px" :model="formState" label-position="top" ref="formRef"> |
| | | <el-form-item |
| | | label="产ååç§°" |
| | | prop="productModelId" |
| | | :rules="[ |
| | | <el-dialog v-model="isShow" |
| | | title="æ°å¢ç产订å" |
| | | width="800" |
| | | @close="closeModal"> |
| | | <el-form label-width="140px" |
| | | :model="formState" |
| | | label-position="top" |
| | | ref="formRef"> |
| | | <el-form-item label="产ååç§°" |
| | | prop="productModelId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©äº§å', |
| | | trigger: 'change', |
| | | } |
| | | ]" |
| | | > |
| | | <el-button type="primary" @click="showProductSelectDialog = true"> |
| | | ]"> |
| | | <el-button type="primary" |
| | | @click="showProductSelectDialog = true"> |
| | | {{ formState.productName ? formState.productName : 'éæ©äº§å' }} |
| | | </el-button> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="è§æ ¼" |
| | | prop="productModelName" |
| | | > |
| | | <el-input v-model="formState.productModelName" disabled /> |
| | | <el-form-item label="è§æ ¼" |
| | | prop="productModelName"> |
| | | <el-input v-model="formState.productModelName" |
| | | disabled /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="åä½" |
| | | prop="unit" |
| | | > |
| | | <el-input v-model="formState.unit" disabled /> |
| | | <el-form-item label="åä½" |
| | | prop="unit"> |
| | | <el-input v-model="formState.unit" |
| | | disabled /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="å·¥èºè·¯çº¿"> |
| | | <el-select v-model="formState.routeId" |
| | | placeholder="è¯·éæ©å·¥èºè·¯çº¿" |
| | |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="éæ±æ°é" |
| | | prop="quantity" |
| | | > |
| | | <el-input-number v-model="formState.quantity" :step="1" :min="1" style="width: 100%" /> |
| | | <el-form-item label="éæ±æ°é" |
| | | prop="quantity"> |
| | | <el-input-number v-model="formState.quantity" |
| | | :step="1" |
| | | :min="1" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- 产åéæ©å¼¹çª --> |
| | | <ProductSelectDialog |
| | | v-model="showProductSelectDialog" |
| | | @confirm="handleProductSelect" |
| | | single |
| | | /> |
| | | <ProductSelectDialog v-model="showProductSelectDialog" |
| | | @confirm="handleProductSelect" |
| | | single /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="handleSubmit">确认</el-button> |
| | | <el-button type="primary" |
| | | @click="handleSubmit">确认</el-button> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, computed, getCurrentInstance} from "vue"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import {addProductOrder, listProcessRoute} from "@/api/productionManagement/productionOrder.js"; |
| | | import { ref, computed, getCurrentInstance } from "vue"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import { |
| | | addProductOrder, |
| | | listProcessRoute, |
| | | } from "@/api/productionManagement/productionOrder.js"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | |
| | | type: { |
| | | type: String, |
| | | required: true, |
| | | default: 'qualified', |
| | | }, |
| | | }); |
| | | type: { |
| | | type: String, |
| | | required: true, |
| | | default: "qualified", |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | const emit = defineEmits(["update:visible", "completed"]); |
| | | |
| | | // ååºå¼æ°æ®ï¼æ¿ä»£é项å¼ç dataï¼ |
| | | const formState = ref({ |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | routeId: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | unit: "", |
| | | quantity: 0, |
| | | }); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | }, |
| | | }); |
| | | |
| | | const showProductSelectDialog = ref(false); |
| | | |
| | | let { proxy } = getCurrentInstance() |
| | | |
| | | const closeModal = () => { |
| | | // éç½®è¡¨åæ°æ® |
| | | formState.value = { |
| | | // ååºå¼æ°æ®ï¼æ¿ä»£é项å¼ç dataï¼ |
| | | const formState = ref({ |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | routeId: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | quantity: '', |
| | | unit: "", |
| | | quantity: 0, |
| | | }); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit("update:visible", val); |
| | | }, |
| | | }); |
| | | |
| | | const showProductSelectDialog = ref(false); |
| | | |
| | | let { proxy } = getCurrentInstance(); |
| | | |
| | | const closeModal = () => { |
| | | // éç½®è¡¨åæ°æ® |
| | | formState.value = { |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | routeId: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | quantity: "", |
| | | }; |
| | | isShow.value = false; |
| | | }; |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | // 产åéæ©å¤ç |
| | | const handleProductSelect = async (products) => { |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | formState.value.productId = product.productId; |
| | | formState.value.productName = product.productName; |
| | | formState.value.productModelName = product.model; |
| | | formState.value.productModelId = product.id; |
| | | formState.value.unit = product.unit; |
| | | showProductSelectDialog.value = false; |
| | | fetchRouteOptions( product.id); |
| | | // 触å表åéªè¯æ´æ° |
| | | proxy.$refs["formRef"]?.validateField('productModelId'); |
| | | } |
| | | }; |
| | | |
| | | const routeOptions = ref([]); |
| | | const bindRouteLoading = ref(false); |
| | | const fetchRouteOptions = (productModelId) => { |
| | | formState.value.routeId = undefined; |
| | | routeOptions.value = [] |
| | | bindRouteLoading.value = true; |
| | | listProcessRoute({ productModelId: productModelId }).then(res => { |
| | | routeOptions.value = res.data || []; |
| | | }).finally(() => { |
| | | bindRouteLoading.value = false; |
| | | }) |
| | | } |
| | | |
| | | const handleSubmit = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | // éªè¯æ¯å¦éæ©äºäº§ååè§æ ¼ |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©äº§å"); |
| | | return; |
| | | } |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©è§æ ¼"); |
| | | return; |
| | | } |
| | | |
| | | addProductOrder(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit('completed'); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }) |
| | | // 产åéæ©å¤ç |
| | | const handleProductSelect = async products => { |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | formState.value.productId = product.id; |
| | | formState.value.productName = product.productName; |
| | | formState.value.productModelName = product.model; |
| | | formState.value.productModelId = product.id; |
| | | formState.value.unit = product.unit; |
| | | showProductSelectDialog.value = false; |
| | | fetchRouteOptions(product.id); |
| | | // 触å表åéªè¯æ´æ° |
| | | proxy.$refs["formRef"]?.validateField("productModelId"); |
| | | } |
| | | }) |
| | | }; |
| | | }; |
| | | |
| | | const routeOptions = ref([]); |
| | | const bindRouteLoading = ref(false); |
| | | const fetchRouteOptions = productModelId => { |
| | | formState.value.routeId = undefined; |
| | | routeOptions.value = []; |
| | | bindRouteLoading.value = true; |
| | | listProcessRoute({ productModelId: productModelId }) |
| | | .then(res => { |
| | | routeOptions.value = res.data || []; |
| | | }) |
| | | .finally(() => { |
| | | bindRouteLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow, |
| | | }); |
| | | const handleSubmit = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | // éªè¯æ¯å¦éæ©äºäº§ååè§æ ¼ |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©äº§å"); |
| | | return; |
| | | } |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©è§æ ¼"); |
| | | return; |
| | | } |
| | | |
| | | addProductOrder(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit("completed"); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow, |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" |
| | | :inline="true"> |
| | | <el-form-item label="å·¥åºåç§°:"> |
| | | <el-input v-model="searchForm.name" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥åºç¼å·:"> |
| | | <el-input v-model="searchForm.no" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <div class="process-config-container"> |
| | | <!-- 左侧工åºå表 --> |
| | | <div class="process-list-section"> |
| | | <div class="section-header"> |
| | | <h3 class="section-title">å·¥åºå表</h3> |
| | | <el-button type="primary" |
| | | @click="handleQuery">æç´¢</el-button> |
| | | size="small" |
| | | @click="handleAddProcess"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon>æ°å¢å·¥åº |
| | | </el-button> |
| | | </div> |
| | | <div class="process-card-list" |
| | | v-loading="processLoading"> |
| | | <div v-for="process in processValueList" |
| | | :key="process.id" |
| | | class="process-card" |
| | | :class="{ active: selectedProcess?.id === process.id }" |
| | | @click="selectProcess(process)"> |
| | | <div class="card-header"> |
| | | <div class="process-name">{{ process.name }} <span class="process-code">{{ process.no }}</span></div> |
| | | <div class="card-actions"> |
| | | <el-button link |
| | | type="primary" |
| | | @click.stop="handleEditProcess(process)"> |
| | | <el-icon> |
| | | <Edit /> |
| | | </el-icon> |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button link |
| | | type="danger" |
| | | @click.stop="handleDeleteProcess(process)"> |
| | | <el-icon> |
| | | <Delete /> |
| | | </el-icon> |
| | | å é¤ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <div class="card-body"> |
| | | <!-- <div class="process-name">{{ process.name }}</div> --> |
| | | <div class="process-desc">{{ process.remark || 'ææ æè¿°' }}</div> |
| | | </div> |
| | | <div class="card-footer"> |
| | | <div class="status-tag"> <el-tag size="small" |
| | | :type="process.status ? 'success' : 'info'"> |
| | | {{ process.status ? 'å¯ç¨' : 'åç¨' }} |
| | | </el-tag> |
| | | <el-tag size="small" |
| | | :type="process.isQuality ? 'warning' : 'info'" |
| | | style="margin-left: 8px"> |
| | | {{ process.isQuality ? 'è´¨æ£' : 'éè´¨æ£' }} |
| | | </el-tag> |
| | | </div> |
| | | <span class="param-count">å·¥èµå®é¢: Â¥{{ process.salaryQuota || 0 }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- å³ä¾§åæ°å表 --> |
| | | <div class="param-list-section"> |
| | | <div class="section-header"> |
| | | <h3 class="section-title"> |
| | | {{ selectedProcess ? selectedProcess.name + ' - åæ°é
ç½®' : 'è¯·éæ©å·¥åº' }} |
| | | </h3> |
| | | <el-button type="primary" |
| | | size="small" |
| | | :disabled="!selectedProcess" |
| | | @click="handleSelectParam"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon>鿩忰 |
| | | </el-button> |
| | | </div> |
| | | <div class="param-table-wrapper"> |
| | | <PIMTable v-if="selectedProcess" |
| | | rowKey="id" |
| | | :column="paramColumn" |
| | | :tableData="paramList" |
| | | :page="paramPage" |
| | | height="calc(100vh - 280px)" |
| | | :isSelection="false" |
| | | @pagination="handleParamPagination" /> |
| | | <div v-else |
| | | class="empty-tip"> |
| | | <el-empty description="请ä»å·¦ä¾§éæ©ä¸ä¸ªå·¥åº" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- å·¥åºæ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="processDialogVisible" |
| | | :title="isProcessEdit ? 'ç¼è¾å·¥åº' : 'æ°å¢å·¥åº'" |
| | | width="500px"> |
| | | <el-form :model="processForm" |
| | | :rules="processRules" |
| | | ref="processFormRef" |
| | | label-width="100px"> |
| | | <el-form-item label="å·¥åºç¼ç " |
| | | prop="no"> |
| | | <el-input v-model="processForm.no" |
| | | placeholder="请è¾å
¥å·¥åºç¼ç " /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥åºåç§°" |
| | | prop="name"> |
| | | <el-input v-model="processForm.name" |
| | | placeholder="请è¾å
¥å·¥åºåç§°" /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥èµå®é¢" |
| | | prop="salaryQuota"> |
| | | <el-input v-model="processForm.salaryQuota" |
| | | type="number" |
| | | :step="0.001" /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¯å¦è´¨æ£" |
| | | prop="isQuality"> |
| | | <el-switch v-model="processForm.isQuality" |
| | | :active-value="true" |
| | | inactive-value="false" /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥åºæè¿°" |
| | | prop="remark"> |
| | | <el-input v-model="processForm.remark" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥å·¥åºæè¿°" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç¶æ" |
| | | prop="status"> |
| | | <el-radio-group v-model="processForm.status"> |
| | | <el-radio :label="true">å¯ç¨</el-radio> |
| | | <el-radio :label="false">åç¨</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="table_list"> |
| | | <div style="text-align: right" |
| | | class="mb10"> |
| | | <el-button type="primary" |
| | | @click="showNewModal">æ°å¢å·¥åº</el-button> |
| | | <el-button type="info" |
| | | plain |
| | | @click="handleImport">导å
¥</el-button> |
| | | <el-button type="danger" |
| | | @click="handleDelete" |
| | | :disabled="selectedRows.length === 0" |
| | | plain>å é¤å·¥åº</el-button> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="processDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" |
| | | @click="handleProcessSubmit">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- éæ©åæ°å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="paramDialogVisible" |
| | | title="鿩忰" |
| | | width="1000px"> |
| | | <div class="param-select-container"> |
| | | <!-- 左侧忰å表 --> |
| | | <div class="param-list-area"> |
| | | <div class="area-title">å¯éåæ°</div> |
| | | <div class="search-box"> |
| | | <el-input v-model="paramSearchKeyword" |
| | | placeholder="请è¾å
¥åæ°åç§°æç´¢" |
| | | clearable |
| | | size="small" |
| | | @input="handleSelectParam"> |
| | | <template #prefix> |
| | | <el-icon> |
| | | <Search /> |
| | | </el-icon> |
| | | </template> |
| | | </el-input> |
| | | </div> |
| | | <el-table :data="filteredParamList" |
| | | height="360" |
| | | border |
| | | highlight-current-row |
| | | @current-change="handleParamSelect"> |
| | | <el-table-column prop="paramName" |
| | | label="åæ°åç§°" /> |
| | | <el-table-column prop="paramType" |
| | | label="åæ°ç±»å"> |
| | | <template #default="scope"> |
| | | <el-tag size="small" |
| | | :type="getParamTypeTag(scope.row.paramType)"> |
| | | {{ getParamTypeText(scope.row.paramType) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | <!-- å³ä¾§åæ°è¯¦æ
--> |
| | | <div class="param-detail-area"> |
| | | <div class="area-title">åæ°è¯¦æ
</div> |
| | | <el-form v-if="selectedParam" |
| | | :model="selectedParam" |
| | | label-width="100px" |
| | | class="param-detail-form"> |
| | | <el-form-item label="åæ°åç§°"> |
| | | <span class="detail-text">{{ selectedParam.paramName }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="åæ°æ¨¡å¼"> |
| | | <el-tag size="small" |
| | | :type="selectedParam.valueMode == '1' ? 'success' : 'warning'"> |
| | | {{ selectedParam.valueMode == '1' ? 'åå¼' : 'åºé´' }} |
| | | </el-tag> |
| | | </el-form-item> |
| | | <el-form-item label="åæ°ç±»å"> |
| | | <el-tag size="small" |
| | | :type="getParamTypeTag(selectedParam.paramType)"> |
| | | {{ getParamTypeText(selectedParam.paramType) }} |
| | | </el-tag> |
| | | </el-form-item> |
| | | <el-form-item label="åæ°æ ¼å¼"> |
| | | <span class="detail-text">{{ selectedParam.paramFormat || '-' }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="åä½"> |
| | | <span class="detail-text">{{ selectedParam.unit || '-' }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="æ åå¼" |
| | | v-if="selectedParam.valueMode == '1'"> |
| | | <el-input v-model="selectedParam.standardValue" |
| | | type="number" |
| | | placeholder="请è¾å
¥é»è®¤å¼" /> |
| | | </el-form-item> |
| | | <el-form-item label="æå°å¼" |
| | | v-if="selectedParam.valueMode == '2'"> |
| | | <el-input v-model="selectedParam.minValue" |
| | | type="number" |
| | | placeholder="请è¾å
¥æå°å¼" /> |
| | | </el-form-item> |
| | | <el-form-item label="æå¤§å¼" |
| | | v-if="selectedParam.valueMode == '2'"> |
| | | <el-input v-model="selectedParam.maxValue" |
| | | type="number" |
| | | placeholder="请è¾å
¥æå¤§å¼" /> |
| | | </el-form-item> |
| | | <el-form-item label="æåº"> |
| | | <el-input v-model="selectedParam.sort" |
| | | type="number" |
| | | placeholder="请è¾å
¥æåº" /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¯å¦å¿
å¡«"> |
| | | <el-switch v-model="selectedParam.isRequired" |
| | | :active-value="1" |
| | | :inactive-value="0" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-empty v-else |
| | | description="请ä»å·¦ä¾§éæ©åæ°" /> |
| | | </div> |
| | | </div> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | <new-process v-if="isShowNewModal" |
| | | v-model:visible="isShowNewModal" |
| | | @completed="getList" /> |
| | | <edit-process v-if="isShowEditModal" |
| | | v-model:visible="isShowEditModal" |
| | | :record="record" |
| | | @completed="getList" /> |
| | | <ImportDialog ref="importDialogRef" |
| | | v-model="importDialogVisible" |
| | | title="导å
¥å·¥åº" |
| | | :action="importAction" |
| | | :headers="importHeaders" |
| | | :auto-upload="false" |
| | | :on-success="handleImportSuccess" |
| | | :on-error="handleImportError" |
| | | @confirm="handleImportConfirm" |
| | | @download-template="handleDownloadTemplate" |
| | | @close="handleImportClose" /> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="paramDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" |
| | | :disabled="!selectedParam" |
| | | @click="handleParamSubmit">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- ç¼è¾åæ°å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="editParamDialogVisible" |
| | | title="ç¼è¾åæ°" |
| | | width="600px"> |
| | | <el-form :model="editParamForm" |
| | | :rules="editParamRules" |
| | | ref="editParamFormRef" |
| | | label-width="120px"> |
| | | <el-form-item label="åæ°åç§°"> |
| | | <span class="detail-text">{{ editParamForm.paramName }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="åæ°æ¨¡å¼"> |
| | | <el-tag size="small" |
| | | :type="editParamForm.valueMode == '1' ? 'success' : 'warning'"> |
| | | {{ editParamForm.valueMode == '1' ? 'åå¼' : 'åºé´' }} |
| | | </el-tag> |
| | | </el-form-item> |
| | | <el-form-item label="æ åå¼" |
| | | v-if="editParamForm.valueMode == '1'" |
| | | prop="standardValue"> |
| | | <el-input v-model="editParamForm.standardValue" |
| | | type="number" |
| | | placeholder="请è¾å
¥æ åå¼" /> |
| | | </el-form-item> |
| | | <el-form-item label="æå°å¼" |
| | | v-if="editParamForm.valueMode == '2'" |
| | | prop="minValue"> |
| | | <el-input v-model="editParamForm.minValue" |
| | | type="number" |
| | | placeholder="请è¾å
¥æå°å¼" /> |
| | | </el-form-item> |
| | | <el-form-item label="æå¤§å¼" |
| | | v-if="editParamForm.valueMode == '2'" |
| | | prop="maxValue"> |
| | | <el-input v-model="editParamForm.maxValue" |
| | | type="number" |
| | | placeholder="请è¾å
¥æå¤§å¼" /> |
| | | </el-form-item> |
| | | <el-form-item label="æåº" |
| | | prop="sort"> |
| | | <el-input v-model="editParamForm.sort" |
| | | type="number" |
| | | placeholder="请è¾å
¥æåº" /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¯å¦å¿
å¡«" |
| | | prop="isRequired"> |
| | | <el-switch v-model="editParamForm.isRequired" |
| | | :active-value="1" |
| | | :inactive-value="0" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="editParamDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" |
| | | @click="handleEditParamSubmit">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue"; |
| | | import NewProcess from "@/views/productionManagement/productionProcess/New.vue"; |
| | | import EditProcess from "@/views/productionManagement/productionProcess/Edit.vue"; |
| | | import ImportDialog from "@/components/Dialog/ImportDialog.vue"; |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Plus, Edit, Delete, Search } from "@element-plus/icons-vue"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import { listType } from "@/api/system/dict/type"; |
| | | import { |
| | | listPage, |
| | | add, |
| | | update, |
| | | del, |
| | | importData, |
| | | downloadTemplate, |
| | | list as getProcessListApi, |
| | | processList, |
| | | getProcessParamList, |
| | | addProcessParam, |
| | | editProcessParam, |
| | | deleteProcessParam, |
| | | } from "@/api/productionManagement/productionProcess.js"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import { getBaseParamList } from "@/api/basicData/parameterMaintenance.js"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | name: "", |
| | | no: "", |
| | | }, |
| | | // å·¥åºåè¡¨æ°æ® |
| | | const processValueList = ref([]); |
| | | const selectedProcess = ref(null); |
| | | const processLoading = ref(false); |
| | | |
| | | // åæ°åè¡¨æ°æ® |
| | | const paramList = ref([]); |
| | | const paramLoading = ref(false); |
| | | const paramPage = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const tableColumn = ref([ |
| | | |
| | | // æ°æ®åå
¸ |
| | | const dictTypes = ref([]); |
| | | |
| | | // å·¥åºå¯¹è¯æ¡ |
| | | const processDialogVisible = ref(false); |
| | | const isProcessEdit = ref(false); |
| | | const processFormRef = ref(null); |
| | | const processForm = reactive({ |
| | | id: null, |
| | | no: "", |
| | | name: "", |
| | | salaryQuota: null, |
| | | isQuality: false, |
| | | remark: "", |
| | | status: true, |
| | | }); |
| | | const processRules = { |
| | | no: [{ required: true, message: "请è¾å
¥å·¥åºç¼ç ", trigger: "blur" }], |
| | | name: [{ required: true, message: "请è¾å
¥å·¥åºåç§°", trigger: "blur" }], |
| | | salaryQuota: [ |
| | | { |
| | | required: true, |
| | | message: "请è¾å
¥å·¥èµå®é¢", |
| | | trigger: "blur", |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === undefined || value === "") { |
| | | callback(new Error("请è¾å
¥å·¥èµå®é¢")); |
| | | } else if (isNaN(value) || value < 0) { |
| | | callback(new Error("å·¥èµå®é¢å¿
é¡»æ¯éè´æ°å")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | // åæ°å¯¹è¯æ¡ |
| | | const paramDialogVisible = ref(false); |
| | | const availableParamList = ref([]); |
| | | const filteredParamList = ref([]); |
| | | const selectedParam = ref(null); |
| | | const paramSearchKeyword = ref(""); |
| | | |
| | | // ç¼è¾åæ°å¯¹è¯æ¡ |
| | | const editParamDialogVisible = ref(false); |
| | | const editParamFormRef = ref(null); |
| | | const editParamForm = reactive({ |
| | | id: null, |
| | | processId: null, |
| | | paramId: null, |
| | | paramName: "", |
| | | valueMode: "1", |
| | | standardValue: null, |
| | | minValue: null, |
| | | maxValue: null, |
| | | sort: 1, |
| | | isRequired: 0, |
| | | tenantId: 1, |
| | | }); |
| | | const editParamRules = { |
| | | standardValue: [ |
| | | { |
| | | required: true, |
| | | message: "请è¾å
¥æ åå¼", |
| | | trigger: "blur", |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === undefined || value === "") { |
| | | callback(new Error("请è¾å
¥æ åå¼")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | minValue: [ |
| | | { |
| | | required: true, |
| | | message: "请è¾å
¥æå°å¼", |
| | | trigger: "blur", |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === undefined || value === "") { |
| | | callback(new Error("请è¾å
¥æå°å¼")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | maxValue: [ |
| | | { |
| | | required: true, |
| | | message: "请è¾å
¥æå¤§å¼", |
| | | trigger: "blur", |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === undefined || value === "") { |
| | | callback(new Error("请è¾å
¥æå¤§å¼")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | sort: [ |
| | | { |
| | | required: true, |
| | | message: "请è¾å
¥æåº", |
| | | trigger: "blur", |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === undefined || value === "") { |
| | | callback(new Error("请è¾å
¥æåº")); |
| | | } else if (isNaN(value) || value < 1) { |
| | | callback(new Error("æåºå¿
é¡»æ¯å¤§äº0çæ´æ°")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | // åæ°è¡¨æ ¼åé
ç½® |
| | | const paramColumn = ref([ |
| | | { |
| | | label: "å·¥åºç¼å·", |
| | | prop: "no", |
| | | label: "åæ°åç§°", |
| | | prop: "paramName", |
| | | }, |
| | | { |
| | | label: "å·¥åºåç§°", |
| | | prop: "name", |
| | | label: "åæ°æ¨¡å¼", |
| | | prop: "valueMode", |
| | | dataType: "tag", |
| | | formatType: row => (row.valueMode === "1" ? "success" : "warning"), |
| | | formatData: row => (row.valueMode === "1" ? "åå¼" : "åºé´"), |
| | | }, |
| | | { |
| | | label: "å·¥èµå®é¢", |
| | | prop: "salaryQuota", |
| | | }, |
| | | { |
| | | label: "æ¯å¦è´¨æ£", |
| | | prop: "isQuality", |
| | | formatData: (params) => { |
| | | return params ? "æ¯" : "å¦"; |
| | | label: "åæ°ç±»å", |
| | | prop: "paramType", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | const typeMap = { |
| | | 1: "primary", |
| | | 2: "info", |
| | | 3: "warning", |
| | | 4: "success", |
| | | }; |
| | | return typeMap[params] || "default"; |
| | | }, |
| | | formatData: val => { |
| | | const labelMap = { |
| | | 1: "æ°å¼æ ¼å¼", |
| | | 2: "ææ¬æ ¼å¼", |
| | | 3: "䏿é项", |
| | | 4: "æ¶é´æ ¼å¼", |
| | | }; |
| | | return labelMap[val] || val; |
| | | }, |
| | | }, |
| | | { |
| | | label: "夿³¨", |
| | | prop: "remark", |
| | | label: "å弿 ¼å¼", |
| | | prop: "paramFormat", |
| | | formatData: (val, row) => { |
| | | if (row.paramType == "3") { |
| | | const dict = dictTypes.value.find(item => item.dictType === val); |
| | | return dict ? "åå
¸:" + dict.dictName : val; |
| | | } |
| | | return val; |
| | | }, |
| | | }, |
| | | { |
| | | label: "æ´æ°æ¶é´", |
| | | prop: "updateTime", |
| | | label: "æ åå¼", |
| | | prop: "standardValue", |
| | | formatData: (val, row) => { |
| | | return row.valueMode == "1" ? val : "-"; |
| | | }, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æå°å¼", |
| | | prop: "minValue", |
| | | formatData: (val, row) => { |
| | | return row.valueMode == "2" ? val : "-"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "æå¤§å¼", |
| | | prop: "maxValue", |
| | | formatData: (val, row) => { |
| | | return row.valueMode == "2" ? val : "-"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "æåº", |
| | | prop: "sort", |
| | | }, |
| | | { |
| | | label: "æ¯å¦å¿
å¡«", |
| | | prop: "isRequired", |
| | | dataType: "tag", |
| | | formatType: row => (row.isRequired === 1 ? "success" : "info"), |
| | | formatData: row => (row.isRequired === 1 ? "æ¯" : "å¦"), |
| | | }, |
| | | { |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | dataType: "action", |
| | | width: "150", |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: row => { |
| | | showEditModal(row); |
| | | }, |
| | | clickFun: row => handleEditParam(row), |
| | | }, |
| | | { |
| | | name: "å é¤", |
| | | clickFun: row => handleDeleteParam(row), |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const isShowNewModal = ref(false); |
| | | const isShowEditModal = ref(false); |
| | | const record = ref({}); |
| | | const importDialogVisible = ref(false); |
| | | const importDialogRef = ref(null); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | // 导å
¥ç¸å
³é
ç½® |
| | | const importAction = |
| | | import.meta.env.VITE_APP_BASE_API + "/productProcess/importData"; |
| | | const importHeaders = { Authorization: "Bearer " + getToken() }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined; |
| | | listPage(params) |
| | | // è·åå·¥åºå表 |
| | | const getProcessList = () => { |
| | | processLoading.value = true; |
| | | getProcessListApi() |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records.map(item => ({ |
| | | ...item, |
| | | })); |
| | | page.total = res.data.total; |
| | | processValueList.value = res.data || []; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | .catch(() => { |
| | | ElMessage.error("è·åå·¥åºå表失败"); |
| | | }) |
| | | .finally(() => { |
| | | processLoading.value = false; |
| | | }); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | |
| | | // è·ååæ°å表 |
| | | const getParamList = processId => { |
| | | paramLoading.value = true; |
| | | getProcessParamList(processId) |
| | | .then(res => { |
| | | paramList.value = res.data || []; |
| | | paramPage.total = paramList.value.length; |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error("è·ååæ°å表失败"); |
| | | }) |
| | | .finally(() => { |
| | | paramLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // æå¼æ°å¢å¼¹æ¡ |
| | | const showNewModal = () => { |
| | | isShowNewModal.value = true; |
| | | // éæ©å·¥åº |
| | | const selectProcess = process => { |
| | | selectedProcess.value = process; |
| | | getParamList(process.id); |
| | | }; |
| | | |
| | | const showEditModal = row => { |
| | | isShowEditModal.value = true; |
| | | record.value = row; |
| | | // å·¥åºæä½ |
| | | const handleAddProcess = () => { |
| | | isProcessEdit.value = false; |
| | | processForm.id = null; |
| | | processForm.no = ""; |
| | | processForm.name = ""; |
| | | processForm.salaryQuota = null; |
| | | processForm.isQuality = false; |
| | | processForm.remark = ""; |
| | | processForm.status = true; |
| | | processDialogVisible.value = true; |
| | | }; |
| | | |
| | | // å é¤ |
| | | function handleDelete() { |
| | | const no = selectedRows.value.map(item => item.no); |
| | | const ids = selectedRows.value.map(item => item.id); |
| | | if (no.length > 2) { |
| | | proxy.$modal |
| | | .confirm( |
| | | 'æ¯å¦ç¡®è®¤å é¤å·¥åºç¼å·ä¸º"' + |
| | | no[0] + |
| | | "ã" + |
| | | no[1] + |
| | | '"ç' + |
| | | no.length + |
| | | "æ¡æ°æ®é¡¹ï¼" |
| | | ) |
| | | .then(function () { |
| | | return del(ids); |
| | | }) |
| | | const handleEditProcess = process => { |
| | | isProcessEdit.value = true; |
| | | processForm.id = process.id; |
| | | processForm.no = process.no; |
| | | processForm.name = process.name; |
| | | processForm.salaryQuota = process.salaryQuota; |
| | | processForm.isQuality = process.isQuality || false; |
| | | processForm.remark = process.remark || ""; |
| | | processForm.status = process.status; |
| | | processDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleDeleteProcess = process => { |
| | | ElMessageBox.confirm("ç¡®å®è¦å é¤è¯¥å·¥åºåï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | del([process.id]) |
| | | .then(() => { |
| | | getList(); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | ElMessage.success("å 餿å"); |
| | | getProcessList(); |
| | | if (selectedProcess.value?.id === process.id) { |
| | | selectedProcess.value = null; |
| | | paramList.value = []; |
| | | } |
| | | }) |
| | | .catch(() => {}); |
| | | } else { |
| | | proxy.$modal |
| | | .confirm('æ¯å¦ç¡®è®¤å é¤å·¥åºç¼å·ä¸º"' + no + '"çæ°æ®é¡¹ï¼') |
| | | .then(function () { |
| | | return del(ids); |
| | | }) |
| | | .then(() => { |
| | | getList(); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | }) |
| | | .catch(() => {}); |
| | | } |
| | | } |
| | | |
| | | // 导å
¥ |
| | | const handleImport = () => { |
| | | importDialogVisible.value = true; |
| | | .catch(() => { |
| | | ElMessage.error("å é¤å¤±è´¥"); |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | // 确认导å
¥ |
| | | const handleImportConfirm = () => { |
| | | if (importDialogRef.value) { |
| | | importDialogRef.value.submit(); |
| | | } |
| | | }; |
| | | |
| | | // 导å
¥æå |
| | | const handleImportSuccess = response => { |
| | | if (response.code === 200) { |
| | | proxy.$modal.msgSuccess("导å
¥æå"); |
| | | importDialogVisible.value = false; |
| | | if (importDialogRef.value) { |
| | | importDialogRef.value.clearFiles(); |
| | | const handleProcessSubmit = () => { |
| | | processFormRef.value.validate(valid => { |
| | | if (valid) { |
| | | const apiMethod = isProcessEdit.value ? update : add; |
| | | apiMethod(processForm) |
| | | .then(() => { |
| | | ElMessage.success(isProcessEdit.value ? "ç¼è¾æå" : "æ°å¢æå"); |
| | | processDialogVisible.value = false; |
| | | getProcessList(); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error(isProcessEdit.value ? "ç¼è¾å¤±è´¥" : "æ°å¢å¤±è´¥"); |
| | | }); |
| | | } |
| | | getList(); |
| | | }); |
| | | }; |
| | | |
| | | // åæ°æä½ |
| | | const handleSelectParam = () => { |
| | | if (!selectedProcess.value) { |
| | | ElMessage.warning("请å
éæ©ä¸ä¸ªå·¥åº"); |
| | | return; |
| | | } |
| | | // è·åå¯éåæ°å表 |
| | | getBaseParamList({ paramName: paramSearchKeyword.value }).then(res => { |
| | | if (res.code === 200) { |
| | | filteredParamList.value = res.data || []; |
| | | page.total = res.data?.length || 0; |
| | | } else { |
| | | ElMessage.error(res.msg || "æ¥è¯¢å¤±è´¥"); |
| | | } |
| | | }); |
| | | console.log(filteredParamList.value, "å¯éåæ°å表"); |
| | | selectedParam.value = null; |
| | | paramDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleParamSelect = row => { |
| | | selectedParam.value = row; |
| | | }; |
| | | |
| | | const handleParamSearch = () => { |
| | | const keyword = paramSearchKeyword.value.trim().toLowerCase(); |
| | | if (!keyword) { |
| | | filteredParamList.value = availableParamList.value; |
| | | } else { |
| | | proxy.$modal.msgError(response.msg || "导å
¥å¤±è´¥"); |
| | | filteredParamList.value = availableParamList.value.filter(item => |
| | | item.paramName.toLowerCase().includes(keyword) |
| | | ); |
| | | } |
| | | }; |
| | | |
| | | // 导å
¥å¤±è´¥ |
| | | const handleImportError = error => { |
| | | proxy.$modal.msgError("导å
¥å¤±è´¥ï¼" + (error.message || "æªç¥é误")); |
| | | const getParamTypeText = type => { |
| | | const typeMap = { |
| | | 1: "æ°å¼æ ¼å¼", |
| | | 2: "ææ¬æ ¼å¼", |
| | | 3: "䏿é项", |
| | | 4: "æ¶é´æ ¼å¼", |
| | | }; |
| | | return typeMap[type] || "æªç¥åæ°ç±»å"; |
| | | }; |
| | | const getParamTypeTag = type => { |
| | | const typeMap = { |
| | | 1: "primary", |
| | | 2: "info", |
| | | 3: "warning", |
| | | 4: "success", |
| | | }; |
| | | return typeMap[type] || "default"; |
| | | }; |
| | | |
| | | // å
³é导å
¥å¼¹çª |
| | | const handleImportClose = () => { |
| | | if (importDialogRef.value) { |
| | | importDialogRef.value.clearFiles(); |
| | | const handleDeleteParam = row => { |
| | | ElMessageBox.confirm("ç¡®å®è¦å é¤è¯¥åæ°åï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | deleteProcessParam(row.id) |
| | | .then(() => { |
| | | ElMessage.success("å 餿å"); |
| | | getParamList(selectedProcess.value.id); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error("å é¤å¤±è´¥"); |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | const handleEditParam = row => { |
| | | editParamForm.id = row.id; |
| | | editParamForm.processId = row.processId; |
| | | editParamForm.paramId = row.paramId; |
| | | editParamForm.paramName = row.paramName; |
| | | editParamForm.valueMode = row.valueMode; |
| | | editParamForm.standardValue = row.standardValue; |
| | | editParamForm.minValue = row.minValue; |
| | | editParamForm.maxValue = row.maxValue; |
| | | editParamForm.sort = row.sort || 1; |
| | | editParamForm.isRequired = row.isRequired || 0; |
| | | editParamForm.tenantId = 1; |
| | | editParamDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleEditParamSubmit = () => { |
| | | editParamFormRef.value.validate(valid => { |
| | | if (valid) { |
| | | editProcessParam(editParamForm) |
| | | .then(() => { |
| | | ElMessage.success("ç¼è¾æå"); |
| | | editParamDialogVisible.value = false; |
| | | getParamList(selectedProcess.value.id); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error("ç¼è¾å¤±è´¥"); |
| | | }); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleParamSubmit = () => { |
| | | if (!selectedParam.value) { |
| | | ElMessage.warning("请å
éæ©ä¸ä¸ªåæ°"); |
| | | return; |
| | | } |
| | | }; |
| | | |
| | | // ä¸è½½æ¨¡æ¿ |
| | | const handleDownloadTemplate = async () => { |
| | | try { |
| | | const res = await downloadTemplate(); |
| | | const blob = new Blob([res], { |
| | | type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", |
| | | addProcessParam({ |
| | | processId: selectedProcess.value.id, |
| | | paramId: selectedParam.value.id, |
| | | sort: selectedParam.value.sort || 1, |
| | | standardValue: selectedParam.value.standardValue, |
| | | minValue: selectedParam.value.minValue, |
| | | maxValue: selectedParam.value.maxValue, |
| | | isRequired: selectedParam.value.isRequired || 0, |
| | | tenantId: 1, |
| | | }) |
| | | .then(() => { |
| | | ElMessage.success("æ·»å æå"); |
| | | paramDialogVisible.value = false; |
| | | getParamList(selectedProcess.value.id); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error("æ·»å 失败"); |
| | | }); |
| | | const url = window.URL.createObjectURL(blob); |
| | | const link = document.createElement("a"); |
| | | link.href = url; |
| | | link.download = "å·¥åºå¯¼å
¥æ¨¡æ¿.xlsx"; |
| | | link.click(); |
| | | window.URL.revokeObjectURL(url); |
| | | proxy.$modal.msgSuccess("模æ¿ä¸è½½æå"); |
| | | } catch (error) { |
| | | proxy.$modal.msgError("模æ¿ä¸è½½å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | // const handleOut = () => { |
| | | // ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | // confirmButtonText: "确认", |
| | | // cancelButtonText: "åæ¶", |
| | | // type: "warning", |
| | | // }) |
| | | // .then(() => { |
| | | // proxy.download("/salesLedger/scheduling/exportTwo", {}, "å·¥åºæäº§.xlsx"); |
| | | // }) |
| | | // .catch(() => { |
| | | // proxy.$modal.msg("已忶"); |
| | | // }); |
| | | // }; |
| | | const handleParamPagination = obj => { |
| | | paramPage.current = obj.page; |
| | | paramPage.size = obj.limit; |
| | | getParamList(selectedProcess.value.id); |
| | | }; |
| | | |
| | | // è·åæ°æ®åå
¸ |
| | | const getDictTypes = () => { |
| | | listType({ pageNum: 1, pageSize: 1000 }).then(res => { |
| | | dictTypes.value = res.rows || []; |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | getProcessList(); |
| | | getDictTypes(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped></style> |
| | | <style scoped lang="scss"> |
| | | .app-container { |
| | | padding: 20px; |
| | | background-color: #f0f2f5; |
| | | min-height: calc(100vh - 84px); |
| | | } |
| | | |
| | | .process-config-container { |
| | | display: flex; |
| | | gap: 20px; |
| | | height: calc(100vh - 124px); |
| | | } |
| | | |
| | | // 左侧工åºå表 |
| | | .process-list-section { |
| | | width: 370px; |
| | | min-width: 370px; |
| | | flex-shrink: 0; |
| | | background: #fff; |
| | | border-radius: 8px; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 16px 20px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | |
| | | .section-title { |
| | | margin: 0; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | } |
| | | |
| | | .process-card-list { |
| | | flex: 1; |
| | | overflow-y: auto; |
| | | padding: 16px; |
| | | } |
| | | |
| | | .process-card { |
| | | background: #fff; |
| | | border: 1px solid #ebeef5; |
| | | border-radius: 8px; |
| | | padding: 16px; |
| | | margin-bottom: 12px; |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| | | transform: translateY(-2px); |
| | | } |
| | | |
| | | &.active { |
| | | border-color: #409eff; |
| | | background: #f5f7fa; |
| | | box-shadow: 0 4px 12px rgba(64, 158, 255, 0.2); |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 8px; |
| | | |
| | | .process-code { |
| | | font-size: 12px; |
| | | // color: #909399; |
| | | color: #cb9b18; |
| | | font-family: "Courier New", monospace; |
| | | } |
| | | |
| | | .card-actions { |
| | | display: flex; |
| | | gap: 4px; |
| | | |
| | | .el-button { |
| | | padding: 4px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .card-body { |
| | | margin-bottom: 12px; |
| | | |
| | | .process-name { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .process-desc { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | } |
| | | |
| | | .card-footer { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | |
| | | .param-count { |
| | | font-size: 12px; |
| | | color: #606266; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // å³ä¾§åæ°å表 |
| | | .param-list-section { |
| | | flex: 1; |
| | | background: #fff; |
| | | border-radius: 8px; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .param-table-wrapper { |
| | | flex: 1; |
| | | padding: 0 20px 20px; |
| | | overflow: auto; |
| | | } |
| | | |
| | | /* è¡¨æ ¼æ¨ªåæ»å¨ */ |
| | | :deep(.el-table) { |
| | | // min-width: 800px; |
| | | } |
| | | |
| | | .empty-tip { |
| | | flex: 1; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | // è¡¨æ ¼æ ·å¼ |
| | | :deep(.el-table) { |
| | | border: none; |
| | | border-radius: 6px; |
| | | overflow: hidden; |
| | | |
| | | .el-table__header-wrapper { |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | |
| | | th { |
| | | background: transparent; |
| | | font-weight: 600; |
| | | color: #ffffff; |
| | | border-bottom: none; |
| | | padding: 16px 0; |
| | | } |
| | | } |
| | | |
| | | .el-table__body-wrapper { |
| | | tr { |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | background: linear-gradient( |
| | | 90deg, |
| | | rgba(102, 126, 234, 0.05) 0%, |
| | | rgba(118, 75, 162, 0.05) 100% |
| | | ); |
| | | } |
| | | |
| | | td { |
| | | border-bottom: 1px solid #f0f0f0; |
| | | padding: 14px 0; |
| | | color: #303133; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // ç¼ç åå
æ ¼æ ·å¼ |
| | | :deep(.code-cell) { |
| | | color: #e6a23c; |
| | | font-family: "Courier New", monospace; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | // æ°å¼åå
æ ¼æ ·å¼ |
| | | :deep(.quantity-cell) { |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | font-family: "Courier New", monospace; |
| | | } |
| | | |
| | | // éæ©åæ°å¯¹è¯æ¡æ ·å¼ |
| | | .param-select-container { |
| | | display: flex; |
| | | gap: 20px; |
| | | height: 450px; |
| | | |
| | | .param-list-area { |
| | | // flex: 1; |
| | | width: 380px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .area-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | margin-bottom: 12px; |
| | | padding-bottom: 8px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .search-box { |
| | | margin-bottom: 12px; |
| | | |
| | | .el-input { |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .param-detail-area { |
| | | // width: 380px; |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | background: #f5f7fa; |
| | | border-radius: 8px; |
| | | padding: 16px; |
| | | |
| | | .area-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | margin-bottom: 16px; |
| | | padding-bottom: 8px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .param-detail-form { |
| | | .el-form-item { |
| | | margin-bottom: 12px; |
| | | |
| | | .el-form-item__label { |
| | | color: #606266; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | |
| | | .detail-text { |
| | | color: #303133; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="产åè§æ ¼:"> |
| | | <el-input v-model="searchForm.specification" |
| | | <el-input v-model="searchForm.model" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | style="width: 160px;" |
| | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="10"> |
| | | <el-form-item label="产åè§æ ¼"> |
| | | <div class="info-display">{{ mergeForm.specification || '-' }}</div> |
| | | <div class="info-display">{{ mergeForm.model || '-' }}</div> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="10"> |
| | |
| | | filterable |
| | | placeholder="è¯·éæ©"> |
| | | <el-option v-for="item in specificationOptions" |
| | | :key="item.skuId" |
| | | :label="item.specification" |
| | | :value="item.skuId" /> |
| | | :key="item.id" |
| | | :label="item.model" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="åæ°" |
| | |
| | | }, |
| | | { |
| | | label: "产åè§æ ¼", |
| | | prop: "specification", |
| | | prop: "model", |
| | | width: "150px", |
| | | className: "spec-cell", |
| | | }, |
| | |
| | | mergeForm.ids = [row.id]; |
| | | mergeForm.materialCode = row.materialCode; |
| | | mergeForm.productName = row.productName || ""; |
| | | mergeForm.specification = row.specification || ""; |
| | | mergeForm.model = row.model || ""; |
| | | mergeForm.length = row.length || 0; |
| | | mergeForm.width = row.width || 0; |
| | | mergeForm.height = row.height || 0; |
| | |
| | | const mergeForm = reactive({ |
| | | materialCode: "", |
| | | productName: "", |
| | | specification: "", |
| | | model: "", |
| | | length: 0, |
| | | width: 0, |
| | | height: 0, |
| | |
| | | productMaterialId: undefined, |
| | | productMaterialSkuId: undefined, |
| | | productName: "", |
| | | specification: "", |
| | | model: "", |
| | | materialCode: "", |
| | | quantity: 0, |
| | | volume: 0, |
| | |
| | | if (item.materialList && item.materialList.length > 0) { |
| | | newItem.children = item.materialList.map(material => ({ |
| | | value: material.id, // 使ç¨materialçidä½ä¸ºvalue |
| | | label: material.materialName, // 使ç¨materialNameä½ä¸ºlabel |
| | | label: material.productName, // 使ç¨materialNameä½ä¸ºlabel |
| | | })); |
| | | } |
| | | |
| | |
| | | fetchSpecificationOptions(value); |
| | | }; |
| | | |
| | | const fetchSpecificationOptions = materialId => { |
| | | const fetchSpecificationOptions = productId => { |
| | | specificationOptions.value = []; |
| | | if (materialId) { |
| | | modelListPage({ materialId: materialId, size: -1, current: -1 }).then( |
| | | res => { |
| | | specificationOptions.value = res.data.records; |
| | | } |
| | | ); |
| | | if (productId) { |
| | | modelListPage({ productId: productId, size: -1, current: -1 }).then(res => { |
| | | specificationOptions.value = res.data.records; |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const handleChangeSpecification = value => { |
| | | form.materialCode = undefined; |
| | | const selectedModel = specificationOptions.value.find( |
| | | item => item.skuId === value |
| | | item => item.id === value |
| | | ); |
| | | if (selectedModel) { |
| | | form.materialCode = selectedModel.materialCode; |
| | | // è§£æè§æ ¼å符串è·åé¿å®½é« |
| | | const specification = selectedModel.specification; |
| | | if (specification) { |
| | | const dimensions = specification.match(/^(\d+)\*(\d+)\*(\d+)$/); |
| | | const model = selectedModel.model; |
| | | if (model) { |
| | | const dimensions = model.match(/^(\d+)\*(\d+)\*(\d+)$/); |
| | | if (dimensions && dimensions.length === 4) { |
| | | form.length = parseInt(dimensions[1]); |
| | | form.width = parseInt(dimensions[2]); |
| | |
| | | searchForm: { |
| | | customerName: "", |
| | | productName: "", |
| | | specification: "", |
| | | model: "", |
| | | materialCode: "", |
| | | applyNo: "", |
| | | dateRange: [], |
| | |
| | | Object.assign(searchForm.value, { |
| | | customerName: "", |
| | | productName: "", |
| | | specification: "", |
| | | model: "", |
| | | materialCode: "", |
| | | applyNo: "", |
| | | dateRange: [], |
| | |
| | | const firstRow = selectedRows.value[0]; |
| | | mergeForm.materialCode = selectedserialNo.value; |
| | | mergeForm.productName = firstRow.productName || ""; |
| | | mergeForm.specification = firstRow.specification || ""; |
| | | mergeForm.model = firstRow.model || ""; |
| | | mergeForm.length = firstRow.length || 0; |
| | | mergeForm.width = firstRow.width || 0; |
| | | mergeForm.height = firstRow.height || 0; |
| | |
| | | productName: "", |
| | | productMaterialId: undefined, |
| | | productMaterialSkuId: undefined, |
| | | specification: "", |
| | | model: "", |
| | | materialCode: "", |
| | | quantity: 0, |
| | | volume: 0, |
| | |
| | | productName: row.productName || "", |
| | | productMaterialId: row.productMaterialId || undefined, |
| | | productMaterialSkuId: row.productMaterialSkuId || undefined, |
| | | specification: row.specification || "", |
| | | model: row.model || "", |
| | | materialCode: row.materialCode || "", |
| | | quantity: row.quantity || 0, |
| | | volume: row.volume || 0, |
| | |
| | | }, |
| | | { |
| | | label: "产åè§æ ¼", |
| | | prop: "specification", |
| | | prop: "model", |
| | | className: "spec-cell", |
| | | }, |
| | | { |
| | |
| | | <template> |
| | | <div class="app-container metric-binding"> |
| | | <el-row :gutter="16" class="metric-binding-row"> |
| | | <el-row :gutter="16" |
| | | class="metric-binding-row"> |
| | | <!-- å·¦ä¾§ï¼æ£æµæ åå表 --> |
| | | <el-col :xs="24" :sm="24" :md="12" :lg="14" :xl="14" class="left-col"> |
| | | <el-col :xs="24" |
| | | :sm="24" |
| | | :md="12" |
| | | :lg="14" |
| | | :xl="14" |
| | | class="left-col"> |
| | | <div class="panel left-panel"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="standardColumns" |
| | | :tableData="standardTableData" |
| | | :page="page" |
| | | :isSelection="false" |
| | | :rowClassName="rowClassNameCenter" |
| | | :tableLoading="tableLoading" |
| | | :rowClick="handleTableRowClick" |
| | | @pagination="handlePagination" |
| | | :total="page.total" |
| | | > |
| | | <template #standardNoCell="{ row }"> |
| | | <span class="clickable-link" @click="handleStandardRowClick(row)"> |
| | | {{ row.standardNo }} |
| | | </span> |
| | | </template> |
| | | |
| | | <!-- 表头æç´¢ --> |
| | | <template #standardNoHeader> |
| | | <el-input |
| | | v-model="searchForm.standardNo" |
| | | placeholder="æ åç¼å·" |
| | | clearable |
| | | size="small" |
| | | @change="handleQuery" |
| | | @clear="handleQuery" |
| | | /> |
| | | </template> |
| | | <template #standardNameHeader> |
| | | <el-input |
| | | v-model="searchForm.standardName" |
| | | placeholder="æ ååç§°" |
| | | clearable |
| | | size="small" |
| | | @change="handleQuery" |
| | | @clear="handleQuery" |
| | | /> |
| | | </template> |
| | | <template #inspectTypeHeader> |
| | | <el-select |
| | | v-model="searchForm.inspectType" |
| | | placeholder="ç±»å«" |
| | | clearable |
| | | size="small" |
| | | style="width: 120px" |
| | | @change="handleQuery" |
| | | @clear="handleQuery" |
| | | > |
| | | <el-option label="åæææ£éª" value="0" /> |
| | | <el-option label="è¿ç¨æ£éª" value="1" /> |
| | | <el-option label="åºåæ£éª" value="2" /> |
| | | </el-select> |
| | | </template> |
| | | <template #stateHeader> |
| | | <el-select |
| | | v-model="searchForm.state" |
| | | placeholder="ç¶æ" |
| | | clearable |
| | | size="small" |
| | | style="width: 110px" |
| | | @change="handleQuery" |
| | | @clear="handleQuery" |
| | | > |
| | | <el-option label="è稿" value="0" /> |
| | | <el-option label="éè¿" value="1" /> |
| | | <el-option label="æ¤é" value="2" /> |
| | | </el-select> |
| | | </template> |
| | | </PIMTable> |
| | | <PIMTable rowKey="id" |
| | | :column="standardColumns" |
| | | :tableData="standardTableData" |
| | | :page="page" |
| | | :isSelection="false" |
| | | :rowClassName="rowClassNameCenter" |
| | | :tableLoading="tableLoading" |
| | | :rowClick="handleTableRowClick" |
| | | @pagination="handlePagination" |
| | | :total="page.total"> |
| | | <template #standardNoCell="{ row }"> |
| | | <span class="clickable-link" |
| | | @click="handleStandardRowClick(row)"> |
| | | {{ row.standardNo }} |
| | | </span> |
| | | </template> |
| | | <!-- 表头æç´¢ --> |
| | | <template #standardNoHeader> |
| | | <el-input v-model="searchForm.standardNo" |
| | | placeholder="æ åç¼å·" |
| | | clearable |
| | | size="small" |
| | | @change="handleQuery" |
| | | @clear="handleQuery" /> |
| | | </template> |
| | | <template #standardNameHeader> |
| | | <el-input v-model="searchForm.standardName" |
| | | placeholder="æ ååç§°" |
| | | clearable |
| | | size="small" |
| | | @change="handleQuery" |
| | | @clear="handleQuery" /> |
| | | </template> |
| | | <template #inspectTypeHeader> |
| | | <el-select v-model="searchForm.inspectType" |
| | | placeholder="ç±»å«" |
| | | clearable |
| | | size="small" |
| | | style="width: 120px" |
| | | @change="handleQuery" |
| | | @clear="handleQuery"> |
| | | <el-option label="åæææ£éª" |
| | | value="0" /> |
| | | <el-option label="è¿ç¨æ£éª" |
| | | value="1" /> |
| | | <el-option label="åºåæ£éª" |
| | | value="2" /> |
| | | </el-select> |
| | | </template> |
| | | <template #stateHeader> |
| | | <el-select v-model="searchForm.state" |
| | | placeholder="ç¶æ" |
| | | clearable |
| | | size="small" |
| | | style="width: 110px" |
| | | @change="handleQuery" |
| | | @clear="handleQuery"> |
| | | <el-option label="è稿" |
| | | value="0" /> |
| | | <el-option label="éè¿" |
| | | value="1" /> |
| | | <el-option label="æ¤é" |
| | | value="2" /> |
| | | </el-select> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | </el-col> |
| | | |
| | | <!-- å³ä¾§ï¼ç»å®å表 --> |
| | | <el-col :xs="24" :sm="24" :md="12" :lg="10" :xl="10" class="right-col"> |
| | | <el-col :xs="24" |
| | | :sm="24" |
| | | :md="12" |
| | | :lg="10" |
| | | :xl="10" |
| | | class="right-col"> |
| | | <div class="panel right-panel"> |
| | | <div class="right-header"> |
| | | <div class="title">ç»å®å
³ç³»</div> |
| | | <div class="desc" v-if="currentStandard"> |
| | | å½åæ£æµæ åç¼å·ï¼<span class="link-text">{{ currentStandard.standardNo }}</span> |
| | | </div> |
| | | <div class="desc" v-else>è¯·éæ©å·¦ä¾§æ£æµæ å</div> |
| | | </div> |
| | | |
| | | <div class="right-toolbar"> |
| | | <el-button type="primary" :disabled="!currentStandard" @click="openBindingDialog">æ·»å ç»å®</el-button> |
| | | <el-button type="danger" plain :disabled="!currentStandard" @click="handleBatchUnbind">å é¤</el-button> |
| | | </div> |
| | | |
| | | <el-table |
| | | v-loading="bindingLoading" |
| | | :data="bindingTableData" |
| | | border |
| | | :row-class-name="() => 'row-center'" |
| | | class="center-table" |
| | | style="width: 100%" |
| | | height="calc(100vh - 220px)" |
| | | @selection-change="handleBindingSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="48" align="center" /> |
| | | <el-table-column type="index" label="åºå·" width="60" align="center" /> |
| | | <el-table-column prop="productName" label="产ååç§°" min-width="140" /> |
| | | <el-table-column label="æä½" width="120" fixed="right" align="center"> |
| | | <template #default="{ row }"> |
| | | <el-button link type="danger" size="small" @click="handleUnbind(row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <div class="right-header"> |
| | | <div class="title">ç»å®å
³ç³»</div> |
| | | <div class="desc" |
| | | v-if="currentStandard"> |
| | | å½åæ£æµæ åç¼å·ï¼<span class="link-text">{{ currentStandard.standardNo }}</span> |
| | | </div> |
| | | <div class="desc" |
| | | v-else>è¯·éæ©å·¦ä¾§æ£æµæ å</div> |
| | | </div> |
| | | <div class="right-toolbar"> |
| | | <el-button type="primary" |
| | | :disabled="!currentStandard" |
| | | @click="openBindingDialog">æ·»å ç»å®</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | :disabled="!currentStandard" |
| | | @click="handleBatchUnbind">å é¤</el-button> |
| | | </div> |
| | | <el-table v-loading="bindingLoading" |
| | | :data="bindingTableData" |
| | | border |
| | | :row-class-name="() => 'row-center'" |
| | | class="center-table" |
| | | style="width: 100%" |
| | | height="calc(100vh - 220px)" |
| | | @selection-change="handleBindingSelectionChange"> |
| | | <el-table-column type="selection" |
| | | width="48" |
| | | align="center" /> |
| | | <el-table-column type="index" |
| | | label="åºå·" |
| | | width="60" |
| | | align="center" /> |
| | | <el-table-column prop="productName" |
| | | label="产ååç§°" |
| | | min-width="140" /> |
| | | <el-table-column label="æä½" |
| | | width="120" |
| | | fixed="right" |
| | | align="center"> |
| | | <template #default="{ row }"> |
| | | <el-button link |
| | | type="danger" |
| | | size="small" |
| | | @click="handleUnbind(row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- æ·»å ç»å®å¼¹æ¡ --> |
| | | <el-dialog |
| | | v-model="bindingDialogVisible" |
| | | title="æ·»å ç»å®" |
| | | width="520px" |
| | | @close="closeBindingDialog" |
| | | > |
| | | <el-dialog v-model="bindingDialogVisible" |
| | | title="æ·»å ç»å®" |
| | | width="520px" |
| | | @close="closeBindingDialog"> |
| | | <el-form label-width="100px"> |
| | | <el-form-item label="产å"> |
| | | <el-tree-select |
| | | v-model="selectedProductIds" |
| | | multiple |
| | | collapse-tags |
| | | collapse-tags-tooltip |
| | | placeholder="è¯·éæ©äº§åï¼å¯å¤éï¼" |
| | | clearable |
| | | check-strictly |
| | | :data="productOptions" |
| | | :render-after-expand="false" |
| | | style="width: 100%" |
| | | /> |
| | | <el-button type="primary" |
| | | @click="openProductSelectDialog">éæ©äº§å</el-button> |
| | | <div class="selected-products mt-2" |
| | | v-if="selectedProducts.length > 0"> |
| | | <el-tag v-for="product in selectedProducts" |
| | | :key="product.id" |
| | | closable |
| | | @close="removeSelectedProduct(product.id)" |
| | | class="mr-2 mb-2"> |
| | | {{ product.productName }} - {{ product.model }} |
| | | </el-tag> |
| | | </div> |
| | | <div v-else |
| | | class="text-gray-400"></div> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="closeBindingDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitBinding">ç¡®å®</el-button> |
| | | <el-button type="primary" |
| | | :disabled="selectedProducts.length === 0" |
| | | @click="submitBinding">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- 产åéæ©å¯¹è¯æ¡ --> |
| | | <ProductSelectDialog v-model="productSelectDialogVisible" |
| | | :single="false" |
| | | @confirm="handleProductSelect" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search } from '@element-plus/icons-vue' |
| | | import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue' |
| | | import { ElMessageBox } from 'element-plus' |
| | | import PIMTable from '@/components/PIMTable/PIMTable.vue' |
| | | import { productTreeList } from '@/api/basicData/product.js' |
| | | import { |
| | | qualityTestStandardListPage |
| | | } from '@/api/qualityManagement/metricMaintenance.js' |
| | | import { productProcessListPage } from '@/api/basicData/productProcess.js' |
| | | import { |
| | | qualityTestStandardBindingList, |
| | | qualityTestStandardBindingAdd, |
| | | qualityTestStandardBindingDel |
| | | } from '@/api/qualityManagement/qualityTestStandardBinding.js' |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import { qualityTestStandardListPage } from "@/api/qualityManagement/metricMaintenance.js"; |
| | | import { productProcessListPage } from "@/api/basicData/productProcess.js"; |
| | | import { |
| | | qualityTestStandardBindingList, |
| | | qualityTestStandardBindingAdd, |
| | | qualityTestStandardBindingDel, |
| | | } from "@/api/qualityManagement/qualityTestStandardBinding.js"; |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | // 左侧æ ååè¡¨ï¼æ´è¡å
容å±
ä¸ï¼é
åæ ·å¼ï¼ |
| | | const rowClassNameCenter = () => 'row-center' |
| | | // 左侧æ ååè¡¨ï¼æ´è¡å
容å±
ä¸ï¼é
åæ ·å¼ï¼ |
| | | const rowClassNameCenter = () => "row-center"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | standardNo: '', |
| | | standardName: '', |
| | | state: '', |
| | | inspectType: '' |
| | | } |
| | | }) |
| | | const { searchForm } = toRefs(data) |
| | | const data = reactive({ |
| | | searchForm: { |
| | | standardNo: "", |
| | | standardName: "", |
| | | state: "", |
| | | inspectType: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | // 左侧 |
| | | const standardTableData = ref([]) |
| | | const tableLoading = ref(false) |
| | | const page = reactive({ current: 1, size: 10, total: 0 }) |
| | | // 左侧 |
| | | const standardTableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ current: 1, size: 10, total: 0 }); |
| | | |
| | | // å·¥åºä¸æï¼ç¨äºåè¡¨åæ¾ï¼ |
| | | const processOptions = ref([]) |
| | | // å·¥åºä¸æï¼ç¨äºåè¡¨åæ¾ï¼ |
| | | const processOptions = ref([]); |
| | | |
| | | const getProcessList = async () => { |
| | | try { |
| | | const res = await productProcessListPage({ current: 1, size: 1000 }) |
| | | if (res?.code === 200) { |
| | | const records = res?.data?.records || [] |
| | | processOptions.value = records.map((item) => ({ |
| | | label: item.processName || item.name || item.label, |
| | | value: item.id || item.processId || item.value |
| | | })) |
| | | const getProcessList = async () => { |
| | | try { |
| | | const res = await productProcessListPage({ current: 1, size: 1000 }); |
| | | if (res?.code === 200) { |
| | | const records = res?.data?.records || []; |
| | | processOptions.value = records.map(item => ({ |
| | | label: item.processName || item.name || item.label, |
| | | value: item.id || item.processId || item.value, |
| | | })); |
| | | } |
| | | } catch (error) { |
| | | console.error("è·åå·¥åºå表失败:", error); |
| | | } |
| | | } catch (error) { |
| | | console.error('è·åå·¥åºå表失败:', error) |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const standardColumns = ref([ |
| | | { label: 'æ åç¼å·', prop: 'standardNo', dataType: 'slot', slot: 'standardNoCell', minWidth: 160, align: 'center', headerSlot: 'standardNoHeader' }, |
| | | { label: 'æ ååç§°', prop: 'standardName', minWidth: 180, align: 'center', headerSlot: 'standardNameHeader' }, |
| | | { |
| | | label: 'ç±»å«', |
| | | prop: 'inspectType', |
| | | headerSlot: 'inspectTypeHeader', |
| | | align: 'center', |
| | | dataType: 'tag', |
| | | formatData: (val) => { |
| | | const map = { 0: 'åæææ£éª', 1: 'è¿ç¨æ£éª', 2: 'åºåæ£éª' } |
| | | return map[val] || val |
| | | } |
| | | }, |
| | | { |
| | | label: 'å·¥åº', |
| | | prop: 'processId', |
| | | align: 'center', |
| | | dataType: 'tag', |
| | | formatData: (val) => { |
| | | const target = processOptions.value.find( |
| | | (item) => String(item.value) === String(val) |
| | | ) |
| | | return target?.label || val |
| | | } |
| | | }, |
| | | { |
| | | label: '夿³¨', |
| | | prop: 'remark', |
| | | minWidth: 160, |
| | | align: 'center' |
| | | } |
| | | // { |
| | | // label: 'ç¶æ', |
| | | // prop: 'state', |
| | | // headerSlot: 'stateHeader', |
| | | // dataType: 'tag', |
| | | // formatData: (val) => { |
| | | // const map = { 0: 'è稿', 1: 'éè¿', 2: 'æ¤é' } |
| | | // return map[val] || val |
| | | // }, |
| | | // formatType: (val) => { |
| | | // if (val == 1) return 'success' |
| | | // if (val == 2) return 'warning' |
| | | // return 'info' |
| | | // } |
| | | // } |
| | | ]) |
| | | const standardColumns = ref([ |
| | | { |
| | | label: "æ åç¼å·", |
| | | prop: "standardNo", |
| | | dataType: "slot", |
| | | slot: "standardNoCell", |
| | | minWidth: 160, |
| | | align: "center", |
| | | headerSlot: "standardNoHeader", |
| | | }, |
| | | { |
| | | label: "æ ååç§°", |
| | | prop: "standardName", |
| | | minWidth: 180, |
| | | align: "center", |
| | | headerSlot: "standardNameHeader", |
| | | }, |
| | | { |
| | | label: "ç±»å«", |
| | | prop: "inspectType", |
| | | headerSlot: "inspectTypeHeader", |
| | | align: "center", |
| | | dataType: "tag", |
| | | formatData: val => { |
| | | const map = { 0: "åæææ£éª", 1: "è¿ç¨æ£éª", 2: "åºåæ£éª" }; |
| | | return map[val] || val; |
| | | }, |
| | | }, |
| | | { |
| | | label: "å·¥åº", |
| | | prop: "processId", |
| | | align: "center", |
| | | dataType: "tag", |
| | | formatData: val => { |
| | | const target = processOptions.value.find( |
| | | item => String(item.value) === String(val) |
| | | ); |
| | | return target?.label || val; |
| | | }, |
| | | }, |
| | | { |
| | | label: "夿³¨", |
| | | prop: "remark", |
| | | minWidth: 160, |
| | | align: "center", |
| | | }, |
| | | // { |
| | | // label: 'ç¶æ', |
| | | // prop: 'state', |
| | | // headerSlot: 'stateHeader', |
| | | // dataType: 'tag', |
| | | // formatData: (val) => { |
| | | // const map = { 0: 'è稿', 1: 'éè¿', 2: 'æ¤é' } |
| | | // return map[val] || val |
| | | // }, |
| | | // formatType: (val) => { |
| | | // if (val == 1) return 'success' |
| | | // if (val == 2) return 'warning' |
| | | // return 'info' |
| | | // } |
| | | // } |
| | | ]); |
| | | |
| | | const currentStandard = ref(null) |
| | | const currentStandard = ref(null); |
| | | |
| | | // å³ä¾§ç»å® |
| | | const bindingTableData = ref([]) |
| | | const bindingLoading = ref(false) |
| | | const bindingSelectedRows = ref([]) |
| | | const bindingDialogVisible = ref(false) |
| | | // å³ä¾§ç»å® |
| | | const bindingTableData = ref([]); |
| | | const bindingLoading = ref(false); |
| | | const bindingSelectedRows = ref([]); |
| | | const bindingDialogVisible = ref(false); |
| | | |
| | | // äº§åæ ï¼ç¨äºç»å®éæ©ï¼ |
| | | const productOptions = ref([]) |
| | | const selectedProductIds = ref([]) |
| | | // 产åéæ© |
| | | const productSelectDialogVisible = ref(false); |
| | | const selectedProducts = ref([]); |
| | | |
| | | const getProductOptions = async () => { |
| | | // é¿å
éå¤è¯·æ± |
| | | if (productOptions.value?.length) return |
| | | const res = await productTreeList() |
| | | productOptions.value = convertIdToValue(Array.isArray(res) ? res : []) |
| | | } |
| | | const openProductSelectDialog = () => { |
| | | productSelectDialogVisible.value = true; |
| | | }; |
| | | |
| | | function convertIdToValue(data) { |
| | | return (data || []).map((item) => { |
| | | const { id, children, ...rest } = item |
| | | const newItem = { |
| | | ...rest, |
| | | value: id |
| | | } |
| | | if (children && children.length > 0) { |
| | | newItem.children = convertIdToValue(children) |
| | | } |
| | | return newItem |
| | | }) |
| | | } |
| | | const handleProductSelect = products => { |
| | | // å并已鿩ç产åï¼é¿å
éå¤ |
| | | const existingIds = new Set(selectedProducts.value.map(p => p.id)); |
| | | const newProducts = products.filter(p => !existingIds.has(p.id)); |
| | | selectedProducts.value = [...selectedProducts.value, ...newProducts]; |
| | | }; |
| | | |
| | | const handleQuery = () => { |
| | | page.current = 1 |
| | | getStandardList() |
| | | } |
| | | const removeSelectedProduct = id => { |
| | | selectedProducts.value = selectedProducts.value.filter(p => p.id !== id); |
| | | }; |
| | | |
| | | const handlePagination = (obj) => { |
| | | page.current = obj.page |
| | | page.size = obj.limit |
| | | getStandardList() |
| | | } |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getStandardList(); |
| | | }; |
| | | |
| | | const getStandardList = () => { |
| | | tableLoading.value = true |
| | | qualityTestStandardListPage({ |
| | | ...searchForm.value, |
| | | current: page.current, |
| | | size: page.size, |
| | | state: 1 |
| | | }) |
| | | .then((res) => { |
| | | const records = res?.data?.records || [] |
| | | standardTableData.value = records |
| | | page.total = res?.data?.total || records.length |
| | | const handlePagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getStandardList(); |
| | | }; |
| | | |
| | | const getStandardList = () => { |
| | | tableLoading.value = true; |
| | | qualityTestStandardListPage({ |
| | | ...searchForm.value, |
| | | current: page.current, |
| | | size: page.size, |
| | | state: 1, |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false |
| | | }) |
| | | } |
| | | .then(res => { |
| | | const records = res?.data?.records || []; |
| | | standardTableData.value = records; |
| | | page.total = res?.data?.total || records.length; |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // è¡¨æ ¼è¡ç¹å»ï¼å è½½å³ä¾§ç»å®å表 |
| | | const handleTableRowClick = (row) => { |
| | | currentStandard.value = row |
| | | loadBindingList() |
| | | } |
| | | // è¡¨æ ¼è¡ç¹å»ï¼å è½½å³ä¾§ç»å®å表 |
| | | const handleTableRowClick = row => { |
| | | currentStandard.value = row; |
| | | loadBindingList(); |
| | | }; |
| | | |
| | | // 左侧è¡ç¹å»ï¼å è½½å³ä¾§ç»å®å表ï¼ä¿çç¨äºæ åç¼å·åçç¹å»ï¼ |
| | | const handleStandardRowClick = (row) => { |
| | | currentStandard.value = row |
| | | loadBindingList() |
| | | } |
| | | // 左侧è¡ç¹å»ï¼å è½½å³ä¾§ç»å®å表ï¼ä¿çç¨äºæ åç¼å·åçç¹å»ï¼ |
| | | const handleStandardRowClick = row => { |
| | | currentStandard.value = row; |
| | | loadBindingList(); |
| | | }; |
| | | |
| | | const loadBindingList = () => { |
| | | if (!currentStandard.value?.id) { |
| | | bindingTableData.value = [] |
| | | return |
| | | } |
| | | bindingLoading.value = true |
| | | qualityTestStandardBindingList({ testStandardId: currentStandard.value.id }) |
| | | .then((res) => { |
| | | const base = res?.data || [] |
| | | // å°å½åæ åçå·¥åºå夿³¨å¸¦å°ç»å®å表ä¸å±ç¤º |
| | | bindingTableData.value = base.map((item) => ({ |
| | | ...item, |
| | | processId: currentStandard.value?.processId, |
| | | remark: currentStandard.value?.remark |
| | | })) |
| | | }) |
| | | .finally(() => { |
| | | bindingLoading.value = false |
| | | }) |
| | | } |
| | | const loadBindingList = () => { |
| | | if (!currentStandard.value?.id) { |
| | | bindingTableData.value = []; |
| | | return; |
| | | } |
| | | bindingLoading.value = true; |
| | | qualityTestStandardBindingList({ testStandardId: currentStandard.value.id }) |
| | | .then(res => { |
| | | const base = res?.data || []; |
| | | // å°å½åæ åçå·¥åºå夿³¨å¸¦å°ç»å®å表ä¸å±ç¤º |
| | | bindingTableData.value = base.map(item => ({ |
| | | ...item, |
| | | processId: currentStandard.value?.processId, |
| | | remark: currentStandard.value?.remark, |
| | | })); |
| | | }) |
| | | .finally(() => { |
| | | bindingLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | const handleBindingSelectionChange = (selection) => { |
| | | bindingSelectedRows.value = selection |
| | | } |
| | | const handleBindingSelectionChange = selection => { |
| | | bindingSelectedRows.value = selection; |
| | | }; |
| | | |
| | | const openBindingDialog = () => { |
| | | if (!currentStandard.value?.id) return |
| | | selectedProductIds.value = [] |
| | | getProductOptions() |
| | | bindingDialogVisible.value = true |
| | | } |
| | | const openBindingDialog = () => { |
| | | if (!currentStandard.value?.id) return; |
| | | selectedProducts.value = []; |
| | | bindingDialogVisible.value = true; |
| | | }; |
| | | |
| | | const closeBindingDialog = () => { |
| | | bindingDialogVisible.value = false |
| | | } |
| | | const closeBindingDialog = () => { |
| | | bindingDialogVisible.value = false; |
| | | selectedProducts.value = []; |
| | | }; |
| | | |
| | | const submitBinding = async () => { |
| | | const testStandardId = currentStandard.value?.id |
| | | if (!testStandardId) return |
| | | const ids = (selectedProductIds.value || []).filter(Boolean) |
| | | if (!ids.length) { |
| | | proxy.$message.warning('è¯·éæ©äº§å') |
| | | return |
| | | } |
| | | const payload = ids.map((pid) => ({ |
| | | productId: pid, |
| | | testStandardId |
| | | })) |
| | | await qualityTestStandardBindingAdd(payload) |
| | | proxy.$message.success('æ·»å æå') |
| | | bindingDialogVisible.value = false |
| | | loadBindingList() |
| | | } |
| | | const submitBinding = async () => { |
| | | const testStandardId = currentStandard.value?.id; |
| | | if (!testStandardId) return; |
| | | const ids = (selectedProducts.value || []).map(p => p.id).filter(Boolean); |
| | | if (!ids.length) { |
| | | ElMessage.warning("è¯·éæ©äº§å"); |
| | | return; |
| | | } |
| | | const payload = ids.map(pid => ({ |
| | | productId: pid, |
| | | testStandardId, |
| | | })); |
| | | await qualityTestStandardBindingAdd(payload); |
| | | ElMessage.success("æ·»å æå"); |
| | | bindingDialogVisible.value = false; |
| | | selectedProducts.value = []; |
| | | loadBindingList(); |
| | | }; |
| | | |
| | | const handleUnbind = async (row) => { |
| | | const id = row?.id ?? row?.qualityTestStandardBindingId |
| | | if (id == null || id === '') return |
| | | try { |
| | | await ElMessageBox.confirm('确认å é¤è¯¥ç»å®ï¼', 'æç¤º', { type: 'warning' }) |
| | | } catch { |
| | | return |
| | | } |
| | | try { |
| | | await qualityTestStandardBindingDel([id]) |
| | | proxy.$message.success('å 餿å') |
| | | loadBindingList() |
| | | } catch (err) { |
| | | console.error('å é¤ç»å®å¤±è´¥:', err) |
| | | proxy.$message?.error(err?.message || 'å é¤å¤±è´¥') |
| | | } |
| | | } |
| | | const handleUnbind = async row => { |
| | | const id = row?.id ?? row?.qualityTestStandardBindingId; |
| | | if (id == null || id === "") return; |
| | | try { |
| | | await ElMessageBox.confirm("确认å é¤è¯¥ç»å®ï¼", "æç¤º", { type: "warning" }); |
| | | } catch { |
| | | return; |
| | | } |
| | | try { |
| | | await qualityTestStandardBindingDel([id]); |
| | | proxy.$message.success("å 餿å"); |
| | | loadBindingList(); |
| | | } catch (err) { |
| | | console.error("å é¤ç»å®å¤±è´¥:", err); |
| | | proxy.$message?.error(err?.message || "å é¤å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | const handleBatchUnbind = async () => { |
| | | if (!bindingSelectedRows.value.length) { |
| | | proxy.$message.warning('è¯·éæ©æ°æ®') |
| | | return |
| | | } |
| | | const ids = bindingSelectedRows.value |
| | | .map((i) => i?.id ?? i?.qualityTestStandardBindingId) |
| | | .filter((id) => id != null && id !== '') |
| | | if (!ids.length) { |
| | | proxy.$message.warning('é䏿°æ®ç¼ºå°ææ id') |
| | | return |
| | | } |
| | | try { |
| | | await ElMessageBox.confirm('éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼', 'å é¤æç¤º', { type: 'warning' }) |
| | | } catch { |
| | | return |
| | | } |
| | | try { |
| | | await qualityTestStandardBindingDel(ids) |
| | | proxy.$message.success('å 餿å') |
| | | loadBindingList() |
| | | } catch (err) { |
| | | console.error('æ¹éå é¤ç»å®å¤±è´¥:', err) |
| | | proxy.$message?.error(err?.message || 'å é¤å¤±è´¥') |
| | | } |
| | | } |
| | | const handleBatchUnbind = async () => { |
| | | if (!bindingSelectedRows.value.length) { |
| | | proxy.$message.warning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | const ids = bindingSelectedRows.value |
| | | .map(i => i?.id ?? i?.qualityTestStandardBindingId) |
| | | .filter(id => id != null && id !== ""); |
| | | if (!ids.length) { |
| | | proxy.$message.warning("é䏿°æ®ç¼ºå°ææ id"); |
| | | return; |
| | | } |
| | | try { |
| | | await ElMessageBox.confirm( |
| | | "éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", |
| | | "å é¤æç¤º", |
| | | { type: "warning" } |
| | | ); |
| | | } catch { |
| | | return; |
| | | } |
| | | try { |
| | | await qualityTestStandardBindingDel(ids); |
| | | proxy.$message.success("å 餿å"); |
| | | loadBindingList(); |
| | | } catch (err) { |
| | | console.error("æ¹éå é¤ç»å®å¤±è´¥:", err); |
| | | proxy.$message?.error(err?.message || "å é¤å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getStandardList() |
| | | getProcessList() |
| | | }) |
| | | onMounted(() => { |
| | | getStandardList(); |
| | | getProcessList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .metric-binding { |
| | | padding: 0; |
| | | } |
| | | .metric-binding { |
| | | padding: 0; |
| | | } |
| | | |
| | | .metric-binding-row { |
| | | width: 100%; |
| | | } |
| | | .metric-binding-row { |
| | | width: 100%; |
| | | } |
| | | |
| | | .metric-binding-row .left-col, |
| | | .metric-binding-row .right-col { |
| | | margin-bottom: 16px; |
| | | } |
| | | .metric-binding-row .left-col, |
| | | .metric-binding-row .right-col { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .metric-binding-row .panel { |
| | | background: #ffffff; |
| | | padding: 16px; |
| | | box-sizing: border-box; |
| | | height: 100%; |
| | | min-height: 400px; |
| | | } |
| | | .metric-binding-row .panel { |
| | | background: #ffffff; |
| | | padding: 16px; |
| | | box-sizing: border-box; |
| | | height: 100%; |
| | | min-height: 400px; |
| | | } |
| | | |
| | | .left-panel, |
| | | .right-panel { |
| | | height: 100%; |
| | | } |
| | | .left-panel, |
| | | .right-panel { |
| | | height: 100%; |
| | | } |
| | | |
| | | .toolbar { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 12px; |
| | | } |
| | | .toolbar { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .toolbar-right { |
| | | flex-shrink: 0; |
| | | } |
| | | .toolbar-right { |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .right-header { |
| | | display: flex; |
| | | align-items: baseline; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | .right-header { |
| | | display: flex; |
| | | align-items: baseline; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .right-header .title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | } |
| | | .right-header .title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .right-header .desc { |
| | | font-size: 13px; |
| | | color: #666; |
| | | } |
| | | .right-header .desc { |
| | | font-size: 13px; |
| | | color: #666; |
| | | } |
| | | |
| | | .right-toolbar { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | margin-bottom: 10px; |
| | | } |
| | | .right-toolbar { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .link-text { |
| | | color: #409eff; |
| | | cursor: default; |
| | | } |
| | | .link-text { |
| | | color: #409eff; |
| | | cursor: default; |
| | | } |
| | | |
| | | .clickable-link { |
| | | color: #409eff; |
| | | cursor: pointer; |
| | | } |
| | | .clickable-link { |
| | | color: #409eff; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .clickable-link:hover { |
| | | text-decoration: underline; |
| | | } |
| | | .clickable-link:hover { |
| | | text-decoration: underline; |
| | | } |
| | | |
| | | :deep(.row-center td) { |
| | | text-align: center !important; |
| | | } |
| | | :deep(.row-center td) { |
| | | text-align: center !important; |
| | | } |
| | | |
| | | /* el-table 表头/å
容ç»ä¸å±
ä¸ï¼row-class-name ä¸ä½ç¨äºè¡¨å¤´ï¼ */ |
| | | :deep(.center-table .el-table__header-wrapper th .cell) { |
| | | text-align: center !important; |
| | | } |
| | | :deep(.center-table .el-table__body-wrapper td .cell) { |
| | | text-align: center !important; |
| | | } |
| | | /* el-table 表头/å
容ç»ä¸å±
ä¸ï¼row-class-name ä¸ä½ç¨äºè¡¨å¤´ï¼ */ |
| | | :deep(.center-table .el-table__header-wrapper th .cell) { |
| | | text-align: center !important; |
| | | } |
| | | :deep(.center-table .el-table__body-wrapper td .cell) { |
| | | text-align: center !important; |
| | | } |
| | | |
| | | /* PIMTable 表头å±
ä¸ */ |
| | | :deep(.lims-table .pim-table-header-cell) { |
| | | text-align: center; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | /* PIMTable 表头å±
ä¸ */ |
| | | :deep(.lims-table .pim-table-header-cell) { |
| | | text-align: center; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | :deep(.lims-table .pim-table-header-title) { |
| | | text-align: center; |
| | | width: 100%; |
| | | } |
| | | :deep(.lims-table .pim-table-header-title) { |
| | | text-align: center; |
| | | width: 100%; |
| | | } |
| | | |
| | | :deep(.lims-table .pim-table-header-extra) { |
| | | width: 100%; |
| | | margin-top: 4px; |
| | | } |
| | | :deep(.lims-table .pim-table-header-extra) { |
| | | width: 100%; |
| | | margin-top: 4px; |
| | | } |
| | | </style> |