| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" |
| | | :inline="true"> |
| | | <!-- ç®åçæç´¢æ¡ä»¶ --> |
| | | <el-form-item label="产ååç§°:"> |
| | | <el-input v-model="searchForm.productName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | style="width: 160px;" |
| | | @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="è®¡åæ¥æèå´:"> |
| | | <el-date-picker v-model="searchForm.dateRange" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 240px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¸åç¶æ:"> |
| | | <el-select v-model="searchForm.status" |
| | | placeholder="è¯·éæ©ç¶æ" |
| | | clearable |
| | | filterable |
| | | style="width: 100px"> |
| | | <el-option label="å¾
ä¸å" |
| | | value="0" /> |
| | | <el-option label="é¨åä¸å" |
| | | value="1" /> |
| | | <el-option label="å·²ä¸å" |
| | | value="2" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <!-- å±å¼çæç´¢æ¡ä»¶ --> |
| | | <template v-if="searchFormExpanded"> |
| | | <el-form-item label="客æ·åç§°:"> |
| | | <el-input v-model="searchForm.customerName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | style="width: 160px;" |
| | | @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="产åè§æ ¼:"> |
| | | <el-input v-model="searchForm.model" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | style="width: 160px;" |
| | | @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç©æç¼ç :"> |
| | | <el-input v-model="searchForm.materialCode" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | style="width: 160px;" |
| | | @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç³è¯·åç¼å·:"> |
| | | <el-input v-model="searchForm.applyNo" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | style="width: 160px;" |
| | | @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | </template> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="handleQuery">æç´¢</el-button> |
| | | <el-button type="info" |
| | | @click="handleReset">éç½®</el-button> |
| | | <el-button type="primary" |
| | | @click="handleAdd">æ°å¢</el-button> |
| | | <el-button type="warning" |
| | | @click="getLoadProdData" |
| | | :loading="loadProdDataLoading">æåæ°æ®</el-button> |
| | | <el-button type="warning" |
| | | @click="handleMerge">åå¹¶ä¸å</el-button> |
| | | <el-button type="warning" |
| | | @click="handleImport">导å
¥</el-button> |
| | | <el-button type="warning" |
| | | @click="handleExport">导åº</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div> |
| | | </div> |
| | | </div> |
| | | <div class="search-header"> |
| | | <el-button type="text" |
| | | @click="toggleSearchForm"> |
| | | <el-icon> |
| | | <ArrowUp v-if="searchFormExpanded" /> |
| | | <ArrowDown v-else /> |
| | | </el-icon> |
| | | {{ searchFormExpanded ? 'æ¶èµ·æç´¢æ¡ä»¶' : 'å±å¼æç´¢æ¡ä»¶' }} |
| | | </el-button> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | height="calc(100vh - 350px)" |
| | | :tableLoading="tableLoading" |
| | | :isSelection="true" |
| | | :selectable="isSelectable" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="pagination"> |
| | | <template #quantity="{ row }"> |
| | | {{ row.quantity || '-' }}<span style="color:rgb(63, 95, 211)"> å</span> |
| | | </template> |
| | | <template #volume="{ row }"> |
| | | {{ row.volume || '-' }}<span style="color:rgba(12, 46, 40, 0.76)"> æ¹</span> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | <!-- åå¹¶ä¸åå¼¹çª --> |
| | | <el-dialog v-model="isShowNewModal" |
| | | destroy-on-close |
| | | title="åå¹¶ä¸å" |
| | | width="600px"> |
| | | <el-form :model="mergeForm" |
| | | label-width="120px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="10"> |
| | | <el-form-item label="ç©æç¼ç "> |
| | | <div class="info-display">{{ mergeForm.materialCode || '-' }}</div> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="10"> |
| | | <el-form-item label="产ååç§°"> |
| | | <el-tag class="info-display">{{ mergeForm.productName || '-' }}</el-tag> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="10"> |
| | | <el-form-item label="产åè§æ ¼"> |
| | | <div class="info-display">{{ mergeForm.model || '-' }}</div> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="10"> |
| | | <el-form-item label="é¿*宽*é«"> |
| | | <div class="info-display">{{ mergeForm.length || '-' }}*{{ mergeForm.width || '-' }}*{{ mergeForm.height || '-' }}</div> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="计å宿æ¶é´"> |
| | | <el-date-picker v-model="mergeForm.planCompleteTime" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="强度" |
| | | v-if="mergeForm.productName === 'ç å'"> |
| | | <div v-if="strengthError" |
| | | class="strength-error" |
| | | style="color: red; margin-bottom: 8px;">{{ strengthError }}</div> |
| | | <el-select v-model="mergeForm.strength" |
| | | placeholder="è¯·éæ©å¼ºåº¦" |
| | | style="width: 100%" |
| | | required> |
| | | <el-option v-for="item in block_strength" |
| | | :key="item.id" |
| | | :label="item.label" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="çäº§æ¹æ°"> |
| | | <el-input-number v-model="mergeForm.totalAssignedQuantity" |
| | | :min="0" |
| | | :max="sumAssignedQuantity" |
| | | @change="onBlur" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <!-- <el-form-item label="夿³¨"> |
| | | <el-input v-model="mergeForm.remark" |
| | | type="textarea" /> |
| | | </el-form-item> --> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="isShowNewModal = false">åæ¶</el-button> |
| | | <el-button type="primary" |
| | | @click="handleMergeSubmit">ç¡®å®ä¸å</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- 导å
¥å¼¹çª --> |
| | | <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" /> |
| | | <!-- æ°å¢/ç¼è¾å¼¹çª --> |
| | | <el-dialog v-model="dialogVisible" |
| | | destroy-on-close |
| | | :title="operationType === 'add' ? 'æ°å¢ç产计å' : 'ç¼è¾ç产计å'" |
| | | width="600px"> |
| | | <el-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="120px"> |
| | | <el-form-item label="ç³è¯·åç¼å·" |
| | | prop="applyNo"> |
| | | <el-input v-model="form.applyNo" |
| | | placeholder="请è¾å
¥ç³è¯·åç¼å·" /> |
| | | </el-form-item> |
| | | <el-form-item label="客æ·åç§°" |
| | | prop="customerName"> |
| | | <el-input v-model="form.customerName" |
| | | placeholder="请è¾å
¥å®¢æ·åç§°" /> |
| | | </el-form-item> |
| | | <el-form-item label="产ååç§°" |
| | | prop="productMaterialId"> |
| | | <el-tree-select v-model="form.productMaterialId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | :data="productOptions" |
| | | :render-after-expand="false" |
| | | filterable |
| | | @change="handleProductChange" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="产åè§æ ¼" |
| | | prop="productMaterialSkuId"> |
| | | <el-select v-model="form.productMaterialSkuId" |
| | | @change="handleChangeSpecification" |
| | | filterable |
| | | placeholder="è¯·éæ©"> |
| | | <el-option v-for="item in specificationOptions" |
| | | :key="item.id" |
| | | :label="item.model" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="åæ°" |
| | | prop="quantity"> |
| | | <el-input-number v-model="form.quantity" |
| | | :min="0" |
| | | placeholder="请è¾å
¥åæ°" /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¹æ°" |
| | | prop="volume"> |
| | | <el-input-number v-model="form.volume" |
| | | :min="0" |
| | | placeholder="请è¾å
¥æ¹æ°" /> |
| | | </el-form-item> |
| | | <el-form-item label="é¿" |
| | | prop="length"> |
| | | <el-input-number v-model="form.length" |
| | | :min="0" |
| | | placeholder="请è¾å
¥é¿åº¦" /> |
| | | </el-form-item> |
| | | <el-form-item label="宽" |
| | | prop="width"> |
| | | <el-input-number v-model="form.width" |
| | | :min="0" |
| | | placeholder="请è¾å
¥å®½åº¦" /> |
| | | </el-form-item> |
| | | <el-form-item label="é«" |
| | | prop="height"> |
| | | <el-input-number v-model="form.height" |
| | | :min="0" |
| | | placeholder="请è¾å
¥é«åº¦" /> |
| | | </el-form-item> |
| | | <el-form-item label="计åå¼å§æ¥æ" |
| | | prop="startDate"> |
| | | <el-date-picker v-model="form.startDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="è¯·éæ©è®¡åå¼å§æ¥æ" /> |
| | | </el-form-item> |
| | | <el-form-item label="计åç»ææ¥æ" |
| | | prop="endDate"> |
| | | <el-date-picker v-model="form.endDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="è¯·éæ©è®¡åç»ææ¥æ" /> |
| | | </el-form-item> |
| | | <el-form-item label="强度" |
| | | prop="strength" |
| | | v-if="form.productName === 'ç å'"> |
| | | <el-select v-model="form.strength" |
| | | placeholder="è¯·éæ©å¼ºåº¦" |
| | | style="width: 100%"> |
| | | <el-option v-for="item in block_strength" |
| | | :key="item.label" |
| | | :label="item.label" |
| | | :value="item.label" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="夿³¨ 1" |
| | | prop="remarkOne"> |
| | | <el-input v-model="form.remarkOne" |
| | | placeholder="请è¾å
¥å¤æ³¨ 1" /> |
| | | </el-form-item> |
| | | <el-form-item label="夿³¨ 2" |
| | | prop="remarkTwo"> |
| | | <el-input v-model="form.remarkTwo" |
| | | placeholder="请è¾å
¥å¤æ³¨ 2" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" |
| | | @click="handleSubmit">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref, reactive, getCurrentInstance, toRefs } from "vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import { ArrowUp, ArrowDown } from "@element-plus/icons-vue"; |
| | | import dayjs from "dayjs"; |
| | | import ImportDialog from "@/components/Dialog/ImportDialog.vue"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import { useDict } from "@/utils/dict"; |
| | | import { useRouter } from "vue-router"; |
| | | // import { |
| | | // productionPlanListPage, |
| | | // loadProdData, |
| | | // exportProductionPlan, |
| | | // productionPlanAdd, |
| | | // productionPlanUpdate, |
| | | // productionPlanDelete, |
| | | // productionPlanCombine, |
| | | // } from "@/api/productionPlan/productionPlan.js"; |
| | | |
| | | // Mock data and functions |
| | | const productionPlanListPage = params => { |
| | | console.log("Mock productionPlanListPage called with:", params); |
| | | return Promise.resolve({ |
| | | data: { |
| | | records: [ |
| | | { |
| | | id: 1, |
| | | dataSourceType: 1, |
| | | applyNo: "SQ20260422001", |
| | | customerName: "模æå®¢æ·A", |
| | | productName: "æ¿æ", |
| | | model: "100*200*300", |
| | | materialCode: "MAT001", |
| | | quantity: 100, |
| | | volume: 50, |
| | | status: 0, |
| | | assignedQuantity: 0, |
| | | length: 100, |
| | | width: 200, |
| | | height: 300, |
| | | startDate: "2026-04-22", |
| | | endDate: "2026-04-25", |
| | | strength: "C20", |
| | | remarkOne: "夿³¨1", |
| | | remarkTwo: "夿³¨2", |
| | | }, |
| | | { |
| | | id: 2, |
| | | dataSourceType: 2, |
| | | applyNo: "SQ20260422002", |
| | | customerName: "模æå®¢æ·B", |
| | | productName: "ç å", |
| | | model: "200*200*600", |
| | | materialCode: "MAT002", |
| | | quantity: 200, |
| | | volume: 80, |
| | | status: 1, |
| | | assignedQuantity: 30, |
| | | length: 200, |
| | | width: 200, |
| | | height: 600, |
| | | startDate: "2026-04-23", |
| | | endDate: "2026-04-26", |
| | | strength: "C25", |
| | | remarkOne: "夿³¨1", |
| | | remarkTwo: "夿³¨2", |
| | | }, |
| | | { |
| | | id: 3, |
| | | dataSourceType: 1, |
| | | applyNo: "SQ20260422003", |
| | | customerName: "模æå®¢æ·C", |
| | | productName: "ç å", |
| | | model: "240*115*53", |
| | | materialCode: "MAT003", |
| | | quantity: 1000, |
| | | volume: 1.46, |
| | | status: 2, |
| | | assignedQuantity: 1.46, |
| | | length: 240, |
| | | width: 115, |
| | | height: 53, |
| | | startDate: "2026-04-20", |
| | | endDate: "2026-04-21", |
| | | strength: "MU10", |
| | | remarkOne: "å·²ä¸åæ°æ®", |
| | | remarkTwo: "", |
| | | }, |
| | | ], |
| | | total: 3, |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | const loadProdData = () => { |
| | | console.log("Mock loadProdData called"); |
| | | return Promise.resolve({ code: 200, msg: "忥æå" }); |
| | | }; |
| | | |
| | | const exportProductionPlan = () => { |
| | | console.log("Mock exportProductionPlan called"); |
| | | return Promise.resolve(); |
| | | }; |
| | | |
| | | const productionPlanAdd = payload => { |
| | | console.log("Mock productionPlanAdd called with:", payload); |
| | | return Promise.resolve({ code: 200, msg: "æ°å¢æå" }); |
| | | }; |
| | | |
| | | const productionPlanUpdate = payload => { |
| | | console.log("Mock productionPlanUpdate called with:", payload); |
| | | return Promise.resolve({ code: 200, msg: "ä¿®æ¹æå" }); |
| | | }; |
| | | |
| | | const productionPlanDelete = ids => { |
| | | console.log("Mock productionPlanDelete called with ids:", ids); |
| | | return Promise.resolve({ code: 200, msg: "å 餿å" }); |
| | | }; |
| | | |
| | | const productionPlanCombine = payload => { |
| | | console.log("Mock productionPlanCombine called with:", payload); |
| | | return Promise.resolve({ code: 200, msg: "åå¹¶ä¸åæå" }); |
| | | }; |
| | | import PIMTable from "./components/PIMTable.vue"; |
| | | // import { |
| | | // modelListPage, |
| | | // productTreeList, |
| | | // productTreeListQuery, |
| | | // } from "@/api/basicData/newProduct.js"; |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | const router = useRouter(); |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "æ°æ®æ¥æº", |
| | | width: "100px", |
| | | prop: "dataSourceType", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | const typeMap = { |
| | | 2: "warning", |
| | | 1: "primary", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | }, |
| | | formatData: cell => (cell == 1 ? "éé忥" : "æå¨æ°å¢"), |
| | | }, |
| | | { |
| | | label: "ç³è¯·åç¼å·", |
| | | prop: "applyNo", |
| | | width: "150px", |
| | | }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | prop: "customerName", |
| | | width: "150px", |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | width: "200px", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | // const typeMap = { |
| | | // æ¿æ: "primary", |
| | | // ç å: "warning", |
| | | // }; |
| | | // return typeMap[params] || "info"; |
| | | return "primary"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "产åè§æ ¼", |
| | | prop: "model", |
| | | width: "150px", |
| | | className: "spec-cell", |
| | | }, |
| | | { |
| | | label: "ç©æç¼ç ", |
| | | prop: "materialCode", |
| | | width: "150px", |
| | | }, |
| | | { |
| | | label: "åæ°", |
| | | prop: "quantity", |
| | | align: "right", |
| | | dataType: "slot", |
| | | slot: "quantity", |
| | | }, |
| | | { |
| | | label: "æ¹æ°", |
| | | prop: "volume", |
| | | width: "150px", |
| | | align: "right", |
| | | dataType: "slot", |
| | | slot: "volume", |
| | | className: "volume-cell", |
| | | }, |
| | | { |
| | | label: "ä¸åç¶æ", |
| | | prop: "status", |
| | | width: "150px", |
| | | className: "status-cell", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | const typeMap = { |
| | | 0: "warning", |
| | | 1: "primary", |
| | | 2: "info", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | }, |
| | | formatData: cell => { |
| | | const statusMap = { |
| | | 0: "å¾
ä¸å", |
| | | 1: "é¨åä¸å", |
| | | 2: "å·²ä¸å", |
| | | }; |
| | | return statusMap[cell] || ""; |
| | | }, |
| | | }, |
| | | { |
| | | label: "å·²ä¸åæ¹æ°", |
| | | prop: "assignedQuantity", |
| | | width: "150px", |
| | | className: "spec-cell", |
| | | formatData: cell => (cell ? `${cell}æ¹` : 0), |
| | | }, |
| | | { |
| | | label: "é¿", |
| | | prop: "length", |
| | | className: "dimension-cell", |
| | | formatData: cell => (cell ? `${cell}mm` : ""), |
| | | }, |
| | | { |
| | | label: "宽", |
| | | prop: "width", |
| | | className: "dimension-cell", |
| | | formatData: cell => (cell ? `${cell}mm` : ""), |
| | | }, |
| | | { |
| | | label: "é«", |
| | | prop: "height", |
| | | className: "dimension-cell", |
| | | formatData: cell => (cell ? `${cell}mm` : ""), |
| | | }, |
| | | // { |
| | | // label: "æµæ°´å·", |
| | | // prop: "serialNo", |
| | | // width: "150px", |
| | | // className: "code-cell", |
| | | // }, |
| | | { |
| | | label: "计åå¼å§æ¥æ", |
| | | prop: "startDate", |
| | | width: "150px", |
| | | className: "date-cell", |
| | | formatData: cell => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""), |
| | | }, |
| | | { |
| | | label: "计åç»ææ¥æ", |
| | | prop: "endDate", |
| | | width: "150px", |
| | | className: "date-cell", |
| | | formatData: cell => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""), |
| | | }, |
| | | { |
| | | label: "强度", |
| | | prop: "strength", |
| | | formatData: cell => { |
| | | if (!cell) return ""; |
| | | const strengthItem = block_strength.value.find(item => item.id === cell); |
| | | return strengthItem ? strengthItem.label : cell; |
| | | }, |
| | | }, |
| | | |
| | | { |
| | | label: "夿³¨ 1", |
| | | width: "150px", |
| | | prop: "remarkOne", |
| | | }, |
| | | { |
| | | label: "夿³¨ 2", |
| | | width: "150px", |
| | | prop: "remarkTwo", |
| | | }, |
| | | |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 300, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "primary", |
| | | link: true, |
| | | showHide: row => { |
| | | return row.status == 0 && row.dataSourceType != 1; |
| | | //statusï¼0ï¼å¾
ä¸åï¼1ï¼é¨åä¸åï¼2ï¼å·²ä¸å |
| | | }, |
| | | clickFun: row => { |
| | | handleEdit(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "å é¤", |
| | | type: "danger", |
| | | link: true, |
| | | showHide: row => { |
| | | return row.status == 0; |
| | | }, |
| | | clickFun: row => { |
| | | handleDelete(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "ä¸å", |
| | | type: "text", |
| | | showHide: row => { |
| | | // 计ç®å©ä½æ¹æ° |
| | | const remainingVolume = |
| | | (row.volume || 0) - (row.assignedQuantity || 0); |
| | | // 妿å©ä½æ¹æ°å°äºçäº0ï¼ç¦æ¢éæ© |
| | | return remainingVolume > 0; |
| | | }, |
| | | clickFun: row => { |
| | | // åç¬ä¸åæä½ |
| | | // è®¾ç½®è¡¨åæ°æ® |
| | | strengthError.value = ""; |
| | | mergeForm.ids = [row.id]; |
| | | mergeForm.materialCode = row.materialCode; |
| | | mergeForm.productName = row.productName || ""; |
| | | mergeForm.model = row.model || ""; |
| | | mergeForm.length = row.length || 0; |
| | | mergeForm.width = row.width || 0; |
| | | mergeForm.height = row.height || 0; |
| | | mergeForm.totalAssignedQuantity = |
| | | (Number(row.volume) - Number(row.assignedQuantity)).toFixed(4) || 0; |
| | | mergeForm.planCompleteTime = row.planCompleteTime || ""; |
| | | mergeForm.productMaterialId = row.productMaterialId || ""; |
| | | mergeForm.strength = row.strength || ""; |
| | | sumAssignedQuantity.value = mergeForm.totalAssignedQuantity; |
| | | // æå¼å¼¹çª |
| | | isShowNewModal.value = true; |
| | | }, |
| | | }, |
| | | // { |
| | | // name: "追踪è¿åº¦", |
| | | // type: "text", |
| | | // clickFun: row => { |
| | | // handleTrackProgress(row); |
| | | // }, |
| | | // }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const selectedRows = ref([]); |
| | | |
| | | // 产åç±»å«æ±æ»ç»è®¡æ°æ® |
| | | const categorySummary = ref([]); |
| | | // 产åç±»å«æ±æ»å¼¹çªæ§å¶ |
| | | const showCategorySummaryDialog = ref(false); |
| | | |
| | | // åå¹¶ä¸åå¼¹çªæ§å¶ |
| | | const isShowNewModal = ref(false); |
| | | // åå¹¶ä¸åè¡¨åæ°æ® |
| | | const mergeForm = reactive({ |
| | | materialCode: "", |
| | | productName: "", |
| | | model: "", |
| | | length: 0, |
| | | width: 0, |
| | | height: 0, |
| | | totalAssignedQuantity: 0, |
| | | planCompleteTime: "", |
| | | strength: "", |
| | | productMaterialId: "", |
| | | }); |
| | | |
| | | // 导å
¥ç¸å
³ |
| | | const importDialogRef = ref(null); |
| | | const importDialogVisible = ref(false); |
| | | const importAction = |
| | | import.meta.env.VITE_APP_BASE_API + "/productionPlan/import"; |
| | | const importHeaders = ref({ |
| | | Authorization: `Bearer ${getToken()}`, |
| | | }); |
| | | |
| | | // æ°å¢/ç¼è¾ç¸å
³ |
| | | const dialogVisible = ref(false); |
| | | const operationType = ref("add"); // add | edit |
| | | const productOptions = ref([]); |
| | | const specificationOptions = ref([]); |
| | | const formRef = ref(null); |
| | | // è·å强度åå
¸ |
| | | const { block_strength } = useDict("block_strength"); |
| | | const form = reactive({ |
| | | id: undefined, |
| | | applyNo: "", |
| | | customerName: "", |
| | | productMaterialId: undefined, |
| | | productMaterialSkuId: undefined, |
| | | productName: "", |
| | | model: "", |
| | | materialCode: "", |
| | | quantity: 0, |
| | | volume: 0, |
| | | length: 0, |
| | | width: 0, |
| | | height: 0, |
| | | startDate: "", |
| | | endDate: "", |
| | | status: "", |
| | | strength: "", |
| | | remarkOne: "", |
| | | remarkTwo: "", |
| | | }); |
| | | const rules = reactive({ |
| | | applyNo: [{ required: true, message: "请è¾å
¥ç³è¯·åç¼å·", trigger: "blur" }], |
| | | customerName: [ |
| | | { required: true, message: "请è¾å
¥å®¢æ·åç§°", trigger: "blur" }, |
| | | ], |
| | | productMaterialSkuId: [ |
| | | { required: true, message: "è¯·éæ©äº§åè§æ ¼", trigger: "change" }, |
| | | ], |
| | | volume: [{ required: true, message: "请è¾å
¥æ¹æ°", trigger: "blur" }], |
| | | productMaterialId: [ |
| | | { required: true, message: "è¯·éæ©äº§å", trigger: "change" }, |
| | | ], |
| | | strength: [ |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (form.productName === "ç å" && !value) { |
| | | callback(new Error("ç å产åç强度为å¿
填项")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: ["blur", "change"], |
| | | required: false, |
| | | }, |
| | | ], |
| | | }); |
| | | |
| | | // å¤ç追踪è¿åº¦æé®ç¹å» |
| | | const handleTrackProgress = row => { |
| | | // 跳转å°è¿½è¸ªè¿åº¦é¡µé¢ |
| | | router.push({ |
| | | path: "/productionPlan/trackProgress", |
| | | query: { |
| | | id: row.id, |
| | | applyNo: row.applyNo, |
| | | productName: row.productName, |
| | | model: row.model, |
| | | }, |
| | | }); |
| | | }; |
| | | const onBlur = value => { |
| | | // éå¶åä½å°æ° |
| | | mergeForm.totalAssignedQuantity = Number(value.toFixed(4)); |
| | | }; |
| | | |
| | | const fetchProductOptions = () => { |
| | | // return productTreeList({ type: 2 }).then(res => { |
| | | // productOptions.value = convertIdToValue(res.data); |
| | | // return res; |
| | | // }); |
| | | }; |
| | | |
| | | const convertIdToValue = data => { |
| | | return data.map(item => { |
| | | const newItem = { |
| | | value: `config_${item.configId}`, // 使ç¨config_åç¼ç¡®ä¿å¯ä¸æ§ |
| | | label: item.configName, |
| | | disabled: item.materialList.length === 0, |
| | | }; |
| | | if (item.materialList && item.materialList.length > 0) { |
| | | newItem.children = item.materialList.map(material => ({ |
| | | value: material.id, // 使ç¨materialçidä½ä¸ºvalue |
| | | label: material.productName, // 使ç¨materialNameä½ä¸ºlabel |
| | | })); |
| | | } |
| | | |
| | | return newItem; |
| | | }); |
| | | }; |
| | | |
| | | const handleProductChange = value => { |
| | | form.productMaterialSkuId = undefined; |
| | | // æ¥æ¾éä¸ç产ååç§° |
| | | const findProductName = (options, value) => { |
| | | for (const option of options) { |
| | | if (option.value === value) { |
| | | return option.label; |
| | | } |
| | | if (option.children) { |
| | | const found = findProductName(option.children, value); |
| | | if (found) { |
| | | return found; |
| | | } |
| | | } |
| | | } |
| | | return ""; |
| | | }; |
| | | form.productName = findProductName(productOptions.value, value); |
| | | // 触åå¼ºåº¦åæ®µéªè¯ |
| | | if (formRef.value) { |
| | | formRef.value.validateField("strength"); |
| | | } |
| | | fetchSpecificationOptions(value); |
| | | }; |
| | | |
| | | const fetchSpecificationOptions = productId => { |
| | | specificationOptions.value = []; |
| | | 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.id === value |
| | | ); |
| | | if (selectedModel) { |
| | | form.materialCode = selectedModel.materialCode; |
| | | // è§£æè§æ ¼å符串è·åé¿å®½é« |
| | | 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]); |
| | | form.height = parseInt(dimensions[3]); |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | customerName: "", |
| | | productName: "", |
| | | model: "", |
| | | materialCode: "", |
| | | applyNo: "", |
| | | dateRange: [], |
| | | }, |
| | | searchFormExpanded: false, |
| | | }); |
| | | const { searchForm, searchFormExpanded } = toRefs(data); |
| | | |
| | | // 忢æç´¢è¡¨åå±å¼/æ¶èµ·ç¶æ |
| | | const toggleSearchForm = () => { |
| | | data.searchFormExpanded = !data.searchFormExpanded; |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | /** éç½®æé®æä½ */ |
| | | const handleReset = () => { |
| | | Object.assign(searchForm.value, { |
| | | customerName: "", |
| | | productName: "", |
| | | model: "", |
| | | materialCode: "", |
| | | applyNo: "", |
| | | dateRange: [], |
| | | }); |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | // 计ç®äº§åç±»å«æ±æ»ç»è®¡ |
| | | const calculateCategorySummary = () => { |
| | | const summary = {}; |
| | | |
| | | // éåè¡¨æ ¼æ°æ®ï¼æäº§åç±»å«æ±æ» |
| | | tableData.value.forEach(row => { |
| | | const category = row.materialCode; |
| | | if (!summary[category]) { |
| | | summary[category] = { |
| | | materialCode: category, |
| | | totalAssignedQuantity: 0, |
| | | }; |
| | | } |
| | | summary[category].totalAssignedQuantity += ( |
| | | Number(row.volume) - Number(row.assignedQuantity) |
| | | ).toFixed(4); |
| | | }); |
| | | |
| | | // 转æ¢ä¸ºæ°ç»æ ¼å¼ |
| | | categorySummary.value = Object.values(summary); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | // æé æç´¢åæ° |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.startDate = params.dateRange ? params.dateRange[0] : ""; |
| | | params.endDate = params.dateRange ? params.dateRange[1] : ""; |
| | | delete params.dateRange; |
| | | productionPlanListPage(params) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | // 计ç®äº§åç±»å«æ±æ»ç»è®¡ |
| | | calculateCategorySummary(); |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // éä¸çåºåå· |
| | | const selectedserialNo = ref(""); |
| | | |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | // 妿æéä¸çè¡ï¼è®°å½ç¬¬ä¸ä¸ªéä¸è¡çåºåå· |
| | | if (selection.length > 0) { |
| | | selectedserialNo.value = selection[0].materialCode; |
| | | } else { |
| | | // å¦ææ²¡æéä¸çè¡ï¼æ¸
空åºåå· |
| | | selectedserialNo.value = ""; |
| | | } |
| | | }; |
| | | |
| | | // å¤æè¡æ¯å¦å¯éæ© |
| | | const isSelectable = row => { |
| | | // 计ç®å©ä½æ¹æ° |
| | | const remainingVolume = (row.volume || 0) - (row.assignedQuantity || 0); |
| | | // 妿å©ä½æ¹æ°å°äºçäº0ï¼ç¦æ¢éæ© |
| | | if (remainingVolume <= 0) { |
| | | return false; |
| | | } |
| | | // å¦ææ²¡æéä¸çè¡ï¼ææè¡é½å¯éæ© |
| | | if (!selectedserialNo.value) { |
| | | return true; |
| | | } |
| | | // 妿æéä¸çè¡ï¼åªæåºåå·ç¸åçè¡æå¯éæ© |
| | | return row.materialCode === selectedserialNo.value; |
| | | }; |
| | | // æåæ°æ®æé®æä½ |
| | | const loadProdDataLoading = ref(false); |
| | | const getLoadProdData = () => { |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | loadProdDataLoading.value = true; |
| | | proxy.$modal.loading("æ£å¨æåæ°æ®ï¼è¯·ç¨å..."); |
| | | |
| | | loadProdData() |
| | | .then(res => { |
| | | proxy.$modal.closeLoading(); |
| | | getList(); |
| | | proxy.$modal.msgSuccess("æ°æ®æåæå"); |
| | | }) |
| | | .catch(err => { |
| | | proxy.$modal.closeLoading(); |
| | | console.error("æå失败:", err); |
| | | proxy.$modal.msgError("æ°æ®æå失败ï¼è¯·éè¯"); |
| | | }) |
| | | .finally(() => { |
| | | loadProdDataLoading.value = false; |
| | | }); |
| | | }; |
| | | const sumAssignedQuantity = ref(0); |
| | | // ååºå¼æ°æ® |
| | | const strengthError = ref(""); |
| | | |
| | | // å¤çåå¹¶ä¸åæé®ç¹å» |
| | | const handleMerge = () => { |
| | | if (selectedRows.value.length === 0) { |
| | | ElMessage.warning("è¯·éæ©è¦åå¹¶ä¸åçç产计å"); |
| | | return; |
| | | } |
| | | console.log(selectedRows.value); |
| | | // æ£æ¥å¼ºåº¦ä¸è´æ§ |
| | | const firstRow = selectedRows.value[0]; |
| | | const productName = firstRow.productName || ""; |
| | | let strengthConsistent = true; |
| | | let firstStrength = firstRow.strength || ""; |
| | | strengthError.value = ""; |
| | | |
| | | if (productName === "ç å") { |
| | | for (const row of selectedRows.value) { |
| | | if (row.strength !== firstStrength) { |
| | | strengthConsistent = false; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (!strengthConsistent) { |
| | | strengthError.value = "éæ©çç å强度ä¸ä¸è´ï¼è¯·éæ°éæ©"; |
| | | } |
| | | } |
| | | |
| | | // è®¡ç®æ»å¶é æ°é |
| | | const totalAssignedQuantity = selectedRows.value.reduce((sum, row) => { |
| | | return ( |
| | | sum + |
| | | (row.volume == null |
| | | ? 0 |
| | | : Number(Number(row.volume) - Number(row.assignedQuantity).toFixed(4))) |
| | | ); |
| | | }, 0); |
| | | sumAssignedQuantity.value = totalAssignedQuantity; |
| | | console.log(totalAssignedQuantity); |
| | | // è®¾ç½®è¡¨åæ°æ® |
| | | mergeForm.materialCode = selectedserialNo.value; |
| | | mergeForm.productName = productName; |
| | | mergeForm.model = firstRow.model || ""; |
| | | mergeForm.length = firstRow.length || 0; |
| | | mergeForm.width = firstRow.width || 0; |
| | | mergeForm.height = firstRow.height || 0; |
| | | mergeForm.totalAssignedQuantity = totalAssignedQuantity; |
| | | mergeForm.planCompleteTime = firstRow.planCompleteTime || ""; |
| | | mergeForm.productMaterialId = firstRow.productMaterialId || ""; |
| | | mergeForm.strength = firstStrength; |
| | | mergeForm.ids = selectedRows.value.map(row => row.id); |
| | | |
| | | // æå¼å¼¹çª |
| | | isShowNewModal.value = true; |
| | | }; |
| | | |
| | | // å¤çåå¹¶ä¸åæäº¤ |
| | | const handleMergeSubmit = () => { |
| | | if (mergeForm.totalAssignedQuantity === 0) { |
| | | ElMessage.warning("请è¾å
¥çäº§æ¹æ°"); |
| | | return; |
| | | } |
| | | // éªè¯ç å产åç强度 |
| | | if (mergeForm.productName === "ç å" && !mergeForm.strength) { |
| | | ElMessage.error("ç å产åç强度为å¿
填项"); |
| | | return; |
| | | } |
| | | if (mergeForm.productName != "ç å") { |
| | | mergeForm.strength = ""; |
| | | } |
| | | console.log(sumAssignedQuantity.value, "sumAssignedQuantity"); |
| | | // 计ç®å½åéä¸è¡çæ»æ¹æ° |
| | | const totalVolume = selectedRows.value.reduce((sum, row) => { |
| | | return sum + (Number(row.volume) - Number(row.assignedQuantity) || 0); |
| | | }, 0); |
| | | |
| | | // éªè¯totalAssignedQuantityä¸è½å¤§äºæ»æ¹æ° |
| | | if (mergeForm.totalAssignedQuantity > sumAssignedQuantity.value) { |
| | | ElMessage.error("çäº§æ¹æ°ä¸è½å¤§äºå½å计ç®çæ»å¼"); |
| | | return; |
| | | } |
| | | |
| | | console.log(mergeForm, "mergeForm"); |
| | | const strengthItem = block_strength.value.find( |
| | | item => item.id === mergeForm.strength |
| | | ); |
| | | const payload = { |
| | | ...mergeForm, |
| | | strength: strengthItem ? strengthItem.label : mergeForm.strength, |
| | | }; |
| | | productionPlanCombine(payload) |
| | | .then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success("ä¸åæå"); |
| | | getList(); |
| | | isShowNewModal.value = false; |
| | | // å¯ä»¥éæ©å·æ°å表æå
¶ä»æä½ |
| | | getList(); |
| | | } else { |
| | | ElMessage.error(res.message || "ä¸å失败"); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | console.error("åå¹¶ä¸åå¼å¸¸ï¼", err); |
| | | ElMessage.error("ç³»ç»å¼å¸¸ï¼åå¹¶ä¸å失败"); |
| | | }); |
| | | // å¯ä»¥éæ©å·æ°å表æå
¶ä»æä½ |
| | | }; |
| | | |
| | | // 导å
¥ |
| | | const handleImport = () => { |
| | | importDialogVisible.value = true; |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleExport = () => { |
| | | const fileName = `ç产计å.xlsx`; |
| | | exportProductionPlan() |
| | | .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 handleImportSuccess = response => { |
| | | if (response.code === 200) { |
| | | ElMessage.success("导å
¥æå"); |
| | | importDialogVisible.value = false; |
| | | getList(); |
| | | } else { |
| | | ElMessage.error(response.msg || "导å
¥å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | // 导å
¥å¤±è´¥ |
| | | const handleImportError = error => { |
| | | ElMessage.error("导å
¥å¤±è´¥ï¼è¯·æ£æ¥æä»¶æ ¼å¼æ¯å¦æ£ç¡®"); |
| | | }; |
| | | |
| | | // 确认导å
¥ |
| | | const handleImportConfirm = () => { |
| | | if (importDialogRef.value) { |
| | | importDialogRef.value.submit(); |
| | | } |
| | | }; |
| | | |
| | | // ä¸è½½æ¨¡æ¿ |
| | | const handleDownloadTemplate = () => { |
| | | proxy.download( |
| | | "/productionPlan/downloadTemplate", |
| | | {}, |
| | | "ç产计å导å
¥æ¨¡æ¿.xlsx" |
| | | ); |
| | | }; |
| | | |
| | | // å
³é导å
¥å¼¹çª |
| | | const handleImportClose = () => { |
| | | importDialogVisible.value = false; |
| | | }; |
| | | |
| | | // æ°å¢ |
| | | const handleAdd = () => { |
| | | operationType.value = "add"; |
| | | Object.assign(form, { |
| | | applyNo: "", |
| | | customerName: "", |
| | | productName: "", |
| | | productMaterialId: undefined, |
| | | productMaterialSkuId: undefined, |
| | | model: "", |
| | | materialCode: "", |
| | | quantity: 0, |
| | | volume: 0, |
| | | length: 0, |
| | | width: 0, |
| | | height: 0, |
| | | startDate: "", |
| | | endDate: "", |
| | | strength: "", |
| | | remarkOne: "", |
| | | remarkTwo: "", |
| | | }); |
| | | dialogVisible.value = true; |
| | | fetchProductOptions(); |
| | | }; |
| | | |
| | | // ç¼è¾ |
| | | const handleEdit = row => { |
| | | operationType.value = "edit"; |
| | | Object.assign(form, { |
| | | id: row.id, |
| | | applyNo: row.applyNo || "", |
| | | customerName: row.customerName || "", |
| | | productName: row.productName || "", |
| | | productMaterialId: row.productMaterialId || undefined, |
| | | productMaterialSkuId: row.productMaterialSkuId || undefined, |
| | | model: row.model || "", |
| | | materialCode: row.materialCode || "", |
| | | quantity: row.quantity || 0, |
| | | volume: row.volume || 0, |
| | | length: row.length || 0, |
| | | width: row.width || 0, |
| | | height: row.height || 0, |
| | | startDate: row.startDate || "", |
| | | endDate: row.endDate || "", |
| | | strength: row.strength || "", |
| | | remarkOne: row.remarkOne || "", |
| | | remarkTwo: row.remarkTwo || "", |
| | | }); |
| | | dialogVisible.value = true; |
| | | fetchProductOptions(); |
| | | fetchSpecificationOptions(row.productMaterialId); |
| | | }; |
| | | |
| | | // å é¤ |
| | | const handleDelete = row => { |
| | | proxy.$modal |
| | | .confirm("确认å é¤è¯¥ç产计åï¼", "æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | productionPlanDelete([row.id]) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("å é¤å¤±è´¥"); |
| | | }); |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const handleSubmit = () => { |
| | | formRef.value.validate(valid => { |
| | | if (valid) { |
| | | if (form.volume === 0) { |
| | | proxy.$modal.msgError("æ¹æ°ä¸è½ä¸º0"); |
| | | return; |
| | | } |
| | | if (form.v === "add") { |
| | | payload.id = null; |
| | | } |
| | | const payload = { ...form }; |
| | | if (operationType.value === "add") { |
| | | payload.id = null; |
| | | productionPlanAdd(payload) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess( |
| | | operationType.value === "add" ? "æ°å¢æå" : "ä¿®æ¹æå" |
| | | ); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError( |
| | | operationType.value === "add" ? "æ°å¢å¤±è´¥" : "ä¿®æ¹å¤±è´¥" |
| | | ); |
| | | }); |
| | | } |
| | | if (operationType.value === "edit") { |
| | | productionPlanUpdate(payload) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess( |
| | | operationType.value === "add" ? "æ°å¢æå" : "ä¿®æ¹æå" |
| | | ); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError( |
| | | operationType.value === "add" ? "æ°å¢å¤±è´¥" : "ä¿®æ¹å¤±è´¥" |
| | | ); |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .app-container { |
| | | padding: 24px; |
| | | background-color: #f0f2f5; |
| | | min-height: calc(100vh - 48px); |
| | | } |
| | | |
| | | .search_form { |
| | | // margin-bottom: 24px; |
| | | padding: 20px; |
| | | background-color: #ffffff; |
| | | border-radius: 6px; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05); |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.08); |
| | | } |
| | | } |
| | | |
| | | .search-header { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | // margin-bottom: 5px; |
| | | // padding-bottom: 5px; |
| | | position: relative; |
| | | bottom: 35px; |
| | | // border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .search-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .search-header .el-button { |
| | | color: #606266; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .search-header .el-button:hover { |
| | | color: #409eff; |
| | | } |
| | | |
| | | .search-header .el-icon { |
| | | margin-right: 4px; |
| | | } |
| | | |
| | | .table_list { |
| | | // margin-bottom: 24px; |
| | | background-color: #ffffff; |
| | | border-radius: 6px; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05); |
| | | overflow: hidden; |
| | | height: calc(100vh - 250px); |
| | | margin-top: 0px !important; |
| | | } |
| | | |
| | | :deep(.el-table) { |
| | | border: none; |
| | | border-radius: 6px; |
| | | overflow: hidden; |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.1); |
| | | |
| | | .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; |
| | | letter-spacing: 0.5px; |
| | | } |
| | | } |
| | | |
| | | .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% |
| | | ); |
| | | transform: scale(1.002); |
| | | box-shadow: 0 2px 8px rgba(102, 126, 234, 0.1); |
| | | } |
| | | |
| | | td { |
| | | border-bottom: 1px solid #f0f0f0; |
| | | padding: 14px 0; |
| | | color: #303133; |
| | | } |
| | | } |
| | | |
| | | tr.current-row { |
| | | background: linear-gradient( |
| | | 90deg, |
| | | rgba(102, 126, 234, 0.08) 0%, |
| | | rgba(118, 75, 162, 0.08) 100% |
| | | ); |
| | | } |
| | | |
| | | // æ°å¼åæ®µæ ·å¼ |
| | | .quantity-cell, |
| | | .volume-cell, |
| | | .dimension-cell { |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | font-family: "Courier New", monospace; |
| | | text-shadow: 0 1px 2px rgba(64, 158, 255, 0.2); |
| | | } |
| | | |
| | | // è§æ ¼åæ®µæ ·å¼ |
| | | .spec-cell { |
| | | color: #67c23a; |
| | | font-weight: 500; |
| | | |
| | | padding: 4px 8px; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | // ç¼ç åæ®µæ ·å¼ |
| | | .code-cell { |
| | | color: #e6a23c; |
| | | font-family: "Courier New", monospace; |
| | | font-weight: 500; |
| | | padding: 4px 8px; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | // æ¥æåæ®µæ ·å¼ |
| | | .date-cell { |
| | | color: #909399; |
| | | font-style: italic; |
| | | } |
| | | |
| | | // ç¶ææ ç¾æ ·å¼ |
| | | .status-tag { |
| | | &.pending { |
| | | background: linear-gradient(135deg, #ffeaa7 0%, #fdcb6e 100%); |
| | | color: #d63031; |
| | | padding: 4px 12px; |
| | | border-radius: 12px; |
| | | font-weight: 500; |
| | | box-shadow: 0 2px 4px rgba(253, 203, 110, 0.3); |
| | | } |
| | | |
| | | &.processing { |
| | | background: linear-gradient(135deg, #74b9ff 0%, #0984e3 100%); |
| | | color: #ffffff; |
| | | padding: 4px 12px; |
| | | border-radius: 12px; |
| | | font-weight: 500; |
| | | box-shadow: 0 2px 4px rgba(9, 132, 227, 0.3); |
| | | } |
| | | |
| | | &.completed { |
| | | background: linear-gradient(135deg, #55efc4 0%, #00b894 100%); |
| | | color: #ffffff; |
| | | padding: 4px 12px; |
| | | border-radius: 12px; |
| | | font-weight: 500; |
| | | box-shadow: 0 2px 4px rgba(0, 184, 148, 0.3); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .el-table__empty-block { |
| | | padding: 60px 0; |
| | | background-color: #fafafa; |
| | | } |
| | | } |
| | | |
| | | // æä½æé®æ ·å¼ |
| | | :deep(.el-table .cell .el-button--text) { |
| | | padding: 6px 10px; |
| | | border-radius: 4px; |
| | | transition: all 0.3s ease; |
| | | font-weight: 500; |
| | | |
| | | &:hover { |
| | | background-color: rgba(64, 158, 255, 0.1); |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 2px 4px rgba(64, 158, 255, 0.2); |
| | | } |
| | | |
| | | &:nth-of-type(1) { |
| | | color: #409eff; |
| | | background: linear-gradient( |
| | | 135deg, |
| | | rgba(64, 158, 255, 0.1) 0%, |
| | | rgba(64, 158, 255, 0.05) 100% |
| | | ); |
| | | } |
| | | |
| | | &:nth-of-type(2) { |
| | | color: #67c23a; |
| | | background: linear-gradient( |
| | | 135deg, |
| | | rgba(103, 194, 58, 0.1) 0%, |
| | | rgba(103, 194, 58, 0.05) 100% |
| | | ); |
| | | } |
| | | } |
| | | |
| | | // ä¿¡æ¯å±ç¤ºæ ·å¼ |
| | | .info-display { |
| | | border-radius: 6px; |
| | | color: #303133; |
| | | font-size: 14px; |
| | | min-height: 32px; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .pagination-container { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | padding: 16px 20px; |
| | | background-color: #ffffff; |
| | | border-top: 1px solid #ebeef5; |
| | | border-radius: 0 0 12px 12px; |
| | | } |
| | | |
| | | :deep(.el-button) { |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | transform: translateY(-1px); |
| | | } |
| | | } |
| | | |
| | | :deep(.el-dialog) { |
| | | border-radius: 6px; |
| | | overflow: hidden; |
| | | |
| | | .el-dialog__header { |
| | | background-color: #fafafa; |
| | | border-bottom: 1px solid #ebeef5; |
| | | padding: 20px 24px; |
| | | |
| | | .el-dialog__title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | } |
| | | |
| | | .el-dialog__body { |
| | | padding: 24px; |
| | | } |
| | | |
| | | .el-dialog__footer { |
| | | padding: 16px 24px; |
| | | border-top: 1px solid #ebeef5; |
| | | background-color: #fafafa; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-form) { |
| | | .el-form-item { |
| | | margin-bottom: 20px; |
| | | |
| | | .el-form-item__label { |
| | | font-weight: 500; |
| | | color: #303133; |
| | | } |
| | | |
| | | .el-input, |
| | | .el-select, |
| | | .el-date-picker, |
| | | .el-input-number { |
| | | width: 100%; |
| | | |
| | | // .el-input__inner { |
| | | // border-radius: 6px; |
| | | // border: 1px solid #dcdfe6; |
| | | // transition: all 0.3s ease; |
| | | |
| | | // &:focus { |
| | | // border-color: #409eff; |
| | | // box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2); |
| | | // } |
| | | // } |
| | | } |
| | | } |
| | | } |
| | | |
| | | :deep(.el-tag) { |
| | | border-radius: 4px; |
| | | padding: 2px 8px; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .app-container { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .search_form { |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | gap: 12px; |
| | | |
| | | .el-form { |
| | | width: 100%; |
| | | |
| | | .el-form-item { |
| | | width: 100%; |
| | | } |
| | | } |
| | | |
| | | > div { |
| | | width: 100%; |
| | | display: flex; |
| | | gap: 12px; |
| | | |
| | | .el-button { |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | :deep(.el-table) { |
| | | th, |
| | | td { |
| | | padding: 10px 0; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-dialog) { |
| | | width: 90% !important; |
| | | margin: 20px auto !important; |
| | | } |
| | | } |
| | | .consumption-value { |
| | | font-weight: bold; |
| | | color: #409eff; |
| | | } |
| | | |
| | | .consumption-unit { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | margin-left: 4px; |
| | | } |
| | | // .search_form { |
| | | // :deep(.el-form-item) { |
| | | // margin-bottom: 0px !important; |
| | | // } |
| | | // } |
| | | :deep(.el-table .el-table__body-wrapper tr td) { |
| | | background-color: #fff; |
| | | } |
| | | </style> |