| | |
| | | url: "/energyConsumptionDetail/" + ids, |
| | | method: "delete", |
| | | }); |
| | | } |
| | | |
| | | // æ¥è¯¢éä»¶å表 |
| | | export function fileListPage(query) { |
| | | return request({ |
| | | url: "/energyConsumptionDetailFile/page", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // æ·»å éä»¶ |
| | | export function energyConsumptionDetailFileAdd(query) { |
| | | return request({ |
| | | url: '/energyConsumptionDetailFile', |
| | | method: 'post', |
| | | data: query |
| | | }) |
| | | } |
| | | // å é¤éä»¶ |
| | | export function energyConsumptionDetailFileDel(ids) { |
| | | return request({ |
| | | url: `/energyConsumptionDetailFile/${ids}`, |
| | | method: 'delete', |
| | | }) |
| | | } |
| | |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // æåæ°æ® |
| | | export function loadProdData(query) { |
| | | return request({ |
| | | url: "/productionPlan/loadProdData", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function summaryByProductType(query) { |
| | | return request({ |
| | | url: "/productionPlan/summaryByProductType", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // 导åºç产计å |
| | | export function exportProductionPlan(bomId) { |
| | | return request({ |
| | | url: "/productionPlan/export", |
| | | method: "post", |
| | | params: { bomId }, |
| | | responseType: "blob", |
| | | }); |
| | | } |
| | | |
| | | // ç产计å-æ°å¢ä¿®æ¹ |
| | | export function productionPlanAdd(query) { |
| | | return request({ |
| | | url: "/productionPlan", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | export function productionPlanUpdate(query) { |
| | | return request({ |
| | | url: "/productionPlan", |
| | | method: "put", |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // ç产计å-å é¤ |
| | | export function productionPlanDelete(data) { |
| | | return request({ |
| | | url: "/productionPlan", |
| | | method: "delete", |
| | | data |
| | | }); |
| | | } |
| | | // åå¹¶ä¸å |
| | | export function productionPlanCombine(query) { |
| | | return request({ |
| | | url: "/productionPlan/combine", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | |
| | | style="width: 120px;" |
| | | @change="handleQuery"> |
| | | <el-option label="æ°" |
| | | value="gas" /> |
| | | value="æ°" /> |
| | | <el-option label="çµ" |
| | | value="electricity" /> |
| | | value="çµ" /> |
| | | <el-option label="æ°´" |
| | | value="water" /> |
| | | value="æ°´" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="è½æºåç§°:"> |
| | |
| | | .search_form { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | align-items: flex-start; |
| | | flex-wrap: wrap; |
| | | gap: 16px; |
| | | margin-bottom: 24px; |
| | | padding: 20px; |
| | | background-color: #ffffff; |
| | |
| | | |
| | | &:hover { |
| | | box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.08); |
| | | } |
| | | |
| | | :deep(.el-form) { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 0; |
| | | |
| | | .el-form-item { |
| | | margin-right: 16px; |
| | | margin-bottom: 0; |
| | | |
| | | &:last-child { |
| | | margin-right: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | > div { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | flex-shrink: 0; |
| | | } |
| | | } |
| | | |
| | |
| | | font-size: 12px; |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .app-container { |
| | | padding: 16px; |
| | | @media (max-width: 1200px) { |
| | | .search_form { |
| | | :deep(.el-form) { |
| | | .el-form-item { |
| | | margin-right: 12px; |
| | | margin-bottom: 8px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 992px) { |
| | | .search_form { |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | align-items: stretch; |
| | | gap: 12px; |
| | | |
| | | .el-form { |
| | | :deep(.el-form) { |
| | | width: 100%; |
| | | |
| | | .el-form-item { |
| | | width: 100%; |
| | | margin-right: 12px; |
| | | margin-bottom: 8px; |
| | | flex: 1; |
| | | min-width: 200px; |
| | | |
| | | &:last-child { |
| | | margin-right: 12px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | > div { |
| | | width: 100%; |
| | | display: flex; |
| | | gap: 12px; |
| | | justify-content: flex-end; |
| | | } |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .app-container { |
| | | padding: 12px; |
| | | } |
| | | |
| | | .search_form { |
| | | padding: 16px; |
| | | gap: 12px; |
| | | |
| | | :deep(.el-form) { |
| | | flex-direction: column; |
| | | width: 100%; |
| | | |
| | | .el-form-item { |
| | | width: 100%; |
| | | margin-right: 0; |
| | | margin-bottom: 12px; |
| | | |
| | | &:last-child { |
| | | margin-right: 0; |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .el-form-item__content { |
| | | width: 100%; |
| | | |
| | | .el-input, |
| | | .el-select, |
| | | .el-date-editor { |
| | | width: 100% !important; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | > div { |
| | | width: 100%; |
| | | justify-content: stretch; |
| | | |
| | | .el-button { |
| | | flex: 1; |
| | |
| | | } |
| | | } |
| | | |
| | | .table_list { |
| | | height: calc(100vh - 300px); |
| | | } |
| | | |
| | | :deep(.el-table) { |
| | | th, |
| | | td { |
| | | padding: 10px 0; |
| | | padding: 8px 0; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-dialog) { |
| | | width: 90% !important; |
| | | margin: 20px auto !important; |
| | | width: 95% !important; |
| | | margin: 10px auto !important; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 480px) { |
| | | .search_form { |
| | | padding: 12px; |
| | | |
| | | > div { |
| | | flex-direction: column; |
| | | gap: 8px; |
| | | |
| | | .el-button { |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .consumption-value { |
| | |
| | | style="width: 140px;" |
| | | @change="handleQuery"> |
| | | <el-option label="æ°´" |
| | | value="water" /> |
| | | value="æ°´" /> |
| | | <el-option label="çµ" |
| | | value="electricity" /> |
| | | value="çµ" /> |
| | | <el-option label="æ°" |
| | | value="gas" /> |
| | | value="æ°" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <!-- <el-form-item label="æ¥æèå´:"> |
| | | <el-form-item label="è½æºåç§°:"> |
| | | <el-input v-model="searchForm.energyName" |
| | | 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="è³" |
| | |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 240px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> --> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="handleQuery">æç´¢</el-button> |
| | |
| | | </el-form-item> |
| | | </el-form> |
| | | <div> |
| | | <!-- <el-button type="primary" |
| | | @click="handleAdd">æ°å¢</el-button> --> |
| | | <el-button type="primary" |
| | | @click="handleAdd">æ°å¢</el-button> |
| | | <el-button type="success" |
| | | @click="handleExport">导åº</el-button> |
| | | <el-button type="warning" |
| | | @click="handleImport">导å
¥</el-button> |
| | | </div> |
| | | </div> |
| | | <!-- æ°æ®è¡¨æ ¼ --> |
| | |
| | | label="夿³¨" |
| | | min-width="150" |
| | | show-overflow-tooltip /> |
| | | <!-- <el-table-column label="æä½" |
| | | width="180" |
| | | <el-table-column label="æä½" |
| | | width="220" |
| | | align="center" |
| | | fixed="right"> |
| | | <template #default="scope"> |
| | |
| | | <el-button type="danger" |
| | | link |
| | | @click="handleDelete(scope.row)">å é¤</el-button> |
| | | <el-button type="info" |
| | | link |
| | | @click="downLoadFile(scope.row)">éä»¶</el-button> |
| | | </template> |
| | | </el-table-column> --> |
| | | </el-table-column> |
| | | </el-table> |
| | | <div class="pagination-container"> |
| | | <el-pagination v-model:current-page="page.current" |
| | |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- éä»¶åè¡¨å¼¹çª --> |
| | | <FileListDialog ref="fileListRef" |
| | | v-model="fileListDialogVisible" |
| | | :show-upload-button="true" |
| | | :show-delete-button="true" |
| | | :is-show-pagination="true" |
| | | :page="filePagination" |
| | | :upload-method="handleUpload" |
| | | :delete-method="handleFileDelete" |
| | | @pagination="paginationSearch" |
| | | title="éä»¶å表" /> |
| | | <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" /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import { ref, reactive, onMounted, getCurrentInstance } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Watermelon, Lightning } from "@element-plus/icons-vue"; |
| | | import ImportDialog from "@/components/Dialog/ImportDialog.vue"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import FileListDialog from "@/components/Dialog/FileListDialog.vue"; |
| | | import request from "@/utils/request"; |
| | | import { |
| | | energyConsumptionDetailListPage, |
| | | energyConsumptionDetailAdd, |
| | | energyConsumptionDetailDelete, |
| | | energyTypeListPage, |
| | | fileListPage, |
| | | energyConsumptionDetailFileAdd, |
| | | energyConsumptionDetailFileDel, |
| | | } from "@/api/energyManagement/energyType"; |
| | | |
| | | // æç´¢è¡¨å |
| | |
| | | const formRef = ref(null); |
| | | const isEdit = ref(false); |
| | | const currentId = ref(null); |
| | | |
| | | // éä»¶ç¸å
³ |
| | | const fileListRef = ref(null); |
| | | const fileListDialogVisible = ref(false); |
| | | const currentFileRow = ref(null); |
| | | const filePagination = ref({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | |
| | | // 导å
¥ç¸å
³ |
| | | const importDialogRef = ref(null); |
| | | const importDialogVisible = ref(false); |
| | | const importAction = |
| | | import.meta.env.VITE_APP_BASE_API + "/energyConsumptionDetail/importData"; |
| | | const importHeaders = ref({ |
| | | Authorization: `Bearer ${getToken()}`, |
| | | }); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | |
| | | current: page.current, |
| | | size: page.size, |
| | | type: "åå
¬", |
| | | // energyType: searchForm.energyType, |
| | | // startDate: |
| | | // searchForm.dateRange && searchForm.dateRange.length === 2 |
| | | // ? searchForm.dateRange[0] |
| | | // : null, |
| | | // endDate: |
| | | // searchForm.dateRange && searchForm.dateRange.length === 2 |
| | | // ? searchForm.dateRange[1] |
| | | // : null, |
| | | energyTyep: searchForm.energyType, |
| | | energyName: searchForm.energyName, |
| | | startDate: |
| | | searchForm.dateRange && searchForm.dateRange.length === 2 |
| | | ? searchForm.dateRange[0] |
| | | : null, |
| | | endDate: |
| | | searchForm.dateRange && searchForm.dateRange.length === 2 |
| | | ? searchForm.dateRange[1] |
| | | : null, |
| | | }; |
| | | energyConsumptionDetailListPage(params) |
| | | .then(res => { |
| | |
| | | // éç½® |
| | | const handleReset = () => { |
| | | searchForm.energyType = ""; |
| | | searchForm.energyName = ""; |
| | | searchForm.dateRange = []; |
| | | page.current = 1; |
| | | handleQuery(); |
| | |
| | | }); |
| | | }; |
| | | |
| | | // ä¸è½½æä»¶ |
| | | const downLoadFile = row => { |
| | | currentFileRow.value = row; |
| | | fileListPage({ |
| | | energyConsumptionDetailId: row.id, |
| | | current: filePagination.value.current, |
| | | size: filePagination.value.size, |
| | | }).then(res => { |
| | | if (fileListRef.value) { |
| | | fileListRef.value.open(res.data.records); |
| | | } |
| | | filePagination.value.total = res.data.total || 0; |
| | | }); |
| | | }; |
| | | |
| | | // ä¸ä¼ éä»¶ |
| | | const handleUpload = async () => { |
| | | if (!currentFileRow.value) { |
| | | ElMessage.warning("请å
éæ©æ°æ®"); |
| | | return null; |
| | | } |
| | | |
| | | return new Promise(resolve => { |
| | | // å建ä¸ä¸ªéèçæä»¶è¾å
¥å
ç´ |
| | | const input = document.createElement("input"); |
| | | input.type = "file"; |
| | | input.style.display = "none"; |
| | | input.onchange = async e => { |
| | | const file = e.target.files[0]; |
| | | if (!file) { |
| | | resolve(null); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | // ä½¿ç¨ FormData ä¸ä¼ æä»¶ |
| | | const formData = new FormData(); |
| | | formData.append("file", file); |
| | | |
| | | const uploadRes = await request({ |
| | | url: "/file/upload", |
| | | method: "post", |
| | | data: formData, |
| | | headers: { |
| | | "Content-Type": "multipart/form-data", |
| | | Authorization: `Bearer ${getToken()}`, |
| | | }, |
| | | }); |
| | | |
| | | if (uploadRes.code === 200) { |
| | | // ä¿åéä»¶ä¿¡æ¯ |
| | | const fileData = { |
| | | energyConsumptionDetailId: currentFileRow.value.id, |
| | | name: uploadRes.data.originalName || file.name, |
| | | url: uploadRes.data.tempPath || uploadRes.data.url, |
| | | }; |
| | | |
| | | const saveRes = await energyConsumptionDetailFileAdd(fileData); |
| | | if (saveRes.code === 200) { |
| | | proxy.$modal.msgSuccess("æä»¶ä¸ä¼ æå"); |
| | | // éæ°å è½½æä»¶å表 |
| | | const listRes = await fileListPage({ |
| | | energyConsumptionDetailId: currentFileRow.value.id, |
| | | current: filePagination.value.current, |
| | | size: filePagination.value.size, |
| | | }); |
| | | if (listRes.code === 200 && fileListRef.value) { |
| | | const fileList = (listRes.data?.records || []).map(item => ({ |
| | | name: item.name, |
| | | url: item.url, |
| | | id: item.id, |
| | | ...item, |
| | | })); |
| | | fileListRef.value.setList(fileList); |
| | | filePagination.value.total = listRes.data?.total || 0; |
| | | } |
| | | // è¿åæ°æä»¶ä¿¡æ¯ |
| | | resolve({ |
| | | name: fileData.name, |
| | | url: fileData.url, |
| | | id: Date.now(), |
| | | }); |
| | | } else { |
| | | ElMessage.error(uploadRes.message || "æä»¶ä¸ä¼ 失败"); |
| | | resolve(null); |
| | | } |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("æä»¶ä¸ä¼ 失败"); |
| | | resolve(null); |
| | | } finally { |
| | | document.body.removeChild(input); |
| | | } |
| | | }; |
| | | |
| | | document.body.appendChild(input); |
| | | input.click(); |
| | | }); |
| | | }; |
| | | |
| | | // å页æç´¢ |
| | | const paginationSearch = async (page, size) => { |
| | | filePagination.value.current = page; |
| | | filePagination.value.size = size; |
| | | const listRes = await fileListPage({ |
| | | energyConsumptionDetailId: currentFileRow.value.id, |
| | | current: filePagination.value.current, |
| | | size: filePagination.value.size, |
| | | }); |
| | | if (listRes.code === 200) { |
| | | const fileList = (listRes.data?.records || []).map(item => ({ |
| | | name: item.name, |
| | | url: item.url, |
| | | id: item.id, |
| | | ...item, |
| | | })); |
| | | |
| | | fileListRef.value.setList(fileList); |
| | | filePagination.value.total = listRes.data?.total || 0; |
| | | } |
| | | }; |
| | | |
| | | // å é¤éä»¶ |
| | | const handleFileDelete = async row => { |
| | | try { |
| | | const res = await energyConsumptionDetailFileDel([row.id]); |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | // éæ°å è½½æä»¶å表 |
| | | if (currentFileRow.value && fileListRef.value) { |
| | | const listRes = await fileListPage({ |
| | | energyConsumptionDetailId: currentFileRow.value.id, |
| | | current: filePagination.value.current, |
| | | size: filePagination.value.size, |
| | | }); |
| | | if (listRes.code === 200) { |
| | | const fileList = (listRes.data?.records || []).map(item => ({ |
| | | name: item.name, |
| | | url: item.url, |
| | | id: item.id, |
| | | ...item, |
| | | })); |
| | | fileListRef.value.setList(fileList); |
| | | filePagination.value.total = listRes.data?.total || 0; |
| | | } |
| | | } |
| | | return true; // è¿å true 表示å 餿åï¼ç»ä»¶ä¼æ´æ°å表 |
| | | } else { |
| | | proxy.$modal.msgError(res.msg || "å é¤å¤±è´¥"); |
| | | return false; |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("å é¤å¤±è´¥"); |
| | | return false; |
| | | } |
| | | }; |
| | | |
| | | // 导å
¥ |
| | | const handleImport = () => { |
| | | importDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 导å
¥æå |
| | | const handleImportSuccess = response => { |
| | | if (response.code === 200) { |
| | | ElMessage.success("导å
¥æå"); |
| | | importDialogVisible.value = false; |
| | | handleQuery(); |
| | | } else { |
| | | ElMessage.error(response.message || "导å
¥å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | // 导å
¥å¤±è´¥ |
| | | const handleImportError = error => { |
| | | ElMessage.error("导å
¥å¤±è´¥ï¼è¯·æ£æ¥æä»¶æ ¼å¼æ¯å¦æ£ç¡®"); |
| | | }; |
| | | |
| | | // 确认导å
¥ |
| | | const handleImportConfirm = () => { |
| | | if (importDialogRef.value) { |
| | | importDialogRef.value.submit(); |
| | | } |
| | | }; |
| | | |
| | | // ä¸è½½æ¨¡æ¿ |
| | | const handleDownloadTemplate = () => { |
| | | proxy.download( |
| | | "/energyConsumptionDetail/downloadTemplate", |
| | | {}, |
| | | "ç产è½è导å
¥æ¨¡æ¿.xlsx" |
| | | ); |
| | | }; |
| | | |
| | | // å
³é导å
¥å¼¹çª |
| | | const handleImportClose = () => { |
| | | importDialogVisible.value = false; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getEnergyTypeList(); |
| | | handleQuery(); |
| | |
| | | .search_form { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | align-items: flex-start; |
| | | flex-wrap: wrap; |
| | | gap: 16px; |
| | | margin-bottom: 24px; |
| | | padding: 20px; |
| | | background-color: #ffffff; |
| | |
| | | |
| | | &:hover { |
| | | box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.08); |
| | | } |
| | | |
| | | :deep(.el-form) { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 0; |
| | | |
| | | .el-form-item { |
| | | margin-right: 16px; |
| | | margin-bottom: 0; |
| | | |
| | | &:last-child { |
| | | margin-right: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | > div { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | flex-shrink: 0; |
| | | } |
| | | } |
| | | |
| | |
| | | font-size: 12px; |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .app-container { |
| | | padding: 16px; |
| | | @media (max-width: 1200px) { |
| | | .search_form { |
| | | :deep(.el-form) { |
| | | .el-form-item { |
| | | margin-right: 12px; |
| | | margin-bottom: 8px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 992px) { |
| | | .search_form { |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | align-items: stretch; |
| | | gap: 12px; |
| | | |
| | | .el-form { |
| | | :deep(.el-form) { |
| | | width: 100%; |
| | | |
| | | .el-form-item { |
| | | width: 100%; |
| | | margin-right: 12px; |
| | | margin-bottom: 8px; |
| | | flex: 1; |
| | | min-width: 200px; |
| | | |
| | | &:last-child { |
| | | margin-right: 12px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | > div { |
| | | width: 100%; |
| | | display: flex; |
| | | gap: 12px; |
| | | justify-content: flex-end; |
| | | } |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .app-container { |
| | | padding: 12px; |
| | | } |
| | | |
| | | .search_form { |
| | | padding: 16px; |
| | | gap: 12px; |
| | | |
| | | :deep(.el-form) { |
| | | flex-direction: column; |
| | | width: 100%; |
| | | |
| | | .el-form-item { |
| | | width: 100%; |
| | | margin-right: 0; |
| | | margin-bottom: 12px; |
| | | |
| | | &:last-child { |
| | | margin-right: 0; |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .el-form-item__content { |
| | | width: 100%; |
| | | |
| | | .el-input, |
| | | .el-select, |
| | | .el-date-editor { |
| | | width: 100% !important; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | > div { |
| | | width: 100%; |
| | | justify-content: stretch; |
| | | |
| | | .el-button { |
| | | flex: 1; |
| | |
| | | } |
| | | } |
| | | |
| | | .table_list { |
| | | height: calc(100vh - 300px); |
| | | } |
| | | |
| | | :deep(.el-table) { |
| | | th, |
| | | td { |
| | | padding: 10px 0; |
| | | padding: 8px 0; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-dialog) { |
| | | width: 90% !important; |
| | | margin: 20px auto !important; |
| | | width: 95% !important; |
| | | margin: 10px auto !important; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 480px) { |
| | | .search_form { |
| | | padding: 12px; |
| | | |
| | | > div { |
| | | flex-direction: column; |
| | | gap: 8px; |
| | | |
| | | .el-button { |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .consumption-value { |
| | |
| | | style="width: 140px;" |
| | | @change="handleQuery"> |
| | | <el-option label="æ°´" |
| | | value="water" /> |
| | | value="æ°´" /> |
| | | <el-option label="çµ" |
| | | value="electricity" /> |
| | | value="çµ" /> |
| | | <el-option label="æ°" |
| | | value="gas" /> |
| | | value="æ°" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <!-- <el-form-item label="æ¥æèå´:"> |
| | | <el-form-item label="è½æºåç§°:"> |
| | | <el-input v-model="searchForm.energyName" |
| | | 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="è³" |
| | |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 240px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> --> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="handleQuery">æç´¢</el-button> |
| | |
| | | @click="handleAdd">æ°å¢</el-button> |
| | | <el-button type="success" |
| | | @click="handleExport">导åº</el-button> |
| | | <el-button type="warning" |
| | | @click="handleImport">导å
¥</el-button> |
| | | </div> |
| | | </div> |
| | | <!-- æ°æ®è¡¨æ ¼ --> |
| | |
| | | min-width="150" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="æä½" |
| | | width="180" |
| | | width="220" |
| | | align="center" |
| | | fixed="right"> |
| | | <template #default="scope"> |
| | |
| | | <el-button type="danger" |
| | | link |
| | | @click="handleDelete(scope.row)">å é¤</el-button> |
| | | <el-button type="info" |
| | | link |
| | | @click="downLoadFile(scope.row)">éä»¶</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- éä»¶åè¡¨å¼¹çª --> |
| | | <FileListDialog ref="fileListRef" |
| | | v-model="fileListDialogVisible" |
| | | :show-upload-button="true" |
| | | :show-delete-button="true" |
| | | :is-show-pagination="true" |
| | | :page="filePagination" |
| | | :upload-method="handleUpload" |
| | | :delete-method="handleFileDelete" |
| | | @pagination="paginationSearch" |
| | | title="éä»¶å表" /> |
| | | <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" /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import { ref, reactive, onMounted, getCurrentInstance } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Watermelon, Lightning } from "@element-plus/icons-vue"; |
| | | import ImportDialog from "@/components/Dialog/ImportDialog.vue"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import FileListDialog from "@/components/Dialog/FileListDialog.vue"; |
| | | import request from "@/utils/request"; |
| | | import { |
| | | energyConsumptionDetailListPage, |
| | | energyConsumptionDetailAdd, |
| | | energyConsumptionDetailDelete, |
| | | energyTypeListPage, |
| | | fileListPage, |
| | | energyConsumptionDetailFileAdd, |
| | | energyConsumptionDetailFileDel, |
| | | } from "@/api/energyManagement/energyType"; |
| | | |
| | | // æç´¢è¡¨å |
| | |
| | | const formRef = ref(null); |
| | | const isEdit = ref(false); |
| | | const currentId = ref(null); |
| | | |
| | | // éä»¶ç¸å
³ |
| | | const fileListRef = ref(null); |
| | | const fileListDialogVisible = ref(false); |
| | | const currentFileRow = ref(null); |
| | | const filePagination = ref({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | |
| | | // 导å
¥ç¸å
³ |
| | | const importDialogRef = ref(null); |
| | | const importDialogVisible = ref(false); |
| | | const importAction = |
| | | import.meta.env.VITE_APP_BASE_API + "/energyConsumptionDetail/importData"; |
| | | const importHeaders = ref({ |
| | | Authorization: `Bearer ${getToken()}`, |
| | | }); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | |
| | | current: page.current, |
| | | size: page.size, |
| | | type: "ç产", |
| | | // energyType: searchForm.energyType, |
| | | // startDate: |
| | | // searchForm.dateRange && searchForm.dateRange.length === 2 |
| | | // ? searchForm.dateRange[0] |
| | | // : null, |
| | | // endDate: |
| | | // searchForm.dateRange && searchForm.dateRange.length === 2 |
| | | // ? searchForm.dateRange[1] |
| | | // : null, |
| | | energyTyep: searchForm.energyType, |
| | | energyName: searchForm.energyName, |
| | | startDate: |
| | | searchForm.dateRange && searchForm.dateRange.length === 2 |
| | | ? searchForm.dateRange[0] |
| | | : null, |
| | | endDate: |
| | | searchForm.dateRange && searchForm.dateRange.length === 2 |
| | | ? searchForm.dateRange[1] |
| | | : null, |
| | | }; |
| | | energyConsumptionDetailListPage(params) |
| | | .then(res => { |
| | |
| | | // éç½® |
| | | const handleReset = () => { |
| | | searchForm.energyType = ""; |
| | | searchForm.energyName = ""; |
| | | searchForm.dateRange = []; |
| | | page.current = 1; |
| | | handleQuery(); |
| | |
| | | }); |
| | | }; |
| | | |
| | | // ä¸è½½æä»¶ |
| | | const downLoadFile = row => { |
| | | currentFileRow.value = row; |
| | | fileListPage({ |
| | | energyConsumptionDetailId: row.id, |
| | | current: filePagination.value.current, |
| | | size: filePagination.value.size, |
| | | }).then(res => { |
| | | if (fileListRef.value) { |
| | | fileListRef.value.open(res.data.records); |
| | | } |
| | | filePagination.value.total = res.data.total || 0; |
| | | }); |
| | | }; |
| | | |
| | | // ä¸ä¼ éä»¶ |
| | | const handleUpload = async () => { |
| | | if (!currentFileRow.value) { |
| | | ElMessage.warning("请å
éæ©æ°æ®"); |
| | | return null; |
| | | } |
| | | |
| | | return new Promise(resolve => { |
| | | // å建ä¸ä¸ªéèçæä»¶è¾å
¥å
ç´ |
| | | const input = document.createElement("input"); |
| | | input.type = "file"; |
| | | input.style.display = "none"; |
| | | input.onchange = async e => { |
| | | const file = e.target.files[0]; |
| | | if (!file) { |
| | | resolve(null); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | // ä½¿ç¨ FormData ä¸ä¼ æä»¶ |
| | | const formData = new FormData(); |
| | | formData.append("file", file); |
| | | |
| | | const uploadRes = await request({ |
| | | url: "/file/upload", |
| | | method: "post", |
| | | data: formData, |
| | | headers: { |
| | | "Content-Type": "multipart/form-data", |
| | | Authorization: `Bearer ${getToken()}`, |
| | | }, |
| | | }); |
| | | |
| | | if (uploadRes.code === 200) { |
| | | // ä¿åéä»¶ä¿¡æ¯ |
| | | const fileData = { |
| | | energyConsumptionDetailId: currentFileRow.value.id, |
| | | name: uploadRes.data.originalName || file.name, |
| | | url: uploadRes.data.tempPath || uploadRes.data.url, |
| | | }; |
| | | |
| | | const saveRes = await energyConsumptionDetailFileAdd(fileData); |
| | | if (saveRes.code === 200) { |
| | | proxy.$modal.msgSuccess("æä»¶ä¸ä¼ æå"); |
| | | // éæ°å è½½æä»¶å表 |
| | | const listRes = await fileListPage({ |
| | | energyConsumptionDetailId: currentFileRow.value.id, |
| | | current: filePagination.value.current, |
| | | size: filePagination.value.size, |
| | | }); |
| | | if (listRes.code === 200 && fileListRef.value) { |
| | | const fileList = (listRes.data?.records || []).map(item => ({ |
| | | name: item.name, |
| | | url: item.url, |
| | | id: item.id, |
| | | ...item, |
| | | })); |
| | | fileListRef.value.setList(fileList); |
| | | filePagination.value.total = listRes.data?.total || 0; |
| | | } |
| | | // è¿åæ°æä»¶ä¿¡æ¯ |
| | | resolve({ |
| | | name: fileData.name, |
| | | url: fileData.url, |
| | | id: Date.now(), |
| | | }); |
| | | } else { |
| | | ElMessage.error(uploadRes.message || "æä»¶ä¸ä¼ 失败"); |
| | | resolve(null); |
| | | } |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("æä»¶ä¸ä¼ 失败"); |
| | | resolve(null); |
| | | } finally { |
| | | document.body.removeChild(input); |
| | | } |
| | | }; |
| | | |
| | | document.body.appendChild(input); |
| | | input.click(); |
| | | }); |
| | | }; |
| | | |
| | | // å页æç´¢ |
| | | const paginationSearch = async (page, size) => { |
| | | filePagination.value.current = page; |
| | | filePagination.value.size = size; |
| | | const listRes = await fileListPage({ |
| | | energyConsumptionDetailId: currentFileRow.value.id, |
| | | current: filePagination.value.current, |
| | | size: filePagination.value.size, |
| | | }); |
| | | if (listRes.code === 200) { |
| | | const fileList = (listRes.data?.records || []).map(item => ({ |
| | | name: item.name, |
| | | url: item.url, |
| | | id: item.id, |
| | | ...item, |
| | | })); |
| | | |
| | | fileListRef.value.setList(fileList); |
| | | filePagination.value.total = listRes.data?.total || 0; |
| | | } |
| | | }; |
| | | |
| | | // å é¤éä»¶ |
| | | const handleFileDelete = async row => { |
| | | try { |
| | | const res = await energyConsumptionDetailFileDel([row.id]); |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | // éæ°å è½½æä»¶å表 |
| | | if (currentFileRow.value && fileListRef.value) { |
| | | const listRes = await fileListPage({ |
| | | energyConsumptionDetailId: currentFileRow.value.id, |
| | | current: filePagination.value.current, |
| | | size: filePagination.value.size, |
| | | }); |
| | | if (listRes.code === 200) { |
| | | const fileList = (listRes.data?.records || []).map(item => ({ |
| | | name: item.name, |
| | | url: item.url, |
| | | id: item.id, |
| | | ...item, |
| | | })); |
| | | fileListRef.value.setList(fileList); |
| | | filePagination.value.total = listRes.data?.total || 0; |
| | | } |
| | | } |
| | | return true; // è¿å true 表示å 餿åï¼ç»ä»¶ä¼æ´æ°å表 |
| | | } else { |
| | | proxy.$modal.msgError(res.msg || "å é¤å¤±è´¥"); |
| | | return false; |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("å é¤å¤±è´¥"); |
| | | return false; |
| | | } |
| | | }; |
| | | |
| | | // 导å
¥ |
| | | const handleImport = () => { |
| | | importDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 导å
¥æå |
| | | const handleImportSuccess = response => { |
| | | if (response.code === 200) { |
| | | ElMessage.success("导å
¥æå"); |
| | | importDialogVisible.value = false; |
| | | handleQuery(); |
| | | } else { |
| | | ElMessage.error(response.message || "导å
¥å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | // 导å
¥å¤±è´¥ |
| | | const handleImportError = error => { |
| | | ElMessage.error("导å
¥å¤±è´¥ï¼è¯·æ£æ¥æä»¶æ ¼å¼æ¯å¦æ£ç¡®"); |
| | | }; |
| | | |
| | | // 确认导å
¥ |
| | | const handleImportConfirm = () => { |
| | | if (importDialogRef.value) { |
| | | importDialogRef.value.submit(); |
| | | } |
| | | }; |
| | | |
| | | // ä¸è½½æ¨¡æ¿ |
| | | const handleDownloadTemplate = () => { |
| | | proxy.download( |
| | | "/energyConsumptionDetail/downloadTemplate", |
| | | {}, |
| | | "ç产è½è导å
¥æ¨¡æ¿.xlsx" |
| | | ); |
| | | }; |
| | | |
| | | // å
³é导å
¥å¼¹çª |
| | | const handleImportClose = () => { |
| | | importDialogVisible.value = false; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getEnergyTypeList(); |
| | | handleQuery(); |
| | |
| | | .search_form { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | align-items: flex-start; |
| | | flex-wrap: wrap; |
| | | gap: 16px; |
| | | margin-bottom: 24px; |
| | | padding: 20px; |
| | | background-color: #ffffff; |
| | |
| | | |
| | | &:hover { |
| | | box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.08); |
| | | } |
| | | |
| | | :deep(.el-form) { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 0; |
| | | |
| | | .el-form-item { |
| | | margin-right: 16px; |
| | | margin-bottom: 0; |
| | | |
| | | &:last-child { |
| | | margin-right: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | > div { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | flex-shrink: 0; |
| | | } |
| | | } |
| | | |
| | |
| | | font-size: 12px; |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .app-container { |
| | | padding: 16px; |
| | | @media (max-width: 1200px) { |
| | | .search_form { |
| | | :deep(.el-form) { |
| | | .el-form-item { |
| | | margin-right: 12px; |
| | | margin-bottom: 8px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 992px) { |
| | | .search_form { |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | align-items: stretch; |
| | | gap: 12px; |
| | | |
| | | .el-form { |
| | | :deep(.el-form) { |
| | | width: 100%; |
| | | |
| | | .el-form-item { |
| | | width: 100%; |
| | | margin-right: 12px; |
| | | margin-bottom: 8px; |
| | | flex: 1; |
| | | min-width: 200px; |
| | | |
| | | &:last-child { |
| | | margin-right: 12px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | > div { |
| | | width: 100%; |
| | | display: flex; |
| | | gap: 12px; |
| | | justify-content: flex-end; |
| | | } |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .app-container { |
| | | padding: 12px; |
| | | } |
| | | |
| | | .search_form { |
| | | padding: 16px; |
| | | gap: 12px; |
| | | |
| | | :deep(.el-form) { |
| | | flex-direction: column; |
| | | width: 100%; |
| | | |
| | | .el-form-item { |
| | | width: 100%; |
| | | margin-right: 0; |
| | | margin-bottom: 12px; |
| | | |
| | | &:last-child { |
| | | margin-right: 0; |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .el-form-item__content { |
| | | width: 100%; |
| | | |
| | | .el-input, |
| | | .el-select, |
| | | .el-date-editor { |
| | | width: 100% !important; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | > div { |
| | | width: 100%; |
| | | justify-content: stretch; |
| | | |
| | | .el-button { |
| | | flex: 1; |
| | |
| | | } |
| | | } |
| | | |
| | | .table_list { |
| | | height: calc(100vh - 300px); |
| | | } |
| | | |
| | | :deep(.el-table) { |
| | | th, |
| | | td { |
| | | padding: 10px 0; |
| | | padding: 8px 0; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-dialog) { |
| | | width: 90% !important; |
| | | margin: 20px auto !important; |
| | | width: 95% !important; |
| | | margin: 10px auto !important; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 480px) { |
| | | .search_form { |
| | | padding: 12px; |
| | | |
| | | > div { |
| | | flex-direction: column; |
| | | gap: 8px; |
| | | |
| | | .el-button { |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .consumption-value { |
| | |
| | | :align="item.align" |
| | | :sortable="!!item.sortable" |
| | | :type="item.type" |
| | | :width="item.width"> |
| | | :width="item.width" |
| | | :class-name="item.className || ''"> |
| | | <template #header="scope"> |
| | | <div class="pim-table-header-cell"> |
| | | <div class="pim-table-header-title"> |
| | |
| | | </template> |
| | | <template #default="scope"> |
| | | <!-- ææ§½ --> |
| | | <div v-if="item.dataType == 'slot'"> |
| | | <div v-if="item.dataType == 'slot'" |
| | | :class="item.className || ''"> |
| | | <slot v-if="item.slot" |
| | | :index="scope.$index" |
| | | :name="item.slot" |
| | | :row="scope.row" /> |
| | | </div> |
| | | <!-- è¿åº¦æ¡ --> |
| | | <div v-else-if="item.dataType == 'progress'"> |
| | | <div v-else-if="item.dataType == 'progress'" |
| | | :class="item.className || ''"> |
| | | <el-progress :percentage="Number(scope.row[item.prop])" /> |
| | | </div> |
| | | <!-- å¾ç --> |
| | | <div v-else-if="item.dataType == 'image'"> |
| | | <div v-else-if="item.dataType == 'image'" |
| | | :class="item.className || ''"> |
| | | <img :src="javaApi + '/img/' + scope.row[item.prop]" |
| | | alt="" |
| | | style="width: 40px; height: 40px; margin-top: 10px" /> |
| | | </div> |
| | | <!-- tag --> |
| | | <div v-else-if="item.dataType == 'tag'"> |
| | | <div v-else-if="item.dataType == 'tag'" |
| | | :class="item.className || ''"> |
| | | <el-tag v-if=" |
| | | typeof dataTypeFn(scope.row[item.prop], item.formatData) === |
| | | 'string' |
| | |
| | | </div> |
| | | <!-- æé® --> |
| | | <div v-else-if="item.dataType == 'action'" |
| | | :class="item.className || ''" |
| | | @click.stop> |
| | | <template v-for="(o, key) in item.operation" |
| | | :key="key"> |
| | |
| | | </div> |
| | | <!-- å¯ç¹å»çæå --> |
| | | <div v-else-if="item.dataType == 'link'" |
| | | :class="item.className || ''" |
| | | class="cell link" |
| | | style="width: 100%" |
| | | @click="goLink(scope.row, item.linkMethod)"> |
| | |
| | | <!-- é»è®¤çº¯å±ç¤ºæ°æ® --> |
| | | <div v-else |
| | | class="cell" |
| | | :class="item.className || ''" |
| | | style="width: 100%"> |
| | | <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span> |
| | | <span v-else>{{ |
| | |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" |
| | | :inline="true"> |
| | | <el-form-item label="车é´:"> |
| | | <el-select v-model="searchForm.workshop" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | style="width: 160px;" |
| | | @change="handleQuery"> |
| | | <el-option label="车é´1" |
| | | value="1" /> |
| | | <el-option label="车é´2" |
| | | value="2" /> |
| | | <el-option label="车é´3" |
| | | value="3" /> |
| | | </el-select> |
| | | <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-select v-model="searchForm.status" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | style="width: 160px;" |
| | | @change="handleQuery"> |
| | | <el-option label="å¾
å¤ç" |
| | | value="pending" /> |
| | | <el-option label="è¿è¡ä¸" |
| | | value="processing" /> |
| | | <el-option label="已宿" |
| | | value="completed" /> |
| | | </el-select> |
| | | <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-input v-model="searchForm.productSpec" |
| | | 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> |
| | | <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> |
| | | <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">æåæ°æ®</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> |
| | | <el-button type="primary" |
| | | @click="handleMerge">åå¹¶ä¸å</el-button> |
| | | <el-button type="info" |
| | | @click="showCategorySummaryDialog = true">产åç±»å«æ±æ»</el-button> |
| | | <!-- <el-button type="danger" |
| | | @click="handleDelete">å é¤</el-button> --> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | |
| | | <!-- åå¹¶ä¸åå¼¹çª --> |
| | | <el-dialog v-model="isShowNewModal" |
| | | title="åå¹¶ä¸å" |
| | | width="500px"> |
| | | width="600px"> |
| | | <el-form :model="mergeForm" |
| | | label-width="120px"> |
| | | <el-form-item label="åºåå·"> |
| | | <el-input v-model="mergeForm.serialNo" |
| | | disabled /> |
| | | <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.productSpec || '-' }}</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="çäº§è®¡åæ°é"> |
| | | <el-input-number v-model="mergeForm.totalquantity" |
| | | :min="1" |
| | | :step="1" |
| | | <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-form-item label="夿³¨"> |
| | | <el-input v-model="mergeForm.remark" |
| | | type="textarea" /> |
| | | </el-form-item> |
| | | </el-form-item> --> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- 产åç±»å«æ±æ»å¼¹çª --> |
| | | <el-dialog v-model="showCategorySummaryDialog" |
| | | title="产åç±»å«æ±æ»ç»è®¡" |
| | | width="400px"> |
| | | <el-table :data="categorySummary" |
| | | border |
| | | style="width: 100%"> |
| | | <el-table-column prop="materialCategory" |
| | | label="产åç±»å«" |
| | | align="center" |
| | | width="150" /> |
| | | <el-table-column prop="totalquantity" |
| | | label="æ»å¶é æ°é" |
| | | align="center" /> |
| | | </el-table> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="showCategorySummaryDialog = false">å
³é</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- 追踪è¿åº¦å¼¹çª --> |
| | | <el-dialog v-model="showTrackProgressDialog" |
| | | :title="`追踪è¿åº¦ - ${trackProgressForm.serialNo || ''}`" |
| | | :title="`追踪è¿åº¦ - ${trackProgressForm.materialCode || ''}`" |
| | | width="600px"> |
| | | <el-form :model="trackProgressForm" |
| | | label-width="120px"> |
| | | <el-form-item label="åºåå·"> |
| | | <el-input v-model="trackProgressForm.serialNo" |
| | | <el-form-item label="ç©æç¼ç "> |
| | | <el-input v-model="trackProgressForm.materialCode" |
| | | disabled /> |
| | | </el-form-item> |
| | | <el-form-item label="å½åç¶æ"> |
| | |
| | | </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" |
| | | :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="productName"> |
| | | <el-input v-model="form.productName" |
| | | placeholder="请è¾å
¥äº§ååç§°" /> |
| | | </el-form-item> |
| | | <el-form-item label="产åè§æ ¼" |
| | | prop="productSpec"> |
| | | <el-input v-model="form.productSpec" |
| | | placeholder="请è¾å
¥äº§åè§æ ¼" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç©æç¼ç " |
| | | prop="materialCode"> |
| | | <el-input v-model="form.materialCode" |
| | | placeholder="请è¾å
¥ç©æç¼ç " /> |
| | | </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"> |
| | | <el-input v-model="form.strength" |
| | | placeholder="请è¾å
¥å¼ºåº¦" /> |
| | | </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 } from "vue"; |
| | | import { onMounted, ref, reactive, getCurrentInstance } from "vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import { productionPlanListPage } from "@/api/productionPlan/productionPlan.js"; |
| | | import ImportDialog from "@/components/Dialog/ImportDialog.vue"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import { |
| | | productionPlanListPage, |
| | | loadProdData, |
| | | exportProductionPlan, |
| | | productionPlanAdd, |
| | | productionPlanUpdate, |
| | | productionPlanDelete, |
| | | productionPlanCombine, |
| | | } from "@/api/productionPlan/productionPlan.js"; |
| | | import PIMTable from "./components/PIMTable.vue"; |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "æ¥æº", |
| | | prop: "source", |
| | | width: "100px", |
| | | label: "ç³è¯·åç¼å·", |
| | | prop: "applyNo", |
| | | width: "150px", |
| | | className: "code-cell", |
| | | }, |
| | | { |
| | | label: "ç¶æ", |
| | | prop: "status", |
| | | width: "80px", |
| | | }, |
| | | { |
| | | label: "å®¡æ ¸ç¶æ", |
| | | prop: "auditStatus", |
| | | width: "100px", |
| | | }, |
| | | { |
| | | label: "订åå·", |
| | | prop: "orderNo", |
| | | width: "120px", |
| | | }, |
| | | { |
| | | label: "åºåå·", |
| | | prop: "serialNo", |
| | | width: "140px", |
| | | }, |
| | | { |
| | | label: "é¶ä»¶å·", |
| | | prop: "partNo", |
| | | width: "120px", |
| | | }, |
| | | { |
| | | label: "é¶ä»¶", |
| | | prop: "partName", |
| | | width: "120px", |
| | | }, |
| | | { |
| | | label: "产åç±»å«", |
| | | prop: "materialCategory", |
| | | width: "100px", |
| | | }, |
| | | { |
| | | label: "å·¥èºæä»¶å·", |
| | | prop: "processFileNo", |
| | | width: "140px", |
| | | }, |
| | | { |
| | | label: "é宿°é", |
| | | prop: "salesQuantity", |
| | | width: "100px", |
| | | align: "right", |
| | | }, |
| | | { |
| | | label: "å¶é æ°é", |
| | | prop: "quantity", |
| | | width: "100px", |
| | | align: "right", |
| | | }, |
| | | { |
| | | label: "é¶ä»¶åä½", |
| | | prop: "partUnit", |
| | | width: "80px", |
| | | }, |
| | | { |
| | | label: "主计åéæ±æ¥æ", |
| | | prop: "mainPlanDemandDate", |
| | | formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""), |
| | | width: "140px", |
| | | }, |
| | | { |
| | | label: "æ¿è¯ºæ¥æ", |
| | | prop: "commitmentDate", |
| | | formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""), |
| | | width: "120px", |
| | | }, |
| | | { |
| | | label: "å¶é 屿§", |
| | | prop: "manufactureProperty", |
| | | width: "100px", |
| | | }, |
| | | { |
| | | label: "夿³¨", |
| | | prop: "remark", |
| | | label: "客æ·åç§°", |
| | | prop: "customerName", |
| | | width: "150px", |
| | | }, |
| | | { |
| | | label: "æ´æ°æ¶é´", |
| | | prop: "updateTime", |
| | | formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""), |
| | | width: "120px", |
| | | }, |
| | | { |
| | | label: "æ´æ°äºº", |
| | | prop: "updateBy", |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | width: "100px", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | const typeMap = { |
| | | æ¿æ: "primary", |
| | | ç å: "info", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "å建æ¶é´", |
| | | prop: "createTime", |
| | | formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""), |
| | | width: "120px", |
| | | label: "产åè§æ ¼", |
| | | prop: "productSpec", |
| | | width: "150px", |
| | | className: "spec-cell", |
| | | }, |
| | | { |
| | | label: "å建人", |
| | | prop: "createBy", |
| | | width: "100px", |
| | | label: "ç©æç¼ç ", |
| | | prop: "materialCode", |
| | | width: "150px", |
| | | className: "code-cell", |
| | | }, |
| | | { |
| | | label: "åæ°", |
| | | prop: "quantity", |
| | | className: "quantity-cell", |
| | | }, |
| | | { |
| | | label: "æ¹æ°", |
| | | prop: "volume", |
| | | width: "150px", |
| | | className: "volume-cell", |
| | | }, |
| | | { |
| | | label: "å·²ä¸åæ¹æ°", |
| | | prop: "assignedQuantity", |
| | | width: "150px", |
| | | className: "spec-cell", |
| | | }, |
| | | { |
| | | label: "é¿", |
| | | prop: "length", |
| | | className: "dimension-cell", |
| | | }, |
| | | { |
| | | label: "宽", |
| | | prop: "width", |
| | | className: "dimension-cell", |
| | | }, |
| | | { |
| | | label: "é«", |
| | | prop: "height", |
| | | className: "dimension-cell", |
| | | }, |
| | | { |
| | | 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", |
| | | }, |
| | | // { |
| | | // label: "æ°æ®æ¥æº", |
| | | // width: "100px", |
| | | // prop: "dataSourceType", |
| | | // formatData: cell => (cell == 1 ? "忥" : "æå¨"), |
| | | // }, |
| | | { |
| | | label: "夿³¨ 1", |
| | | prop: "remarkOne", |
| | | }, |
| | | { |
| | | label: "夿³¨ 2", |
| | | prop: "remarkTwo", |
| | | }, |
| | | |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 200, |
| | | width: 300, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "primary", |
| | | link: true, |
| | | clickFun: row => { |
| | | handleEdit(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "å é¤", |
| | | type: "danger", |
| | | link: true, |
| | | clickFun: row => { |
| | | handleDelete(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "ä¸å", |
| | | type: "text", |
| | | disabled: row => { |
| | | // 计ç®å©ä½æ¹æ° |
| | | const remainingVolume = |
| | | (row.volume || 0) - (row.assignedQuantity || 0); |
| | | // 妿å©ä½æ¹æ°å°äºçäº0ï¼ç¦æ¢éæ© |
| | | return remainingVolume <= 0; |
| | | }, |
| | | clickFun: row => { |
| | | // åç¬ä¸åæä½ |
| | | // è®¾ç½®è¡¨åæ°æ® |
| | | mergeForm.serialNo = row.serialNo; |
| | | mergeForm.totalquantity = row.quantity; |
| | | mergeForm.remark = ""; |
| | | |
| | | mergeForm.materialCode = row.materialCode; |
| | | mergeForm.productName = row.productName || ""; |
| | | mergeForm.productSpec = row.productSpec || ""; |
| | | mergeForm.length = row.length || 0; |
| | | mergeForm.width = row.width || 0; |
| | | mergeForm.height = row.height || 0; |
| | | mergeForm.totalAssignedQuantity = |
| | | Number(row.volume) - Number(row.assignedQuantity) || 0; |
| | | mergeForm.planCompleteTime = row.planCompleteTime || ""; |
| | | sumAssignedQuantity.value = mergeForm.totalAssignedQuantity; |
| | | // æå¼å¼¹çª |
| | | isShowNewModal.value = true; |
| | | }, |
| | |
| | | const isShowNewModal = ref(false); |
| | | // åå¹¶ä¸åè¡¨åæ°æ® |
| | | const mergeForm = reactive({ |
| | | serialNo: "", |
| | | totalquantity: 0, |
| | | remark: "", |
| | | materialCode: "", |
| | | productName: "", |
| | | productSpec: "", |
| | | length: 0, |
| | | width: 0, |
| | | height: 0, |
| | | totalAssignedQuantity: 0, |
| | | planCompleteTime: "", |
| | | }); |
| | | |
| | | // 追踪è¿åº¦å¼¹çªæ§å¶ |
| | | const showTrackProgressDialog = ref(false); |
| | | // 追踪è¿åº¦è¡¨åæ°æ® |
| | | const trackProgressForm = reactive({ |
| | | serialNo: "", |
| | | materialCode: "", |
| | | currentStatus: "", |
| | | completionRate: 0, |
| | | progressDetails: [], |
| | | remark: "", |
| | | }); |
| | | |
| | | // 导å
¥ç¸å
³ |
| | | 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 formRef = ref(null); |
| | | const form = reactive({ |
| | | id: undefined, |
| | | applyNo: "", |
| | | customerName: "", |
| | | productName: "", |
| | | productSpec: "", |
| | | materialCode: "", |
| | | quantity: 0, |
| | | volume: 0, |
| | | length: 0, |
| | | width: 0, |
| | | height: 0, |
| | | startDate: "", |
| | | endDate: "", |
| | | strength: "", |
| | | remarkOne: "", |
| | | remarkTwo: "", |
| | | }); |
| | | const rules = reactive({ |
| | | applyNo: [{ required: true, message: "请è¾å
¥ç³è¯·åç¼å·", trigger: "blur" }], |
| | | customerName: [ |
| | | { required: true, message: "请è¾å
¥å®¢æ·åç§°", trigger: "blur" }, |
| | | ], |
| | | productName: [{ required: true, message: "请è¾å
¥äº§ååç§°", trigger: "blur" }], |
| | | productSpec: [{ required: true, message: "请è¾å
¥äº§åè§æ ¼", trigger: "blur" }], |
| | | materialCode: [ |
| | | { required: true, message: "请è¾å
¥ç©æç¼ç ", trigger: "blur" }, |
| | | ], |
| | | }); |
| | | |
| | | // å¤ç追踪è¿åº¦æé®ç¹å» |
| | | const handleTrackProgress = row => { |
| | | // è®¾ç½®è¡¨åæ°æ® |
| | | trackProgressForm.serialNo = row.serialNo; |
| | | trackProgressForm.materialCode = row.materialCode; |
| | | trackProgressForm.currentStatus = row.status; |
| | | |
| | | // çææ¨¡æè¿åº¦æ°æ® |
| | |
| | | |
| | | // æå¼å¼¹çª |
| | | showTrackProgressDialog.value = true; |
| | | }; |
| | | const onBlur = value => { |
| | | // éå¶åä½å°æ° |
| | | mergeForm.totalAssignedQuantity = Number(value.toFixed(4)); |
| | | }; |
| | | |
| | | // çææ¨¡æè¿åº¦è¯¦æ
æ°æ® |
| | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | customerName: "", |
| | | salesContractNo: "", |
| | | projectName: "", |
| | | materialCategory: "", |
| | | specificationModel: "", |
| | | productName: "", |
| | | productSpec: "", |
| | | materialCode: "", |
| | | applyNo: "", |
| | | dateRange: [], |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | /** éç½®æé®æä½ */ |
| | | const handleReset = () => { |
| | | Object.assign(searchForm.value, { |
| | | customerName: "", |
| | | productName: "", |
| | | productSpec: "", |
| | | materialCode: "", |
| | | applyNo: "", |
| | | dateRange: [], |
| | | }); |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | |
| | | |
| | | // éåè¡¨æ ¼æ°æ®ï¼æäº§åç±»å«æ±æ» |
| | | tableData.value.forEach(row => { |
| | | const category = row.materialCategory; |
| | | const category = row.materialCode; |
| | | if (!summary[category]) { |
| | | summary[category] = { |
| | | materialCategory: category, |
| | | totalquantity: 0, |
| | | materialCode: category, |
| | | totalAssignedQuantity: 0, |
| | | }; |
| | | } |
| | | summary[category].totalquantity += row.quantity; |
| | | summary[category].totalAssignedQuantity += |
| | | Number(row.volume) - Number(row.assignedQuantity); |
| | | }); |
| | | |
| | | // 转æ¢ä¸ºæ°ç»æ ¼å¼ |
| | |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | // æé ä¸ä¸ªæ°ç对象ï¼ä¸å
å«entryDateåæ®µ |
| | | // æé æç´¢åæ° |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined; |
| | | // tableData.value = [ |
| | | // { |
| | | // id: 1, |
| | | // source: "éå®è®¢å", |
| | | // status: "å¾
å¤ç", |
| | | // auditStatus: "å·²å®¡æ ¸", |
| | | // orderNo: "SO20260301001", |
| | | // serialNo: "PP20260301001", |
| | | // partNo: "P001", |
| | | // partName: "é¶ä»¶A", |
| | | // materialCategory: "ç±»å«1", |
| | | // processFileNo: "PF20260301001", |
| | | // salesQuantity: 100, |
| | | // quantity: 105, |
| | | // partUnit: "个", |
| | | // mainPlanDemandDate: "2026-03-15", |
| | | // commitmentDate: "2026-03-10", |
| | | // manufactureProperty: "常è§", |
| | | // remark: "", |
| | | // updateTime: "2026-03-01", |
| | | // updateBy: "admin", |
| | | // createTime: "2026-03-01", |
| | | // createBy: "admin", |
| | | // }, |
| | | // { |
| | | // id: 2, |
| | | // source: "éå®è®¢å", |
| | | // status: "å¾
å¤ç", |
| | | // auditStatus: "å·²å®¡æ ¸", |
| | | // orderNo: "SO20260301002", |
| | | // serialNo: "PP20260301001", |
| | | // partNo: "P002", |
| | | // partName: "é¶ä»¶B", |
| | | // materialCategory: "ç±»å«1", |
| | | // processFileNo: "PF20260301002", |
| | | // salesQuantity: 200, |
| | | // quantity: 210, |
| | | // partUnit: "个", |
| | | // mainPlanDemandDate: "2026-03-15", |
| | | // commitmentDate: "2026-03-10", |
| | | // manufactureProperty: "常è§", |
| | | // remark: "", |
| | | // updateTime: "2026-03-01", |
| | | // updateBy: "admin", |
| | | // createTime: "2026-03-01", |
| | | // createBy: "admin", |
| | | // }, |
| | | // { |
| | | // id: 3, |
| | | // source: "éå®è®¢å", |
| | | // status: "è¿è¡ä¸", |
| | | // auditStatus: "å·²å®¡æ ¸", |
| | | // orderNo: "SO20260301003", |
| | | // serialNo: "PP20260301002", |
| | | // partNo: "P003", |
| | | // partName: "é¶ä»¶C", |
| | | // materialCategory: "ç±»å«2", |
| | | // processFileNo: "PF20260301003", |
| | | // salesQuantity: 150, |
| | | // quantity: 155, |
| | | // partUnit: "个", |
| | | // mainPlanDemandDate: "2026-03-20", |
| | | // commitmentDate: "2026-03-15", |
| | | // manufactureProperty: "常è§", |
| | | // remark: "", |
| | | // updateTime: "2026-03-01", |
| | | // updateBy: "admin", |
| | | // createTime: "2026-03-01", |
| | | // createBy: "admin", |
| | | // }, |
| | | // { |
| | | // id: 4, |
| | | // source: "éå®è®¢å", |
| | | // status: "è¿è¡ä¸", |
| | | // auditStatus: "å·²å®¡æ ¸", |
| | | // orderNo: "SO20260301004", |
| | | // serialNo: "PP20260301002", |
| | | // partNo: "P004", |
| | | // partName: "é¶ä»¶D", |
| | | // materialCategory: "ç±»å«2", |
| | | // processFileNo: "PF20260301004", |
| | | // salesQuantity: 300, |
| | | // quantity: 315, |
| | | // partUnit: "个", |
| | | // mainPlanDemandDate: "2026-03-20", |
| | | // commitmentDate: "2026-03-15", |
| | | // manufactureProperty: "常è§", |
| | | // remark: "", |
| | | // updateTime: "2026-03-01", |
| | | // updateBy: "admin", |
| | | // createTime: "2026-03-01", |
| | | // createBy: "admin", |
| | | // }, |
| | | // { |
| | | // id: 5, |
| | | // source: "éå®è®¢å", |
| | | // status: "已宿", |
| | | // auditStatus: "å·²å®¡æ ¸", |
| | | // orderNo: "SO20260301005", |
| | | // serialNo: "PP20260301003", |
| | | // partNo: "P005", |
| | | // partName: "é¶ä»¶E", |
| | | // materialCategory: "ç±»å«3", |
| | | // processFileNo: "PF20260301005", |
| | | // salesQuantity: 250, |
| | | // quantity: 260, |
| | | // partUnit: "个", |
| | | // mainPlanDemandDate: "2026-03-10", |
| | | // commitmentDate: "2026-03-05", |
| | | // manufactureProperty: "常è§", |
| | | // remark: "", |
| | | // updateTime: "2026-03-01", |
| | | // updateBy: "admin", |
| | | // createTime: "2026-03-01", |
| | | // createBy: "admin", |
| | | // }, |
| | | // ]; |
| | | // tableLoading.value = false; |
| | | // page.total = tableData.value.length; |
| | | // // 计ç®äº§åç±»å«æ±æ»ç»è®¡ |
| | | // calculateCategorySummary(); |
| | | params.startDate = params.dateRange ? params.dateRange[0] : ""; |
| | | params.endDate = params.dateRange ? params.dateRange[1] : ""; |
| | | delete params.dateRange; |
| | | productionPlanListPage(params) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | |
| | | selectedRows.value = selection; |
| | | // 妿æéä¸çè¡ï¼è®°å½ç¬¬ä¸ä¸ªéä¸è¡çåºåå· |
| | | if (selection.length > 0) { |
| | | selectedserialNo.value = selection[0].serialNo; |
| | | 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.serialNo === selectedserialNo.value; |
| | | return row.materialCode === selectedserialNo.value; |
| | | }; |
| | | |
| | | // æåæ°æ®æé®æä½ |
| | | const getLoadProdData = () => { |
| | | loadProdData() |
| | | .then(res => {}) |
| | | .catch(() => {}); |
| | | }; |
| | | const sumAssignedQuantity = ref(0); |
| | | // å¤çåå¹¶ä¸åæé®ç¹å» |
| | | const handleMerge = () => { |
| | | if (selectedRows.value.length === 0) { |
| | | ElMessage.warning("è¯·éæ©è¦åå¹¶ä¸åçç产计å"); |
| | | return; |
| | | } |
| | | |
| | | console.log(selectedRows.value); |
| | | // è®¡ç®æ»å¶é æ°é |
| | | const totalQuantity = selectedRows.value.reduce((sum, row) => { |
| | | return sum + row.quantity; |
| | | const totalAssignedQuantity = selectedRows.value.reduce((sum, row) => { |
| | | return ( |
| | | sum + |
| | | (row.volume == null |
| | | ? 0 |
| | | : Number(row.volume) - Number(row.assignedQuantity)) |
| | | ); |
| | | }, 0); |
| | | |
| | | sumAssignedQuantity.value = totalAssignedQuantity; |
| | | console.log(totalAssignedQuantity); |
| | | // è®¾ç½®è¡¨åæ°æ® |
| | | mergeForm.serialNo = selectedserialNo.value; |
| | | mergeForm.totalquantity = totalQuantity; |
| | | mergeForm.remark = ""; |
| | | const firstRow = selectedRows.value[0]; |
| | | mergeForm.materialCode = selectedserialNo.value; |
| | | mergeForm.productName = firstRow.productName || ""; |
| | | mergeForm.productSpec = firstRow.productSpec || ""; |
| | | mergeForm.length = firstRow.length || 0; |
| | | mergeForm.width = firstRow.width || 0; |
| | | mergeForm.height = firstRow.height || 0; |
| | | mergeForm.totalAssignedQuantity = totalAssignedQuantity; |
| | | mergeForm.planCompleteTime = firstRow.planCompleteTime || ""; |
| | | |
| | | // æå¼å¼¹çª |
| | | isShowNewModal.value = true; |
| | |
| | | |
| | | // å¤çåå¹¶ä¸åæäº¤ |
| | | const handleMergeSubmit = () => { |
| | | // è¿éå¯ä»¥æ·»å ä¸åé»è¾ |
| | | ElMessage.success("åå¹¶ä¸åæå"); |
| | | isShowNewModal.value = false; |
| | | 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; |
| | | } |
| | | |
| | | mergeForm.ids = selectedRows.value.map(row => row.id); |
| | | console.log(mergeForm, "mergeForm"); |
| | | productionPlanCombine(mergeForm) |
| | | .then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success("åå¹¶ä¸åæå"); |
| | | isShowNewModal.value = false; |
| | | // å¯ä»¥éæ©å·æ°å表æå
¶ä»æä½ |
| | | } 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.message || "导å
¥å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | // 导å
¥å¤±è´¥ |
| | | 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: "", |
| | | productSpec: "", |
| | | materialCode: "", |
| | | quantity: 0, |
| | | volume: 0, |
| | | length: 0, |
| | | width: 0, |
| | | height: 0, |
| | | startDate: "", |
| | | endDate: "", |
| | | strength: "", |
| | | remarkOne: "", |
| | | remarkTwo: "", |
| | | }); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // ç¼è¾ |
| | | const handleEdit = row => { |
| | | operationType.value = "edit"; |
| | | Object.assign(form, { |
| | | id: row.id, |
| | | applyNo: row.applyNo || "", |
| | | customerName: row.customerName || "", |
| | | productName: row.productName || "", |
| | | productSpec: row.productSpec || "", |
| | | 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; |
| | | }; |
| | | |
| | | // å é¤ |
| | | 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) { |
| | | const payload = { ...form }; |
| | | if (operationType.value === "add") { |
| | | 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(() => { |
| | |
| | | border: none; |
| | | border-radius: 6px; |
| | | overflow: hidden; |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.1); |
| | | |
| | | .el-table__header-wrapper { |
| | | background-color: #fafafa; |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | |
| | | th { |
| | | background-color: #fafafa; |
| | | background: transparent; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | border-bottom: 1px solid #ebeef5; |
| | | padding: 14px 0; |
| | | color: #ffffff; |
| | | border-bottom: none; |
| | | padding: 16px 0; |
| | | font-size: 14px; |
| | | letter-spacing: 0.5px; |
| | | } |
| | | } |
| | | |
| | |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | background-color: #f5f7fa; |
| | | 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 #ebeef5; |
| | | padding: 12px 0; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | padding: 14px 0; |
| | | color: #303133; |
| | | font-size: 13px; |
| | | } |
| | | } |
| | | |
| | | tr.current-row { |
| | | background-color: #ecf5ff; |
| | | 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; |
| | | font-size: 14px; |
| | | 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-size: 12px; |
| | | 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: 40px 0; |
| | | 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 { |
| | |
| | | color: #909399; |
| | | margin-left: 4px; |
| | | } |
| | | .search_form { |
| | | :deep(.el-form-item) { |
| | | margin-bottom: 0px !important; |
| | | } |
| | | } |
| | | // .search_form { |
| | | // :deep(.el-form-item) { |
| | | // margin-bottom: 0px !important; |
| | | // } |
| | | // } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="table_list"> |
| | | <PIMTable rowKey="materialCode" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | height="calc(100vh - 200px)" |
| | | :tableLoading="tableLoading" |
| | | :isSelection="false" |
| | | @pagination="pagination"> |
| | | </PIMTable> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref, reactive } from "vue"; |
| | | import { summaryByProductType } from "@/api/productionPlan/productionPlan.js"; |
| | | import PIMTable from "../productionPlan/components/PIMTable.vue"; |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ç©æç¼ç ", |
| | | prop: "materialCode", |
| | | className: "code-cell", |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | const typeMap = { |
| | | æ¿æ: "primary", |
| | | ç å: "info", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "产åè§æ ¼", |
| | | prop: "productSpec", |
| | | className: "spec-cell", |
| | | }, |
| | | { |
| | | label: "é¿", |
| | | prop: "length", |
| | | className: "dimension-cell", |
| | | }, |
| | | { |
| | | label: "宽", |
| | | prop: "width", |
| | | className: "dimension-cell", |
| | | }, |
| | | { |
| | | label: "é«", |
| | | prop: "height", |
| | | className: "dimension-cell", |
| | | }, |
| | | { |
| | | label: "åæ°", |
| | | prop: "quantity", |
| | | className: "quantity-cell", |
| | | }, |
| | | { |
| | | label: "æ¹æ°", |
| | | prop: "volume", |
| | | className: "volume-cell", |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | productName: "", |
| | | productSpec: "", |
| | | }); |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | // æé ä¸ä¸ªæ°ç对象ï¼ä¸å
å«entryDateåæ®µ |
| | | const params = { ...searchForm, ...page }; |
| | | params.entryDate = undefined; |
| | | summaryByProductType(params) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | |
| | | tableData.value = res.data; |
| | | page.total = res.total; |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .app-container { |
| | | padding: 24px; |
| | | background-color: #f0f2f5; |
| | | min-height: calc(100vh - 48px); |
| | | } |
| | | |
| | | .search_form { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | .table_list { |
| | | background-color: #ffffff; |
| | | border-radius: 6px; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05); |
| | | overflow: hidden; |
| | | height: calc(100vh - 150px); |
| | | } |
| | | |
| | | :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; |
| | | font-size: 14px; |
| | | 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; |
| | | font-size: 13px; |
| | | } |
| | | } |
| | | |
| | | 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; |
| | | font-size: 14px; |
| | | 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-size: 12px; |
| | | font-style: italic; |
| | | } |
| | | } |
| | | |
| | | .el-table__empty-block { |
| | | padding: 60px 0; |
| | | background-color: #fafafa; |
| | | } |
| | | } |
| | | |
| | | .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); |
| | | } |
| | | } |
| | | |
| | | @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%; |
| | | } |
| | | } |
| | | |
| | | .el-button { |
| | | margin-right: 12px; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-table) { |
| | | th, |
| | | td { |
| | | padding: 10px 0; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | } |
| | | </style> |