Merge branch 'dev_New' of http://114.132.189.42:9002/r/product-inventory-management into dev_New
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // åè´§å°è´¦é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function dangerInvestigationListPage(query) { |
| | | return request({ |
| | | url: "/safeHidden/page", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // æ°å¢å®å
¨è§ç¨ä¸èµè´¨ç®¡ç |
| | | export function safeHiddenAdd(query) { |
| | | return request({ |
| | | url: '/safeHidden', |
| | | method: 'post', |
| | | data: query |
| | | }) |
| | | } |
| | | // ä¿®æ¹å®å
¨è§ç¨ä¸èµè´¨ç®¡ç |
| | | export function safeHiddenUpdate(query) { |
| | | return request({ |
| | | url: '/safeHidden', |
| | | method: 'put', |
| | | data: query |
| | | }) |
| | | } |
| | | // å é¤å®å
¨è§ç¨ä¸èµè´¨ç®¡ç |
| | | export function safeHiddenDel(ids) { |
| | | return request({ |
| | | url: '/safeHidden/' + ids, |
| | | method: 'delete', |
| | | data: ids |
| | | }) |
| | | } |
| | | |
| | | // æ¥è¯¢éä»¶å表 |
| | | export function fileListPage(query) { |
| | | return request({ |
| | | url: "/safeHiddenFile/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | // æ·»å éä»¶ |
| | | export function safeHiddenFileAdd(query) { |
| | | return request({ |
| | | url: '/safeHiddenFile/add', |
| | | method: 'post', |
| | | data: query |
| | | }) |
| | | } |
| | | // å é¤éä»¶ |
| | | export function safeHiddenFileDel(ids) { |
| | | return request({ |
| | | url: '/safeHiddenFile/del', |
| | | method: 'delete', |
| | | data: ids |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | export function safeHazardRecordListPage(query) { |
| | | return request({ |
| | | url: "/safeHazardRecord/page", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function safeHazardRecordDel(ids) { |
| | | return request({ |
| | | url: '/safeHazardRecord/' + ids, |
| | | method: 'delete', |
| | | data: ids |
| | | }) |
| | | } |
| | | // æ°å¢å±é©æºå°è´¦ |
| | | export function safeHazardRecordAdd(query) { |
| | | return request({ |
| | | url: '/safeHazardRecord/borrow', |
| | | method: 'post', |
| | | data: query |
| | | }) |
| | | } |
| | | |
| | | export function safeHazardRecordUpdate(query) { |
| | | return request({ |
| | | url: '/safeHazardRecord/return', |
| | | method: 'put', |
| | | data: query |
| | | }) |
| | | } |
| | |
| | | contractTerm: 0, |
| | | contractStartTime: "", |
| | | contractEndTime: "", |
| | | staffState: "", |
| | | sysPostId: undefined, |
| | | sysDeptId: undefined, |
| | | }, |
| | |
| | | form.value = {...res.data} |
| | | if (form.value.sysPostId === 0) { |
| | | form.value.sysPostId = undefined |
| | | } |
| | | if (form.value.sysDeptId === 0) { |
| | | form.value.sysDeptId = undefined |
| | | } |
| | | // ç¼è¾æ¶ä¹è®¡ç®ä¸æ¬¡ååå¹´é |
| | | calculateContractTerm(); |
| | |
| | | if (!form.value.sysPostId) { |
| | | form.value.sysPostId = 0; |
| | | } |
| | | if (!form.value.sysDeptId) { |
| | | form.value.sysDeptId = 0; |
| | | } |
| | | proxy.$refs.formRef.validate(valid => { |
| | | if (valid) { |
| | | form.value.staffState = 1 |
| | | if (operationType.value === "add") { |
| | | createStaffOnJob(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | |
| | | item.futureTicketsAmount !== undefined ? item.futureTicketsAmount : (item.taxInclusiveTotalPrice || 0) |
| | | ); |
| | | |
| | | // æ°å¢æ¶ï¼æ¬æ¬¡å¼ç¥¨é»è®¤ä¸å¡«ï¼0ï¼ï¼é¿å
䏿å¼å°±æâæªæ¥ç¥¨æ°âæ£æ 0 |
| | | item.ticketsNum = 0; |
| | | item.ticketsAmount = 0; |
| | | |
| | | // 页é¢å±ç¤ºçâæªæ¥ç¥¨æ°/æªæ¥ç¥¨éé¢âé»è®¤å±ç¤ºåå§æªæ¥å¼ |
| | | item.futureTickets = item.tempFutureTickets; |
| | | item.futureTicketsAmount = item.tempFutureTicketsAmount; |
| | | // æ°å¢æ¶ï¼æ¬æ¬¡å¼ç¥¨æ°é»è®¤ = æªæ¥ç¥¨æ°ï¼ä¸ä¸è½å¤§äºæªæ¥ç¥¨æ°ï¼ |
| | | item.ticketsNum = Number(item.tempFutureTickets || 0); |
| | | // èå¨è®¡ç®æ¬æ¬¡å¼ç¥¨éé¢ãæªæ¥ç¥¨æ°ãæªæ¥ç¥¨éé¢ |
| | | const unitPrice = Number(item.taxInclusiveUnitPrice || 0); |
| | | item.ticketsAmount = Number((item.ticketsNum * unitPrice).toFixed(2)); |
| | | item.futureTickets = Number((item.tempFutureTickets - item.ticketsNum).toFixed(2)); |
| | | item.futureTicketsAmount = Number( |
| | | (item.tempFutureTicketsAmount - item.ticketsAmount).toFixed(2) |
| | | ); |
| | | }); |
| | | |
| | | form.productData = allProductData; |
| | |
| | | const totalAmount = allProductData.reduce((sum, item) => { |
| | | return sum + (Number(item.ticketsAmount) || 0); |
| | | }, 0); |
| | | form.invoiceAmount = totalAmount.toFixed(2); |
| | | form.invoiceAmount = Number(totalAmount.toFixed(2)); |
| | | |
| | | // åå¨éä¸çååæ°æ® |
| | | selectedContracts.value = selectedRows; |
| | |
| | | row.ticketsNum = Number(row.tempFutureTickets || 0); |
| | | } |
| | | // è®¡ç®æ¬æ¬¡æ¥ç¥¨éé¢ |
| | | row.ticketsAmount = (row.ticketsNum * row.taxInclusiveUnitPrice).toFixed(2) |
| | | row.ticketsAmount = Number((Number(row.ticketsNum) * Number(row.taxInclusiveUnitPrice || 0)).toFixed(2)); |
| | | // è®¡ç®æªæ¥ç¥¨æ° |
| | | row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2) |
| | | row.futureTickets = Number((Number(row.tempFutureTickets || 0) - Number(row.ticketsNum || 0)).toFixed(2)); |
| | | // è®¡ç®æªæ¥ç¥¨éé¢ |
| | | row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2) |
| | | row.futureTicketsAmount = Number((Number(row.tempFutureTicketsAmount || 0) - Number(row.ticketsAmount || 0)).toFixed(2)); |
| | | calculateinvoiceAmount(); |
| | | }; |
| | | |
| | |
| | | proxy.$modal.msgWarning("æ¬æ¬¡å¼ç¥¨æ°ä¸è½å¤§äºæªæ¥ç¥¨æ°"); |
| | | row.ticketsNum = Number(row.tempFutureTickets || 0); |
| | | // éæ°è®¡ç®æ¬æ¬¡æ¥ç¥¨éé¢ |
| | | row.ticketsAmount = (row.ticketsNum * row.taxInclusiveUnitPrice).toFixed(2); |
| | | row.ticketsAmount = Number((Number(row.ticketsNum) * Number(row.taxInclusiveUnitPrice || 0)).toFixed(2)); |
| | | } |
| | | // è®¡ç®æªæ¥ç¥¨æ° |
| | | row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2) |
| | | row.futureTickets = Number((Number(row.tempFutureTickets || 0) - Number(row.ticketsNum || 0)).toFixed(2)); |
| | | // è®¡ç®æªæ¥ç¥¨éé¢ |
| | | row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2) |
| | | row.futureTicketsAmount = Number((Number(row.tempFutureTicketsAmount || 0) - Number(row.ticketsAmount || 0)).toFixed(2)); |
| | | calculateinvoiceAmount(); |
| | | }; |
| | | |
| | |
| | | invoiceAmountTotal += Number(item.ticketsAmount); |
| | | } |
| | | }); |
| | | form.invoiceAmount = invoiceAmountTotal.toFixed(2); |
| | | form.invoiceAmount = Number(invoiceAmountTotal.toFixed(2)); |
| | | }; |
| | | |
| | | const open = async (type, selectedRows) => { |
| | |
| | | |
| | | // å¦ææ¯æ¹éæä½ï¼è®¾ç½®æ é¢ |
| | | if (Array.isArray(selectedRows) && selectedRows.length > 1) { |
| | | modalOptions.title = `æ¹éæ°å¢ (${selectedRows.length}æ¡)`; |
| | | modalOptions.value = { |
| | | ...(modalOptions.value || {}), |
| | | title: `æ¹éæ°å¢ (${selectedRows.length}æ¡)`, |
| | | }; |
| | | } else { |
| | | modalOptions.title = type === "add" ? "æ°å¢" : "ç¼è¾"; |
| | | modalOptions.value = { |
| | | ...(modalOptions.value || {}), |
| | | title: type === "add" ? "æ°å¢" : "ç¼è¾", |
| | | }; |
| | | } |
| | | |
| | | // 妿æ¯å个æä½ï¼è·åid |
| | |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | // import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import {productionDispatch} from "@/api/productionManagement/productionOrder.js"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- <div class="search_form"> |
| | | <el-form :model="searchForm" |
| | | :inline="true"> |
| | | <el-form-item label="鿣ç¼å·ï¼"> |
| | | <el-input v-model="searchForm.hiddenCode" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="handleQuery"> æç´¢ </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> --> |
| | | <div class="table_list"> |
| | | <div class="actions"> |
| | | <div></div> |
| | | <div> |
| | | <el-button type="primary" |
| | | @click="openForm('add')"> |
| | | æ°å¢éæ£ |
| | | </el-button> |
| | | <!-- <el-button type="primary" |
| | | plain |
| | | @click="handleImport">导å
¥</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> --> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤</el-button> |
| | | <!-- <el-button type="primary" |
| | | plain |
| | | @click="handlePrint">æå°</el-button> --> |
| | | </div> |
| | | </div> |
| | | <el-table :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="(row) => row.id" |
| | | :row-class-name="getRowClass" |
| | | style="width: 100%" |
| | | height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" |
| | | type="selection" |
| | | width="55" |
| | | fixed="left" /> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" /> |
| | | <el-table-column label="鿣ç¼å·" |
| | | prop="hiddenCode" |
| | | width="180" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="鿣æè¿°" |
| | | prop="hiddenDesc" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="鿣å
·ä½ä½ç½®" |
| | | prop="location" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="䏿¥äºº" |
| | | prop="createUserName" |
| | | width="180" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="䏿¥æ¶é´" |
| | | prop="createTime" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="æ´æ¹å®ææé" |
| | | prop="rectifyTime" |
| | | width="120" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="æ´æ¹è´£ä»»äºº" |
| | | prop="rectifyUserName" |
| | | width="120" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="æ´æ¹è´£ä»»äººèç³»æ¹å¼" |
| | | prop="rectifyUserMobile" |
| | | width="120" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="æ´æ¹å
·ä½æªæ½" |
| | | prop="rectifyMeasures" |
| | | width="120" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="å®é
æ´æ¹å®ææ¶é´" |
| | | prop="rectifyActualTime" |
| | | width="120" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="éªæ¶æè§" |
| | | prop="verifyRemark" |
| | | width="120" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="éªæ¶æ¶é´" |
| | | prop="verifyTime" |
| | | width="120" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="éªæ¶ç»æ" |
| | | prop="verifyResult" |
| | | width="120" |
| | | show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <el-tag v-if="scope.row.verifyResult" |
| | | :type="scope.row.verifyResult === 'éè¿' ? 'success' : 'danger'"> |
| | | {{ scope.row.verifyResult }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column fixed="right" |
| | | label="æä½" |
| | | min-width="250" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button link |
| | | type="primary" |
| | | size="small" |
| | | @click="openForm('edit', scope.row)">ç¼è¾</el-button> |
| | | <el-button link |
| | | type="primary" |
| | | size="small" |
| | | @click="downLoadFile(scope.row)">éä»¶</el-button> |
| | | <el-button link |
| | | type="primary" |
| | | size="small" |
| | | @click="openForm('edit2', scope.row)">æ´æ¹</el-button> |
| | | <el-button link |
| | | type="primary" |
| | | size="small" |
| | | :disabled="!scope.row.rectifyActualTime" |
| | | @click="openForm('edit3', scope.row)">éªæ¶</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | @pagination="paginationChange" /> |
| | | </div> |
| | | <FormDialog v-model="dialogFormVisible" |
| | | :title="getTitle(operationType)" |
| | | :width="'70%'" |
| | | :operation-type="operationType" |
| | | @close="closeDia" |
| | | @confirm="submitForm" |
| | | @cancel="closeDia"> |
| | | <el-form :model="form" |
| | | v-if="operationType === 'add' || operationType === 'edit'" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="鿣ç¼å·ï¼" |
| | | prop="hiddenCode"> |
| | | <el-input v-model="form.hiddenCode" |
| | | placeholder="èªå¨çæ" |
| | | disabled |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="鿣å
·ä½ä½ç½®ï¼" |
| | | prop="location"> |
| | | <el-input v-model="form.location" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="鿣æè¿°ï¼" |
| | | prop="hiddenDesc"> |
| | | <el-input v-model="form.hiddenDesc" |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éæ£ç±»åï¼" |
| | | prop="type"> |
| | | <el-select v-model="form.type" |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option v-for="item in typeList" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="鿣é£é©ç级ï¼" |
| | | prop="riskLevel"> |
| | | <el-select v-model="form.riskLevel" |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option v-for="item in riskLevelList" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="䏿¥äººï¼" |
| | | prop="createUser"> |
| | | <el-select v-model="form.createUser" |
| | | placeholder="è¯·éæ©" |
| | | disabled |
| | | clearable> |
| | | <el-option v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="䏿¥æ¶é´ï¼" |
| | | prop="createTime"> |
| | | <el-date-picker style="width: 100%" |
| | | disabled |
| | | v-model="form.createTime" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ´æ¹è´£ä»»äººï¼" |
| | | prop="rectifyUserId"> |
| | | <el-select v-model="form.rectifyUserId" |
| | | placeholder="è¯·éæ©" |
| | | @change="handleChange2" |
| | | clearable> |
| | | <el-option v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ´æ¹å®ææé" |
| | | prop="rectifyTime"> |
| | | <el-date-picker style="width: 100%" |
| | | v-model="form.rectifyTime" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <el-descriptions :column="2" |
| | | style="margin-bottom: 20px;" |
| | | v-if="operationType === 'edit2' || operationType === 'edit3'" |
| | | title="éæ£è¯¦æ
" |
| | | border> |
| | | <el-descriptions-item label="鿣ç¼å·"> |
| | | <span class="detail-title">{{ form.hiddenCode }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="鿣å
·ä½ä½ç½®"> |
| | | <span class="detail-title">{{ form.location }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item :span="2" |
| | | label="鿣æè¿°"> |
| | | <span class="detail-title">{{ form.hiddenDesc }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="éæ£ç±»å"> |
| | | <span class="detail-title">{{ form.type }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="鿣é£é©ç级"> |
| | | <el-tag :type="getTypeTagType(form.riskLevel)"> |
| | | {{ form.riskLevel }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="䏿¥äºº"> |
| | | <span class="detail-title">{{ form.createUserName }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="䏿¥æ¶é´"> |
| | | <span class="detail-title">{{ form.createTime }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="æ´æ¹è´£ä»»äºº"> |
| | | <span class="detail-title">{{ form.rectifyUserName }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="æ´æ¹è´£ä»»äººèç³»æ¹å¼"> |
| | | <span class="detail-title">{{ form.rectifyUserMobile }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="æ´æ¹å®ææé"> |
| | | <span class="detail-title">{{ form.rectifyTime }}</span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <el-descriptions :column="2" |
| | | style="margin-bottom: 20px;" |
| | | v-if="operationType === 'edit3'" |
| | | title="æ´æ¹è¯¦æ
" |
| | | border> |
| | | <el-descriptions-item label="æ´æ¹å
·ä½æªæ½" |
| | | :span="2"> |
| | | <span class="detail-title">{{ form2.rectifyMeasures }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="å®é
æ´æ¹å®ææ¶é´"> |
| | | <span class="detail-title">{{ form2.rectifyActualTime }}</span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <el-form :model="form2" |
| | | v-if="operationType === 'edit2'" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules2" |
| | | ref="formRef2"> |
| | | <el-form-item label="æ´æ¹å
·ä½æªæ½ï¼" |
| | | prop="rectifyMeasures"> |
| | | <el-input v-model="form2.rectifyMeasures" |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请è¾å
¥æ´æ¹å
·ä½æªæ½" |
| | | clearable /> |
| | | </el-form-item> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å®é
æ´æ¹å®ææ¶é´ï¼" |
| | | prop="rectifyActualTime"> |
| | | <el-date-picker style="width: 100%" |
| | | v-model="form2.rectifyActualTime" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <el-form :model="form3" |
| | | v-if="operationType === 'edit3'" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules3" |
| | | ref="formRef3"> |
| | | <el-form-item label="éªæ¶æè§ï¼" |
| | | prop="verifyRemark"> |
| | | <el-input v-model="form3.verifyRemark" |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请è¾å
¥éªæ¶æè§" |
| | | clearable /> |
| | | </el-form-item> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éªæ¶æ¶é´ï¼" |
| | | prop="verifyTime"> |
| | | <el-date-picker style="width: 100%" |
| | | disabled |
| | | v-model="form3.verifyTime" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éªæ¶ç»æï¼" |
| | | prop="verifyResult"> |
| | | <el-select v-model="form3.verifyResult" |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option label="éè¿" |
| | | value="éè¿" /> |
| | | <el-option label="ä¸éè¿" |
| | | value="ä¸éè¿" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éªæ¶äººï¼" |
| | | prop="verifyUserId"> |
| | | <el-select v-model="form3.verifyUserId" |
| | | disabled |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </FormDialog> |
| | | <!-- éä»¶åè¡¨å¼¹çª --> |
| | | <FileListDialog ref="fileListRef" |
| | | v-model="fileListDialogVisible" |
| | | :show-upload-button="true" |
| | | :show-delete-button="true" |
| | | :upload-method="handleUpload" |
| | | :delete-method="handleFileDelete" |
| | | title="éä»¶å表" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getToken } from "@/utils/auth"; |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import { onMounted, ref, getCurrentInstance } from "vue"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import FileListDialog from "@/components/Dialog/FileListDialog.vue"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { getQuotationList } from "@/api/salesManagement/salesQuotation.js"; |
| | | import { |
| | | dangerInvestigationListPage, |
| | | safeHiddenAdd, |
| | | safeHiddenUpdate, |
| | | safeHiddenDel, |
| | | fileListPage, |
| | | safeHiddenFileAdd, |
| | | safeHiddenFileDel, |
| | | } from "@/api/safeProduction/dangerInvestigation.js"; |
| | | import useFormData from "@/hooks/useFormData.js"; |
| | | import request from "@/utils/request"; |
| | | import dayjs from "dayjs"; |
| | | import { get } from "@vueuse/core"; |
| | | |
| | | const userStore = useUserStore(); |
| | | const { proxy } = getCurrentInstance(); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const userList = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | }); |
| | | const total = ref(0); |
| | | const getTitle = type => { |
| | | if (type === "add") { |
| | | return "æ°å¢éæ£"; |
| | | } else if (type === "edit") { |
| | | return "ä¿®æ¹éæ£"; |
| | | } else if (type === "edit2") { |
| | | return "æ´æ¹é¡µé¢"; |
| | | } else if (type === "edit3") { |
| | | return "éªæ¶é¡µé¢"; |
| | | } |
| | | }; |
| | | // è·åç±»åæ ç¾ç±»å |
| | | const getTypeTagType = type => { |
| | | const typeMap = { |
| | | è¾å¤§é£é©: "warning", |
| | | ä½é£é©: "info", |
| | | ä¸è¬é£é©: "info", |
| | | é大é£é©: "danger", |
| | | }; |
| | | return typeMap[type] || "info"; |
| | | }; |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const operationType = ref(""); |
| | | const dialogFormVisible = ref(false); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | hiddenCode: "", // 鿣ç¼å· |
| | | }, |
| | | form: { |
| | | hiddenCode: "", // 鿣ç¼å· |
| | | location: "", // 鿣ä½ç½® |
| | | hiddenDesc: "", // 鿣æè¿° |
| | | createUser: "", // 䏿¥äºº |
| | | createUserName: "", |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 䏿¥æ¶é´ |
| | | rectifyUserId: "", // æ´æ¹è´£ä»»äºº |
| | | rectifyUserName: "", |
| | | rectifyTime: "", // æ´æ¹å®ææé |
| | | rectifyUserMobile: "", // æ´æ¹è´£ä»»äººææºå· |
| | | riskLevel: "", // 鿣é£é©ç级 |
| | | type: "", // éæ£ç±»å |
| | | }, |
| | | |
| | | rules: { |
| | | location: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | hiddenDesc: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | riskLevel: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | type: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | createUser: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | rectifyUserId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | rectifyTime: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const rules2 = { |
| | | rectifyActualTime: [{ required: true, message: "è¯·éæ©", trigger: "blur" }], |
| | | rectifyMeasures: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | }; |
| | | const rules3 = { |
| | | verifyTime: [{ required: true, message: "è¯·éæ©", trigger: "blur" }], |
| | | verifyRemark: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | verifyResult: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | acceptDesc: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | }; |
| | | const typeList = ref([ |
| | | { |
| | | value: "设å¤å®å
¨", |
| | | label: "设å¤å®å
¨", |
| | | }, |
| | | { |
| | | value: "人åæä½", |
| | | label: "人åæä½", |
| | | }, |
| | | { |
| | | value: "ç¯å¢é£é©", |
| | | label: "ç¯å¢é£é©", |
| | | }, |
| | | { |
| | | value: "ç©æç®¡æ§", |
| | | label: "ç©æç®¡æ§", |
| | | }, |
| | | { |
| | | value: "å
¶ä»", |
| | | label: "å
¶ä»", |
| | | }, |
| | | ]); |
| | | const form2 = ref({ |
| | | rectifyActualTime: "", // å®é
æ´æ¹å®ææ¶é´ |
| | | rectifyMeasures: "", // æ´æ¹å
·ä½æªæ½ |
| | | }); |
| | | const form3 = ref({ |
| | | verifyTime: "", // éªæ¶æ¶é´ |
| | | verifyRemark: "", // éªæ¶å¤æ³¨ |
| | | acceptDesc: "", // éªæ¶æè¿° |
| | | verifyUserId: "", // éªæ¶äºº |
| | | verifyUserName: "", |
| | | verifyResult: "", // éªæ¶ç»æ |
| | | }); |
| | | const riskLevelList = ref([ |
| | | { |
| | | value: "é大é£é©", |
| | | label: "é大é£é©", |
| | | }, |
| | | { |
| | | value: "è¾å¤§é£é©", |
| | | label: "è¾å¤§é£é©", |
| | | }, |
| | | { |
| | | value: "ä¸è¬é£é©", |
| | | label: "ä¸è¬é£é©", |
| | | }, |
| | | { |
| | | value: "ä½é£é©", |
| | | label: "ä½é£é©", |
| | | }, |
| | | ]); |
| | | // éæ£ç±»åé项 |
| | | const { type_qualification } = proxy.useDict("type_qualification"); |
| | | const { form, rules } = toRefs(data); |
| | | const { form: searchForm } = useFormData(data.searchForm); |
| | | // 产å表åå¼¹æ¡æ°æ® |
| | | const productFormVisible = ref(false); |
| | | |
| | | const quotationLoading = ref(false); |
| | | const quotationList = ref([]); |
| | | const quotationSearchForm = reactive({ |
| | | quotationNo: "", |
| | | customer: "", |
| | | }); |
| | | |
| | | const handleChange2 = userId => { |
| | | const selectedUser = userList.value.find(user => user.userId === userId); |
| | | if (selectedUser) { |
| | | form.value.rectifyUserName = selectedUser.nickName; |
| | | form.value.rectifyUserMobile = selectedUser.phonenumber; |
| | | } |
| | | }; |
| | | |
| | | // 导å
¥ç¸å
³ |
| | | const importUploadRef = ref(null); |
| | | const importUpload = reactive({ |
| | | title: "导å
¥éå®å°è´¦", |
| | | open: false, |
| | | url: import.meta.env.VITE_APP_BASE_API + "/sales/ledger/import", |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | isUploading: false, |
| | | beforeUpload: file => { |
| | | const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls"); |
| | | const isLt10M = file.size / 1024 / 1024 < 10; |
| | | if (!isExcel) { |
| | | proxy.$modal.msgError("ä¸ä¼ æä»¶åªè½æ¯ xlsx/xls æ ¼å¼!"); |
| | | return false; |
| | | } |
| | | if (!isLt10M) { |
| | | proxy.$modal.msgError("ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿ 10MB!"); |
| | | return false; |
| | | } |
| | | return true; |
| | | }, |
| | | onChange: (file, fileList) => { |
| | | console.log("æä»¶ç¶ææ¹å", file, fileList); |
| | | }, |
| | | onProgress: (event, file, fileList) => { |
| | | console.log("ä¸ä¼ ä¸...", event.percent); |
| | | }, |
| | | onSuccess: (response, file, fileList) => { |
| | | console.log("ä¸ä¼ æå", response, file, fileList); |
| | | importUpload.isUploading = false; |
| | | if (response.code === 200) { |
| | | proxy.$modal.msgSuccess("导å
¥æå"); |
| | | importUpload.open = false; |
| | | if (importUploadRef.value) { |
| | | importUploadRef.value.clearFiles(); |
| | | } |
| | | getList(); |
| | | } else { |
| | | proxy.$modal.msgError(response.msg || "导å
¥å¤±è´¥"); |
| | | } |
| | | }, |
| | | onError: (error, file, fileList) => { |
| | | console.error("ä¸ä¼ 失败", error, file, fileList); |
| | | importUpload.isUploading = false; |
| | | proxy.$modal.msgError("导å
¥å¤±è´¥ï¼è¯·éè¯"); |
| | | }, |
| | | }); |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | // åªæå¨ç¹å»æç´¢æé®æ¶æé置页ç å°ç¬¬ä¸é¡µ |
| | | // é¿å
表ååæ®µchangeäºä»¶å¹²æ°å页 |
| | | if (arguments.length === 0) { |
| | | page.current = 1; |
| | | } |
| | | expandedRowKeys.value = []; |
| | | getList(); |
| | | }; |
| | | const paginationChange = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const { entryDate, ...rest } = searchForm; |
| | | // å°èå´æ¥æåæ®µä¼ éç»å端 |
| | | const params = { ...rest, ...page }; |
| | | // ç§»é¤å½å
¥æ¥æçé»è®¤å¼è®¾ç½®ï¼åªä¿çèå´æ¥æå段 |
| | | delete params.entryDate; |
| | | return dangerInvestigationListPage(params) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | total.value = res.data.total; |
| | | return res; |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | const findNodeById = (nodes, productId) => { |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | if (nodes[i].value === productId) { |
| | | return nodes[i].label; // æ¾å°èç¹ï¼è¿å该èç¹ |
| | | } |
| | | if (nodes[i].children && nodes[i].children.length > 0) { |
| | | const foundNode = findNodeById(nodes[i].children, productId); |
| | | if (foundNode) { |
| | | return foundNode; // å¨åèç¹ä¸æ¾å°ï¼è¿å该èç¹ |
| | | } |
| | | } |
| | | } |
| | | return null; // æ²¡ææ¾å°èç¹ï¼è¿ånull |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | console.log("selection", selectedRows.value); |
| | | }; |
| | | const expandedRowKeys = ref([]); |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = async (type, row) => { |
| | | console.log("row", row); |
| | | operationType.value = type; |
| | | form3.value = { |
| | | verifyTime: "", // éªæ¶æ¶é´ |
| | | verifyRemark: "", // éªæ¶å¤æ³¨ |
| | | verifyResult: "", // éªæ¶æè¿° |
| | | verifyUserId: "", // éªæ¶äºº |
| | | }; |
| | | form2.value = { |
| | | rectifyActualTime: "", // å®é
æ´æ¹å®ææ¶é´ |
| | | rectifyMeasures: "", // æ´æ¹å
·ä½æªæ½ |
| | | }; |
| | | if (type === "add") { |
| | | form.value = { |
| | | hiddenCode: "", // 鿣ç¼å· |
| | | location: "", // 鿣ä½ç½® |
| | | hiddenDesc: "", // 鿣æè¿° |
| | | createUser: Number(currentUserId.value), // 䏿¥äºº |
| | | createUserName: currentUserName.value, |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 䏿¥æ¶é´ |
| | | rectifyUserId: "", // æ´æ¹è´£ä»»äºº |
| | | rectifyUserName: "", |
| | | rectifyTime: "", // æ´æ¹å®ææé |
| | | rectifyUserMobile: "", // æ´æ¹è´£ä»»äººææºå· |
| | | riskLevel: "", // 鿣é£é©ç级 |
| | | type: "", // éæ£ç±»å |
| | | }; |
| | | } else if (type === "edit") { |
| | | form.value = { |
| | | id: row.id, |
| | | hiddenCode: row.hiddenCode, // 鿣ç¼å· |
| | | location: row.location, // 鿣ä½ç½® |
| | | hiddenDesc: row.hiddenDesc, // 鿣æè¿° |
| | | createUser: row.createUser, // 䏿¥äºº |
| | | createUserName: row.createUserName, |
| | | createTime: row.createTime, // 䏿¥æ¶é´ |
| | | rectifyUserId: row.rectifyUserId, // æ´æ¹è´£ä»»äºº |
| | | rectifyUserName: row.rectifyUserName, |
| | | rectifyTime: row.rectifyTime, // æ´æ¹å®ææé |
| | | rectifyUserMobile: row.rectifyUserMobile, // æ´æ¹è´£ä»»äººææºå· |
| | | riskLevel: row.riskLevel, // 鿣é£é©ç级 |
| | | type: row.type, // éæ£ç±»å |
| | | }; |
| | | } else if (type === "edit2") { |
| | | form.value = { |
| | | id: row.id, |
| | | hiddenCode: row.hiddenCode, // 鿣ç¼å· |
| | | location: row.location, // 鿣ä½ç½® |
| | | hiddenDesc: row.hiddenDesc, // 鿣æè¿° |
| | | createUser: row.createUser, // 䏿¥äºº |
| | | createUserName: row.createUserName, |
| | | createTime: row.createTime, // 䏿¥æ¶é´ |
| | | rectifyUserId: row.rectifyUserId, // æ´æ¹è´£ä»»äºº |
| | | rectifyUserName: row.rectifyUserName, |
| | | rectifyTime: row.rectifyTime, // æ´æ¹å®ææé |
| | | rectifyUserMobile: row.rectifyUserMobile, // æ´æ¹è´£ä»»äººææºå· |
| | | riskLevel: row.riskLevel, // 鿣é£é©ç级 |
| | | type: row.type, // éæ£ç±»å |
| | | }; |
| | | form2.value = { |
| | | rectifyActualTime: row.rectifyActualTime, // å®é
æ´æ¹å®ææ¶é´ |
| | | rectifyMeasures: row.rectifyMeasures, // æ´æ¹å
·ä½æªæ½ |
| | | }; |
| | | } else if (type === "edit3") { |
| | | form.value = { |
| | | id: row.id, |
| | | hiddenCode: row.hiddenCode, // 鿣ç¼å· |
| | | location: row.location, // 鿣ä½ç½® |
| | | hiddenDesc: row.hiddenDesc, // 鿣æè¿° |
| | | createUser: row.createUser, // 䏿¥äºº |
| | | createUserName: row.createUserName, |
| | | createTime: row.createTime, // 䏿¥æ¶é´ |
| | | rectifyUserId: row.rectifyUserId, // æ´æ¹è´£ä»»äºº |
| | | rectifyUserName: row.rectifyUserName, |
| | | rectifyTime: row.rectifyTime, // æ´æ¹å®ææé |
| | | rectifyUserMobile: row.rectifyUserMobile, // æ´æ¹è´£ä»»äººææºå· |
| | | riskLevel: row.riskLevel, // 鿣é£é©ç级 |
| | | type: row.type, // éæ£ç±»å |
| | | }; |
| | | form2.value = { |
| | | rectifyActualTime: row.rectifyActualTime, // å®é
æ´æ¹å®ææ¶é´ |
| | | rectifyMeasures: row.rectifyMeasures, // æ´æ¹å
·ä½æªæ½ |
| | | }; |
| | | form3.value = { |
| | | verifyTime: row.verifyTime, // éªæ¶æ¶é´ |
| | | verifyRemark: row.verifyRemark, // éªæ¶å¤æ³¨ |
| | | verifyResult: row.verifyResult, // éªæ¶æè¿° |
| | | verifyUserId: row.verifyUserId, // éªæ¶äºº |
| | | }; |
| | | console.log("form3.value", form3.value); |
| | | if (!form3.value.verifyUserId || form3.value.verifyUserId === "null") { |
| | | form3.value.verifyUserId = Number(currentUserId.value); // éªæ¶äºº |
| | | } |
| | | if (!form3.value.verifyTime || form3.value.verifyTime === "null") { |
| | | form3.value.verifyTime = dayjs().format("YYYY-MM-DD"); // éªæ¶æè¿° |
| | | } |
| | | } |
| | | dialogFormVisible.value = true; |
| | | }; |
| | | const getCurrentUserInfo = () => { |
| | | getInfo; |
| | | }; |
| | | const fetchQuotationList = async () => { |
| | | quotationLoading.value = true; |
| | | try { |
| | | const params = { |
| | | // å
¼å®¹å端å页忮µï¼è¿éæ²¿ç¨æ¥ä»·é¡µé¢å·²æå¯ç¨çåæ®µå½å |
| | | currentPage: 1, |
| | | pageSize: 100, |
| | | ...quotationSearchForm, |
| | | status: "éè¿", |
| | | }; |
| | | const res = await getQuotationList(params); |
| | | quotationList.value = res?.data?.records || []; |
| | | } finally { |
| | | quotationLoading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | console.log("operationType.value", operationType.value); |
| | | |
| | | if (operationType.value == "add") { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | safeHiddenAdd(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | } |
| | | }); |
| | | } else if (operationType.value == "edit") { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | safeHiddenUpdate(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | } |
| | | }); |
| | | } else if (operationType.value == "edit2") { |
| | | console.log("form2.value", form2.value); |
| | | proxy.$refs["formRef2"].validate(valid => { |
| | | if (valid) { |
| | | safeHiddenUpdate({ ...form2.value, ...form.value }).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | } |
| | | }); |
| | | } else if (operationType.value == "edit3") { |
| | | proxy.$refs["formRef3"].validate(valid => { |
| | | if (valid) { |
| | | safeHiddenUpdate({ |
| | | ...form3.value, |
| | | ...form2.value, |
| | | ...form.value, |
| | | }).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | proxy.resetForm("formRef2"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | // å
³é产åå¼¹æ¡ |
| | | const closeProductDia = () => { |
| | | proxy.resetForm("productFormRef"); |
| | | productFormVisible.value = false; |
| | | }; |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | safeHiddenDel(ids).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 夿æ¯å¦å¯ä»¥åè´§ |
| | | * åªæå¨äº§åç¶ææ¯å
è¶³ï¼åè´§ç¶ææ¯å¾
åè´§åå®¡æ ¸æç»çæ¶åæå¯ä»¥åè´§ |
| | | * @param row è¡æ°æ® |
| | | */ |
| | | const canShip = row => { |
| | | // 产åç¶æå¿
é¡»æ¯å
è¶³ï¼approveStatus === 1ï¼ |
| | | if (row.approveStatus !== 1) { |
| | | return false; |
| | | } |
| | | |
| | | // è·ååè´§ç¶æ |
| | | const shippingStatus = row.shippingStatus; |
| | | |
| | | // 妿已åè´§ï¼æåè´§æ¥ææè½¦çå·ï¼ï¼ä¸è½å次åè´§ |
| | | if (row.shippingDate || row.shippingCarNumber) { |
| | | return false; |
| | | } |
| | | |
| | | // åè´§ç¶æå¿
é¡»æ¯"å¾
åè´§"æ"å®¡æ ¸æç»" |
| | | const statusStr = shippingStatus ? String(shippingStatus).trim() : ""; |
| | | return statusStr === "å¾
åè´§" || statusStr === "å®¡æ ¸æç»"; |
| | | }; |
| | | |
| | | /** |
| | | * ä¸è½½æä»¶ |
| | | * |
| | | * @param row ä¸è½½æä»¶çç¸å
³ä¿¡æ¯å¯¹è±¡ |
| | | */ |
| | | const fileListRef = ref(null); |
| | | const fileListDialogVisible = ref(false); |
| | | const currentFileRow = ref(null); |
| | | const downLoadFile = row => { |
| | | currentFileRow.value = row; |
| | | fileListPage({ safeHiddenId: row.id }).then(res => { |
| | | if (fileListRef.value) { |
| | | fileListRef.value.open(res.data.records); |
| | | } |
| | | }); |
| | | }; |
| | | const currentUserId = ref(""); |
| | | const currentUserName = ref(""); |
| | | const getCurrentFactoryName = async () => { |
| | | let res = await userStore.getInfo(); |
| | | currentUserId.value = res.user.userId; |
| | | currentUserName.value = res.user.nickName; |
| | | }; |
| | | |
| | | /** |
| | | * è·åè¡ç±»åï¼ç¨äºå¤ææ¯å¦è¿ææªæ´æ¹ |
| | | * @param row è¡æ°æ® |
| | | * @returns ç±»å |
| | | */ |
| | | const getRowClass = ({ row }) => { |
| | | const now = new Date(); |
| | | |
| | | // æ£æ¥æ¯å¦è¶
è¿æ´æ¹æé䏿ªå®é
æ´æ¹ |
| | | if (row.rectifyTime && !row.rectifyActualTime) { |
| | | const rectifyTime = new Date(row.rectifyTime); |
| | | if (now > rectifyTime) { |
| | | return "overdue-row"; |
| | | } |
| | | } |
| | | |
| | | return ""; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | userListNoPage().then(res => { |
| | | userList.value = res.data; |
| | | }); |
| | | getCurrentFactoryName(); |
| | | }); |
| | | // ä¸ä¼ éä»¶ |
| | | const handleUpload = async () => { |
| | | if (!currentFileRow.value) { |
| | | proxy.$modal.msgWarning("请å
éæ©æ°æ®"); |
| | | 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 = { |
| | | safeHiddenId: currentFileRow.value.id, |
| | | name: uploadRes.data.originalName || file.name, |
| | | url: uploadRes.data.tempPath || uploadRes.data.url, |
| | | }; |
| | | |
| | | const saveRes = await safeHiddenFileAdd(fileData); |
| | | if (saveRes.code === 200) { |
| | | proxy.$modal.msgSuccess("æä»¶ä¸ä¼ æå"); |
| | | // éæ°å è½½æä»¶å表 |
| | | const listRes = await fileListPage({ |
| | | safeHiddenId: currentFileRow.value.id, |
| | | }); |
| | | 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); |
| | | } |
| | | // è¿åæ°æä»¶ä¿¡æ¯ |
| | | resolve({ |
| | | name: fileData.name, |
| | | url: fileData.url, |
| | | id: saveRes.data?.id, |
| | | }); |
| | | } else { |
| | | proxy.$modal.msgError(saveRes.msg || "æä»¶ä¿å失败"); |
| | | resolve(null); |
| | | } |
| | | } else { |
| | | proxy.$modal.msgError(uploadRes.msg || "æä»¶ä¸ä¼ 失败"); |
| | | resolve(null); |
| | | } |
| | | } catch (error) { |
| | | proxy.$modal.msgError("æä»¶ä¸ä¼ 失败"); |
| | | resolve(null); |
| | | } finally { |
| | | document.body.removeChild(input); |
| | | } |
| | | }; |
| | | |
| | | document.body.appendChild(input); |
| | | input.click(); |
| | | }); |
| | | }; |
| | | // å é¤éä»¶ |
| | | const handleFileDelete = async row => { |
| | | try { |
| | | const res = await safeHiddenFileDel([row.id]); |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | // éæ°å è½½æä»¶å表 |
| | | if (currentFileRow.value && fileListRef.value) { |
| | | const listRes = await fileListPage({ |
| | | safeHiddenId: currentFileRow.value.id, |
| | | }); |
| | | 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); |
| | | } |
| | | } |
| | | return true; // è¿å true 表示å 餿åï¼ç»ä»¶ä¼æ´æ°å表 |
| | | } else { |
| | | proxy.$modal.msgError(res.msg || "å é¤å¤±è´¥"); |
| | | return false; |
| | | } |
| | | } catch (error) { |
| | | proxy.$modal.msgError("å é¤å¤±è´¥"); |
| | | return false; |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .ml-10 { |
| | | margin-left: 10px; |
| | | } |
| | | |
| | | .table_list { |
| | | margin-top: unset; |
| | | } |
| | | |
| | | :deep(.warning-row) { |
| | | background-color: #fef0f0 !important; |
| | | } |
| | | |
| | | :deep(.warning-row td) { |
| | | // color: #cf1322 !important; |
| | | } |
| | | |
| | | :deep(.overdue-row) { |
| | | background-color: #ffffff !important; |
| | | } |
| | | |
| | | :deep(.overdue-row td) { |
| | | color: #e1707a !important; |
| | | } |
| | | |
| | | .actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | .print-preview-dialog { |
| | | .el-dialog__body { |
| | | padding: 0; |
| | | max-height: 80vh; |
| | | overflow-y: auto; |
| | | } |
| | | } |
| | | |
| | | .print-preview-container { |
| | | .print-preview-header { |
| | | padding: 15px; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | text-align: center; |
| | | |
| | | .el-button { |
| | | margin: 0 10px; |
| | | } |
| | | } |
| | | |
| | | .print-preview-content { |
| | | padding: 20px; |
| | | background-color: #f5f5f5; |
| | | min-height: 400px; |
| | | } |
| | | } |
| | | |
| | | .print-page { |
| | | width: 220mm; |
| | | height: 90mm; |
| | | padding: 10mm; |
| | | margin: 0 auto; |
| | | background: white; |
| | | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); |
| | | margin-bottom: 10px; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .delivery-note { |
| | | width: 100%; |
| | | height: 100%; |
| | | font-family: "SimSun", serif; |
| | | font-size: 10px; |
| | | line-height: 1.2; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .header { |
| | | text-align: center; |
| | | margin-bottom: 8px; |
| | | |
| | | .company-name { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .document-title { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | |
| | | .info-section { |
| | | margin-bottom: 8px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | |
| | | .info-row { |
| | | line-height: 20px; |
| | | |
| | | .label { |
| | | font-weight: bold; |
| | | width: 60px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .value { |
| | | margin-right: 20px; |
| | | min-width: 80px; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .table-section { |
| | | margin-bottom: 4px; |
| | | flex: 1; |
| | | |
| | | .product-table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | border: 1px solid #000; |
| | | |
| | | th, |
| | | td { |
| | | border: 1px solid #000; |
| | | padding: 6px; |
| | | text-align: center; |
| | | font-size: 14px; |
| | | line-height: 1.4; |
| | | } |
| | | |
| | | th { |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .total-label { |
| | | text-align: right; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .total-value { |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .footer-section { |
| | | .footer-row { |
| | | display: flex; |
| | | margin-bottom: 3px; |
| | | line-height: 20px; |
| | | justify-content: space-between; |
| | | |
| | | .footer-item { |
| | | display: flex; |
| | | margin-right: 20px; |
| | | |
| | | .label { |
| | | font-weight: bold; |
| | | width: 80px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .value { |
| | | min-width: 80px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | &.address-item { |
| | | .address-value { |
| | | min-width: 200px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | @media print { |
| | | .app-container { |
| | | display: none; |
| | | } |
| | | |
| | | .print-page { |
| | | box-shadow: none; |
| | | margin: 0; |
| | | padding: 10mm; |
| | | padding-left: 20mm; |
| | | page-break-inside: avoid; |
| | | page-break-after: always; |
| | | } |
| | | .print-page:last-child { |
| | | page-break-after: avoid; |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">å±é©æºåç§°ï¼</span> |
| | | <el-input v-model="searchForm.name" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥å±é©æºåç§°æç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | <span class="search_title ml10">å±é©æºç±»åï¼</span> |
| | | <el-select v-model="searchForm.type" |
| | | clearable |
| | | @change="handleQuery" |
| | | style="width: 240px"> |
| | | <el-option v-for="item in knowledgeTypeOptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" /> |
| | | </el-select> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px"> |
| | | æç´¢ |
| | | </el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">å»é¢ç¨</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination1" |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | <!-- æ°å¢/ç¼è¾ç¥è¯å¼¹çª --> |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="800px" |
| | | :close-on-click-modal="false"> |
| | | <el-form ref="formRef" |
| | | v-if="dialogType === 'add'" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="120px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å±é©æº" |
| | | prop="safeHazardId"> |
| | | <el-input v-model="valueItem.name" |
| | | readonly |
| | | @click="openSafeHazardSelect" |
| | | placeholder="è¯·éæ©å±é©æº" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æå¨ä½ç½®" |
| | | prop="location"> |
| | | <el-input v-model="valueItem.location" |
| | | disabled |
| | | placeholder="èªå¨å¸¦åº" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å±é©æºç±»å" |
| | | prop="type"> |
| | | <el-input v-model="valueItem.type" |
| | | disabled |
| | | placeholder="èªå¨å¸¦åº" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é£é©ç级" |
| | | prop="riskLevel"> |
| | | <el-input v-model="valueItem.riskLevel" |
| | | disabled |
| | | placeholder="èªå¨å¸¦åº" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºåæ°é" |
| | | prop="stockQty"> |
| | | <el-input v-model="valueItem.stockQty" |
| | | disabled |
| | | placeholder="èªå¨å¸¦åº" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢ç¨ç¨é" |
| | | prop="applyPurpose"> |
| | | <el-input v-model="form.applyPurpose" |
| | | placeholder="请è¾å
¥é¢ç¨ç¨é" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢ç¨æ°é" |
| | | prop="applyQty"> |
| | | <el-input v-model="form.applyQty" |
| | | type="number" |
| | | min="0" |
| | | @input="handleApplyQtyChange" |
| | | placeholder="请è¾å
¥é¢ç¨æ°é" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢ç¨äºº" |
| | | prop="applyUserId"> |
| | | <el-select v-model="form.applyUserId" |
| | | disabled |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢ç¨æ¶é´" |
| | | prop="applyTime"> |
| | | <el-date-picker style="width: 100%" |
| | | disabled |
| | | v-model="form.applyTime" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <el-descriptions :column="2" |
| | | style="margin-bottom: 20px" |
| | | v-if="dialogType === 'edit' || dialogType === 'view'" |
| | | border> |
| | | <el-descriptions-item label="å±é©æºç¼ç "> |
| | | <span>{{ form.code }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="å±é©æºåç§°"> |
| | | <span>{{ form.name }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="å±é©æºç±»å"> |
| | | <span>{{ getTypeLabel(form.type) }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="æå¨ä½ç½®"> |
| | | <span>{{ form.location }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="é£é©ç级"> |
| | | <el-tag :type="getTypeTagType(form.riskLevel)"> |
| | | {{ form.riskLevel }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="é¢ç¨ç¨é"> |
| | | <span>{{ form.applyPurpose }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="é¢ç¨æ¶é´"> |
| | | <span>{{ form.applyTime }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="é¢ç¨æ°é"> |
| | | <span>{{ form.applyQty }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="é¢ç¨äºº"> |
| | | <span>{{ form.applyUserName }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item v-if="dialogType === 'view' && form.returnUserId" |
| | | label="å½è¿äºº"> |
| | | <span>{{ form.returnUserName }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item v-if="dialogType === 'view' && form.returnTime" |
| | | label="å½è¿æ¶é´"> |
| | | <span>{{ form.returnTime }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item v-if="dialogType === 'view' && form.returnUserId" |
| | | label="å½è¿æ
åµè¯´æ"> |
| | | <span>{{ form.returnRemark }}</span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <el-form ref="formRef1" |
| | | v-if="dialogType === 'edit'" |
| | | :model="form" |
| | | :rules="rules1" |
| | | label-width="120px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½è¿äºº" |
| | | prop="returnUserId"> |
| | | <el-select v-model="form.returnUserId" |
| | | disabled |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½è¿æ¶é´" |
| | | prop="returnTime"> |
| | | <el-date-picker style="width: 100%" |
| | | disabled |
| | | v-model="form.returnTime" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="å½è¿æ
åµè¯´æ" |
| | | prop="applyPurpose"> |
| | | <el-input v-model="form.returnRemark" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请è¾å
¥å½è¿æ
åµè¯´æ" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" |
| | | @click="submitForm">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- å±é©æºéæ©å¼¹çª --> |
| | | <el-dialog v-model="safeHazardSelectVisible" |
| | | title="éæ©å±é©æº" |
| | | width="800px" |
| | | :close-on-click-modal="false"> |
| | | <div> |
| | | <el-table :data="safeHazardList" |
| | | border |
| | | v-loading="safeHazardLoading" |
| | | style="width: 100%" |
| | | @row-click="handleSafeHazardSelect"> |
| | | <el-table-column prop="code" |
| | | label="å±é©æºç¼ç " |
| | | width="180" |
| | | show-overflow-tooltip /> |
| | | <el-table-column prop="name" |
| | | label="å±é©æºåç§°" |
| | | show-overflow-tooltip /> |
| | | <el-table-column prop="type" |
| | | label="å±é©æºç±»å" |
| | | width="120" |
| | | show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | {{ getTypeLabel(scope.row.type) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="location" |
| | | label="æå¨ä½ç½®" |
| | | width="180" |
| | | show-overflow-tooltip /> |
| | | <el-table-column prop="riskLevel" |
| | | label="é£é©ç级" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getTypeTagType(scope.row.riskLevel)"> |
| | | {{ scope.row.riskLevel }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="stockQty" |
| | | label="åºåæ°é" |
| | | width="100" /> |
| | | </el-table> |
| | | <pagination :total="safeHazardPage.total" |
| | | style="margin-top: 20px" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="safeHazardPage.current" |
| | | :limit="safeHazardPage.size" |
| | | @pagination="safeHazardPagination" /> |
| | | </div> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="safeHazardSelectVisible = false">åæ¶</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { |
| | | onMounted, |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | getCurrentInstance, |
| | | computed, |
| | | } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import { safeHazardListPage } from "@/api/safeProduction/hazardSourceLedger.js"; |
| | | import { |
| | | safeHazardRecordListPage, |
| | | safeHazardRecordDel, |
| | | safeHazardRecordAdd, |
| | | safeHazardRecordUpdate, |
| | | } from "@/api/safeProduction/hazardousMaterialsControl.js"; |
| | | import dayjs from "dayjs"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | const userStore = useUserStore(); |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | applyPurpose: [ |
| | | { required: true, message: "请è¾å
¥é¢ç¨ç¨é", trigger: "blur" }, |
| | | ], |
| | | applyQty: [{ required: true, message: "请è¾å
¥é¢ç¨æ°é", trigger: "blur" }], |
| | | safeHazardId: [ |
| | | { required: true, message: "è¯·éæ©å±é©æº", trigger: "change" }, |
| | | ], |
| | | }; |
| | | const rules1 = { |
| | | returnRemark: [ |
| | | { required: true, message: "请è¾å
¥å½è¿æ
åµè¯´æ", trigger: "blur" }, |
| | | ], |
| | | }; |
| | | // ååºå¼æ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | name: "", |
| | | type: "", |
| | | }, |
| | | tableLoading: false, |
| | | page: { |
| | | current: 1, |
| | | size: 20, |
| | | total: 0, |
| | | }, |
| | | tableData: [], |
| | | selectedIds: [], |
| | | form: { |
| | | applyPurpose: "", // é¢ç¨ç¨é |
| | | applyTime: "", // é¢ç¨æ¶é´ |
| | | applyQty: "", // é¢ç¨æ°é |
| | | applyUserId: "", // é¢ç¨äººID |
| | | safeHazardId: "", // å±é©æºID |
| | | }, |
| | | dialogVisible: false, |
| | | dialogTitle: "", |
| | | dialogType: "add", |
| | | viewDialogVisible: false, |
| | | currentKnowledge: {}, |
| | | safeHazardSelectVisible: false, |
| | | safeHazardList: [], |
| | | safeHazardLoading: false, |
| | | safeHazardPage: { |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }, |
| | | }); |
| | | |
| | | const { |
| | | searchForm, |
| | | tableLoading, |
| | | page, |
| | | tableData, |
| | | selectedIds, |
| | | form, |
| | | dialogVisible, |
| | | dialogTitle, |
| | | dialogType, |
| | | viewDialogVisible, |
| | | currentKnowledge, |
| | | safeHazardSelectVisible, |
| | | safeHazardList, |
| | | safeHazardLoading, |
| | | safeHazardPage, |
| | | } = toRefs(data); |
| | | const valueItem = ref({}); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(); |
| | | const formRef1 = ref(); |
| | | const riskLevelOptions = ref([ |
| | | { value: "ä½é£é©", label: "ä½é£é©" }, |
| | | { value: "ä¸è¬é£é©", label: "ä¸è¬é£é©" }, |
| | | { value: "è¾å¤§é£é©", label: "è¾å¤§é£é©" }, |
| | | { value: "é大é£é©", label: "é大é£é©" }, |
| | | ]); |
| | | |
| | | // è¡¨æ ¼åé
ç½® |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "å±é©æºç¼ç ", |
| | | prop: "code", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "å±é©æºåç§°", |
| | | prop: "name", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "å±é©æºç±»å", |
| | | prop: "type", |
| | | showOverflowTooltip: true, |
| | | formatData: params => { |
| | | return getTypeLabel(params); |
| | | }, |
| | | }, |
| | | { |
| | | label: "é£é©ç级", |
| | | prop: "riskLevel", |
| | | showOverflowTooltip: true, |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | const typeMap = { |
| | | ä½é£é©: "info", |
| | | ä¸è¬é£é©: "info", |
| | | è¾å¤§é£é©: "warning", |
| | | é大é£é©: "danger", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "é¢ç¨ç¨é", |
| | | prop: "applyPurpose", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "é¢ç¨æ¶é´", |
| | | prop: "applyTime", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "é¢ç¨æ°é", |
| | | prop: "applyQty", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "å½è¿æ¶é´", |
| | | prop: "returnTime", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "å½è¿äºº", |
| | | prop: "returnUserName", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "å½è¿æ
åµè¯´æ", |
| | | prop: "returnRemark", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "æå¨ä½ç½®", |
| | | prop: "location", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "åå·", |
| | | prop: "materialRecordCode", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 200, |
| | | operation: [ |
| | | { |
| | | name: "å½è¿", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: row => row.returnUserId, |
| | | }, |
| | | { |
| | | name: "æ¥ç", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("view", row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const userList = ref([]); |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | getCurrentFactoryName(); |
| | | getList(); |
| | | startAutoRefresh(); |
| | | userListNoPage().then(res => { |
| | | userList.value = res.data; |
| | | }); |
| | | }); |
| | | const currentUserId = ref(""); |
| | | const currentUserName = ref(""); |
| | | const getCurrentFactoryName = async () => { |
| | | let res = await userStore.getInfo(); |
| | | currentUserId.value = res.user.userId; |
| | | currentUserName.value = res.user.nickName; |
| | | }; |
| | | |
| | | // å¤çç¨æ·éæ©åå |
| | | const handleUserChange = userId => { |
| | | const selectedUser = userList.value.find(user => user.userId === userId); |
| | | if (selectedUser) { |
| | | form.value.principalUser = selectedUser.nickName; |
| | | form.value.principalMobile = selectedUser.phonenumber; |
| | | } |
| | | }; |
| | | const handleApplyQtyChange = () => { |
| | | if (form.value.applyQty > valueItem.value.stockQty) { |
| | | ElMessage.error("é¢ç¨æ°éä¸è½å¤§äºåºåæ°é"); |
| | | form.value.applyQty = ""; |
| | | } |
| | | }; |
| | | |
| | | // å¼å§èªå¨å·æ° |
| | | const startAutoRefresh = () => { |
| | | setInterval(() => { |
| | | getList(); |
| | | }, 600000); // 10åéå·æ°ä¸æ¬¡ (10 * 60 * 1000 = 600000ms) |
| | | }; |
| | | |
| | | // æ¥è¯¢æ°æ® |
| | | const handleQuery = () => { |
| | | page.value.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | safeHazardRecordListPage({ ...page.value, ...searchForm.value }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.value.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | const openSafeHazardSelect = async () => { |
| | | await fetchSafeHazardList(); |
| | | safeHazardSelectVisible.value = true; |
| | | }; |
| | | |
| | | const fetchSafeHazardList = () => { |
| | | safeHazardLoading.value = true; |
| | | return safeHazardListPage({ |
| | | page: safeHazardPage.value.current, |
| | | size: safeHazardPage.value.size, |
| | | }) |
| | | .then(res => { |
| | | safeHazardList.value = res.data.records; |
| | | safeHazardPage.value.total = res.data.total; |
| | | }) |
| | | .finally(() => { |
| | | safeHazardLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | const handleSafeHazardSelect = item => { |
| | | valueItem.value = { |
| | | ...item, |
| | | }; |
| | | valueItem.value.type = getTypeLabel(valueItem.value.type); |
| | | form.value.safeHazardId = item.id; |
| | | safeHazardSelectVisible.value = false; |
| | | }; |
| | | |
| | | const safeHazardPagination = obj => { |
| | | safeHazardPage.value.current = obj.page; |
| | | safeHazardPage.value.size = obj.limit; |
| | | fetchSafeHazardList(); |
| | | }; |
| | | |
| | | // å页å¤ç |
| | | const pagination1 = obj => { |
| | | page.value.current = obj.page; |
| | | page.value.size = obj.limit; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // éæ©ååå¤ç |
| | | const handleSelectionChange = selection => { |
| | | selectedIds.value = selection.map(item => item.id); |
| | | }; |
| | | |
| | | // æå¼è¡¨å |
| | | const openForm = (type, row = null) => { |
| | | dialogType.value = type; |
| | | if (type === "add") { |
| | | dialogTitle.value = "é¢ç¨å±é©æº"; |
| | | // é置表å |
| | | form.value = {}; |
| | | Object.assign(form.value, { |
| | | applyPurpose: "", // é¢ç¨ç¨é |
| | | applyTime: dayjs().format("YYYY-MM-DD"), // é¢ç¨æ¶é´ |
| | | applyQty: "", // é¢ç¨æ°é |
| | | applyUserId: currentUserId.value, // é¢ç¨äººID |
| | | safeHazardId: "", // å±é©æºID |
| | | }); |
| | | valueItem.value = {}; |
| | | } else if (type === "edit" && row) { |
| | | dialogTitle.value = "å½è¿"; |
| | | Object.assign(form.value, { |
| | | id: row.id, // 主é®ID |
| | | materialRecordCode: row.materialRecordCode, // åå· |
| | | applyPurpose: row.applyPurpose, // é¢ç¨ç¨é |
| | | applyTime: row.applyTime, // é¢ç¨æ¶é´ |
| | | applyQty: row.applyQty, // é¢ç¨æ°é |
| | | applyUserId: row.applyUserId, // é¢ç¨äººID |
| | | safeHazardId: row.safeHazardId, // å±é©æºID |
| | | applyUserName: row.applyUserName, // é¢ç¨äººå§å |
| | | code: row.code, // å±é©æºç¼ç |
| | | name: row.name, // å±é©æºåç§° |
| | | type: row.type, // å±é©æºç±»å |
| | | location: row.location, // æå¨ä½ç½® |
| | | riskLevel: row.riskLevel, // é£é©ç级 |
| | | type: row.type, // å±é©æºç±»å |
| | | returnTime: dayjs().format("YYYY-MM-DD"), // å½è¿æ¶é´ |
| | | returnUserName: "", // å½è¿äººå§å |
| | | returnUserId: currentUserId.value, // å½è¿äººID |
| | | returnRemark: "", // å½è¿æ
åµè¯´æ |
| | | }); |
| | | } else if (type === "view") { |
| | | dialogTitle.value = "æ¥ç"; |
| | | form.value = { ...row }; |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // æ¥çå±é©æºè¯¦æ
|
| | | const viewKnowledge = row => { |
| | | currentKnowledge.value = { ...row }; |
| | | viewDialogVisible.value = true; |
| | | }; |
| | | |
| | | // è·åç±»åæ ç¾ç±»å |
| | | const getTypeTagType = type => { |
| | | const typeMap = { |
| | | è¾å¤§é£é©: "warning", |
| | | ä½é£é©: "info", |
| | | ä¸è¬é£é©: "info", |
| | | é大é£é©: "danger", |
| | | }; |
| | | return typeMap[type] || "info"; |
| | | }; |
| | | |
| | | // è·åç±»åæ ç¾ææ¬ |
| | | const getTypeLabel = type => { |
| | | return getKnowledgeTypeLabel(type); |
| | | }; |
| | | |
| | | // è·åæçæ ç¾ç±»å |
| | | const getEfficiencyTagType = efficiency => { |
| | | const typeMap = { |
| | | high: "success", |
| | | medium: "warning", |
| | | low: "info", |
| | | }; |
| | | return typeMap[efficiency] || "info"; |
| | | }; |
| | | |
| | | // è·åæçæ ç¾ææ¬ |
| | | const getEfficiencyLabel = efficiency => { |
| | | const efficiencyMap = { |
| | | high: "æ¾èæå", |
| | | medium: "ä¸è¬æå", |
| | | low: "轻微æå", |
| | | }; |
| | | return efficiencyMap[efficiency] || efficiency; |
| | | }; |
| | | |
| | | // è·åæçæåç¾åæ¯ |
| | | const getEfficiencyScore = efficiency => { |
| | | const scoreMap = { |
| | | high: 40, |
| | | medium: 25, |
| | | low: 15, |
| | | }; |
| | | return scoreMap[efficiency] || 0; |
| | | }; |
| | | |
| | | // è·åå¹³åèçæ¶é´ |
| | | const getTimeSaved = efficiency => { |
| | | const timeMap = { |
| | | high: "2-3天", |
| | | medium: "1-2天", |
| | | low: "0.5-1天", |
| | | }; |
| | | return timeMap[efficiency] || "æªç¥"; |
| | | }; |
| | | |
| | | // æäº¤å±é©æºè¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | if (dialogType.value === "add") { |
| | | await formRef.value.validate(); |
| | | safeHazardRecordAdd({ ...form.value }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ·»å æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else { |
| | | await formRef1.value.validate(); |
| | | safeHazardRecordUpdate({ ...form.value }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ´æ°æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | | } |
| | | }; |
| | | |
| | | // å é¤å±é©æºè®°å½ |
| | | const handleDelete = () => { |
| | | if (selectedIds.value.length === 0) { |
| | | ElMessage.warning("è¯·éæ©è¦å é¤çè®°å½"); |
| | | return; |
| | | } |
| | | |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | // console.log(selectedIds.value); |
| | | safeHazardRecordDel(selectedIds.value).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å 餿å"); |
| | | selectedIds.value = []; |
| | | getList(); |
| | | } |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | // ç¨æ·åæ¶ |
| | | }); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const { proxy } = getCurrentInstance(); |
| | | const { hazard_source_type } = proxy.useDict("hazard_source_type"); |
| | | |
| | | // åå
¸å·¥å
· |
| | | const knowledgeTypeOptions = computed(() => hazard_source_type?.value || []); |
| | | const getKnowledgeTypeLabel = val => { |
| | | const item = knowledgeTypeOptions.value.find( |
| | | i => String(i.value) === String(val) |
| | | ); |
| | | return item ? item.label : val; |
| | | }; |
| | | const getKnowledgeTypeTagType = val => { |
| | | const item = knowledgeTypeOptions.value.find( |
| | | i => String(i.value) === String(val) |
| | | ); |
| | | return item?.elTagType || "info"; |
| | | }; |
| | | const handleExport = () => { |
| | | proxy.download( |
| | | "/knowledgeBase/export", |
| | | { ...searchForm.value }, |
| | | "ç¥è¯åº.xlsx" |
| | | ); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .auto-refresh-info { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .auto-refresh-info .el-alert { |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | |
| | | .knowledge-detail { |
| | | padding: 20px 0; |
| | | } |
| | | |
| | | .detail-title { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | |
| | | .detail-section { |
| | | margin-top: 24px; |
| | | } |
| | | |
| | | .detail-section h4 { |
| | | margin: 0 0 12px 0; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | border-left: 4px solid #409eff; |
| | | padding-left: 12px; |
| | | } |
| | | |
| | | .detail-content { |
| | | background: #f8f9fa; |
| | | padding: 16px; |
| | | border-radius: 6px; |
| | | line-height: 1.6; |
| | | color: #606266; |
| | | white-space: pre-wrap; |
| | | } |
| | | |
| | | .key-points { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .usage-stats { |
| | | margin-top: 16px; |
| | | } |
| | | |
| | | .stat-item { |
| | | text-align: center; |
| | | padding: 20px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .stat-number { |
| | | font-size: 24px; |
| | | font-weight: bold; |
| | | color: #409eff; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | } |
| | | |
| | | :deep(.danger-row td) { |
| | | color: #e95a66 !important; |
| | | } |
| | | </style> |
| | |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="è§ç¨èµè´¨ç±»å" |
| | | prop="type" |
| | | show-overflow-tooltip /> |
| | | show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | {{ type_qualification.find(item => item.value === scope.row.type)?.label || '-' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="çæ¬å·" |
| | | prop="version" |
| | | width="180" |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog v-model="dialogFormVisible" |
| | | :title="operationType === 'approval' ? '审æ¹' : '详æ
'" |
| | | width="700px" |
| | | @close="closeDia"> |
| | | <el-form :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | ref="formRef"> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="æµç¨ç¼å·ï¼" |
| | | prop="approveId"> |
| | | <el-input v-model="form.approveId" |
| | | placeholder="èªå¨ç¼å·" |
| | | clearable |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="ç³è¯·é¨é¨ï¼"> |
| | | <el-select disabled |
| | | v-model="form.approveDeptId" |
| | | placeholder="éæ©é¨é¨"> |
| | | <el-option v-for="user in productOptions" |
| | | :key="user.deptId" |
| | | :label="user.deptName" |
| | | :value="user.deptId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row v-if="!isQuotationApproval && !isPurchaseApproval"> |
| | | <el-col :span="24"> |
| | | <el-form-item :label="props.approveType == 5 ? 'éè´ååå·ï¼' : '审æ¹äºç±ï¼'" |
| | | prop="approveReason"> |
| | | <el-input v-model="form.approveReason" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | type="textarea" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- 审æ¹äººéæ©ï¼å¨æèç¹ï¼ --> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç³è¯·äººï¼" |
| | | prop="approveUser"> |
| | | <el-select v-model="form.approveUser" |
| | | placeholder="éæ©äººå" |
| | | disabled> |
| | | <el-option v-for="user in userList" |
| | | :key="user.userId" |
| | | :label="user.nickName" |
| | | :value="user.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç³è¯·æ¥æï¼" |
| | | prop="approveTime"> |
| | | <el-date-picker v-model="form.approveTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <!-- æ¥ä»·å®¡æ¹ï¼å±ç¤ºæ¥ä»·è¯¦æ
ï¼å¤ç¨é宿¥ä»·"æ¥ç详æ
å¯¹è¯æ¡"å
å®¹ç»æï¼ --> |
| | | <div v-if="isQuotationApproval" |
| | | style="margin: 10px 0 18px;"> |
| | | <el-divider content-position="left">æ¥ä»·è¯¦æ
</el-divider> |
| | | <el-skeleton :loading="quotationLoading" |
| | | animated> |
| | | <template #template> |
| | | <el-skeleton-item variant="h3" |
| | | style="width: 30%" /> |
| | | <el-skeleton-item variant="text" |
| | | style="width: 100%" /> |
| | | <el-skeleton-item variant="text" |
| | | style="width: 100%" /> |
| | | </template> |
| | | <template #default> |
| | | <el-empty v-if="!currentQuotation || !currentQuotation.quotationNo" |
| | | description="æªæ¥è¯¢å°å¯¹åºæ¥ä»·è¯¦æ
" /> |
| | | <template v-else> |
| | | <el-descriptions :column="2" |
| | | border> |
| | | <el-descriptions-item label="æ¥ä»·åå·">{{ currentQuotation.quotationNo }}</el-descriptions-item> |
| | | <el-descriptions-item label="客æ·åç§°">{{ currentQuotation.customer }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¸å¡å">{{ currentQuotation.salesperson }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ¥ä»·æ¥æ">{{ currentQuotation.quotationDate }}</el-descriptions-item> |
| | | <el-descriptions-item label="æææè³">{{ currentQuotation.validDate }}</el-descriptions-item> |
| | | <el-descriptions-item label="仿¬¾æ¹å¼">{{ currentQuotation.paymentMethod }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ¥ä»·æ»é¢" |
| | | :span="2"> |
| | | <span style="font-size: 18px; color: #e6a23c; font-weight: bold;"> |
| | | ¥{{ Number(currentQuotation.totalAmount ?? 0).toFixed(2) }} |
| | | </span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <div style="margin-top: 20px;"> |
| | | <h4>产åæç»</h4> |
| | | <el-table :data="currentQuotation.products || []" |
| | | border |
| | | style="width: 100%"> |
| | | <el-table-column prop="product" |
| | | label="产ååç§°" /> |
| | | <el-table-column prop="specification" |
| | | label="è§æ ¼åå·" /> |
| | | <el-table-column prop="unit" |
| | | label="åä½" /> |
| | | <el-table-column prop="unitPrice" |
| | | label="åä»·"> |
| | | <template #default="scope">Â¥{{ Number(scope.row.unitPrice ?? 0).toFixed(2) }}</template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | <div v-if="currentQuotation.remark" |
| | | style="margin-top: 20px;"> |
| | | <h4>夿³¨</h4> |
| | | <p>{{ currentQuotation.remark }}</p> |
| | | </div> |
| | | </template> |
| | | </template> |
| | | </el-skeleton> |
| | | </div> |
| | | <!-- éè´å®¡æ¹ï¼å±ç¤ºéè´è¯¦æ
--> |
| | | <div v-if="isPurchaseApproval" |
| | | style="margin: 10px 0 18px;"> |
| | | <el-divider content-position="left">éè´è¯¦æ
</el-divider> |
| | | <el-skeleton :loading="purchaseLoading" |
| | | animated> |
| | | <template #template> |
| | | <el-skeleton-item variant="h3" |
| | | style="width: 30%" /> |
| | | <el-skeleton-item variant="text" |
| | | style="width: 100%" /> |
| | | <el-skeleton-item variant="text" |
| | | style="width: 100%" /> |
| | | </template> |
| | | <template #default> |
| | | <el-empty v-if="!currentPurchase || !currentPurchase.purchaseContractNumber" |
| | | description="æªæ¥è¯¢å°å¯¹åºéè´è¯¦æ
" /> |
| | | <template v-else> |
| | | <el-descriptions :column="2" |
| | | border> |
| | | <el-descriptions-item label="éè´ååå·">{{ currentPurchase.purchaseContractNumber }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¾åºååç§°">{{ currentPurchase.supplierName }}</el-descriptions-item> |
| | | <el-descriptions-item label="项ç®åç§°">{{ currentPurchase.projectName }}</el-descriptions-item> |
| | | <el-descriptions-item label="éå®ååå·">{{ currentPurchase.salesContractNo }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç¾è®¢æ¥æ">{{ currentPurchase.executionDate }}</el-descriptions-item> |
| | | <el-descriptions-item label="å½å
¥æ¥æ">{{ currentPurchase.entryDate }}</el-descriptions-item> |
| | | <el-descriptions-item label="仿¬¾æ¹å¼">{{ currentPurchase.paymentMethod }}</el-descriptions-item> |
| | | <el-descriptions-item label="ååéé¢" |
| | | :span="2"> |
| | | <span style="font-size: 18px; color: #e6a23c; font-weight: bold;"> |
| | | ¥{{ Number(currentPurchase.contractAmount ?? 0).toFixed(2) }} |
| | | </span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <div style="margin-top: 20px;"> |
| | | <h4>产åæç»</h4> |
| | | <el-table :data="currentPurchase.productData || []" |
| | | border |
| | | style="width: 100%"> |
| | | <el-table-column prop="productCategory" |
| | | label="产ååç§°" /> |
| | | <el-table-column prop="specificationModel" |
| | | label="è§æ ¼åå·" /> |
| | | <el-table-column prop="unit" |
| | | label="åä½" /> |
| | | <el-table-column prop="quantity" |
| | | label="æ°é" /> |
| | | <el-table-column prop="taxInclusiveUnitPrice" |
| | | label="å«ç¨åä»·"> |
| | | <template #default="scope">Â¥{{ Number(scope.row.taxInclusiveUnitPrice ?? 0).toFixed(2) }}</template> |
| | | </el-table-column> |
| | | <el-table-column prop="taxInclusiveTotalPrice" |
| | | label="å«ç¨æ»ä»·"> |
| | | <template #default="scope">Â¥{{ Number(scope.row.taxInclusiveTotalPrice ?? 0).toFixed(2) }}</template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </template> |
| | | </template> |
| | | </el-skeleton> |
| | | </div> |
| | | <el-form :model="{ activities }" |
| | | ref="formRef" |
| | | label-position="top"> |
| | | <el-steps :active="getActiveStep()" |
| | | finish-status="success" |
| | | process-status="process" |
| | | align-center |
| | | direction="vertical"> |
| | | <el-step v-for="(activity, index) in activities" |
| | | :key="index" |
| | | finish-status="success" |
| | | :title="getNodeTitle(index, activities.length)" |
| | | :description="activity.approveNodeUser" |
| | | :icon="getNodeIcon(activity, index)"> |
| | | <template #icon> |
| | | <el-icon v-if="activity.approveNodeStatus === 2" |
| | | color="red" |
| | | :size="22"> |
| | | <WarningFilled /> |
| | | </el-icon> |
| | | <el-icon v-else-if="activity.isShen" |
| | | color="#1890ff" |
| | | :size="22"> |
| | | <Edit /> |
| | | </el-icon> |
| | | <el-icon v-else-if="activity.approveNodeStatus === 1" |
| | | color="#67C23A" |
| | | :size="26"> |
| | | <Check /> |
| | | </el-icon> |
| | | <el-icon v-else |
| | | color="#C0C4CC" |
| | | :size="22"> |
| | | <MoreFilled /> |
| | | </el-icon> |
| | | </template> |
| | | <template #title> |
| | | <span style="color: #000000">{{ getNodeTitle(index, activities.length) }}</span> |
| | | </template> |
| | | <template #description> |
| | | <div class="node-user"> |
| | | <div class="avatar-wrapper"> |
| | | <img :src="userStore.avatar" |
| | | class="user-avatar" |
| | | alt="" /> |
| | | </div> |
| | | <span style="color: #000000">{{ activity.approveNodeUser }}-{{activity.isApproval}}</span> |
| | | </div> |
| | | <div v-if="!activity.isShen" |
| | | class="node-reason"> |
| | | <span>å®¡æ¹æè§ï¼</span>{{ activity.approveNodeReason }} |
| | | </div> |
| | | <div v-if="!activity.isShen" |
| | | class="node-reason"> |
| | | <span>ç¾åï¼</span> |
| | | <img :src="activity.urlTem" |
| | | class="signImg" |
| | | alt="" |
| | | v-if="activity.urlTem" /> |
| | | </div> |
| | | <div v-else-if="activity.isShen"> |
| | | <el-form-item :prop="'activities.' + index + '.approveNodeReason'" |
| | | :rules="[{ required: true, message: 'å®¡æ¹æè§ä¸è½ä¸ºç©º', trigger: 'blur' }]"> |
| | | <el-input v-model="activity.approveNodeReason" |
| | | clearable |
| | | type="textarea" |
| | | :disabled="operationType === 'view'"></el-input> |
| | | </el-form-item> |
| | | </div> |
| | | </template> |
| | | </el-step> |
| | | </el-steps> |
| | | </el-form> |
| | | <template #footer |
| | | v-if="operationType === 'approval'"> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm(2)">ä¸éè¿</el-button> |
| | | <el-button type="primary" |
| | | @click="submitForm(1)">éè¿</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { |
| | | computed, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | reactive, |
| | | ref, |
| | | toRefs, |
| | | } from "vue"; |
| | | import { |
| | | approveProcessDetails, |
| | | getDept, |
| | | updateApproveNode, |
| | | } from "@/api/collaborativeApproval/approvalProcess.js"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import { userListNoPageByTenantId } from "@/api/system/user.js"; |
| | | import { |
| | | WarningFilled, |
| | | Edit, |
| | | Check, |
| | | MoreFilled, |
| | | } from "@element-plus/icons-vue"; |
| | | import { getQuotationList } from "@/api/salesManagement/salesQuotation.js"; |
| | | import { getPurchaseByCode } from "@/api/procurementManagement/procurementLedger.js"; |
| | | const emit = defineEmits(["close"]); |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | const props = defineProps({ |
| | | approveType: { |
| | | type: [Number, String], |
| | | default: 0, |
| | | }, |
| | | }); |
| | | |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref(""); |
| | | const activities = ref([]); |
| | | const formRef = ref(null); |
| | | const userStore = useUserStore(); |
| | | const productOptions = ref([]); |
| | | const userList = ref([]); |
| | | const quotationLoading = ref(false); |
| | | const currentQuotation = ref({}); |
| | | const purchaseLoading = ref(false); |
| | | const currentPurchase = ref({}); |
| | | const isQuotationApproval = computed(() => Number(props.approveType) === 6); |
| | | const isPurchaseApproval = computed(() => Number(props.approveType) === 5); |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | approveTime: "", |
| | | approveId: "", |
| | | approveUser: "", |
| | | approveDeptId: "", |
| | | approveReason: "", |
| | | checkResult: "", |
| | | }, |
| | | }); |
| | | const { form } = toRefs(data); |
| | | |
| | | // èç¹æ é¢ |
| | | const getNodeTitle = (index, len) => { |
| | | if (index === len - 1) return "ç»æ"; |
| | | return "审æ¹"; |
| | | }; |
| | | |
| | | // è·åå½åæ¿æ´»æ¥éª¤ |
| | | const getActiveStep = () => { |
| | | // å¦æææ isShen é½ä¸º falseï¼è¿åæåä¸ä¸ªæ¥éª¤ï¼å
¨é¨å®æï¼ |
| | | const hasActive = activities.value.some(a => a.isShen === true); |
| | | if (!hasActive) return activities.value.length; |
| | | // å½åèç¹ç´¢å¼ |
| | | return activities.value.findIndex(a => a.isShen == true); |
| | | }; |
| | | // æ¥éª¤icon |
| | | const getNodeIcon = (activity, index) => { |
| | | if (activity.approveNodeStatus === 2) return "el-icon-warning"; // ä¸éè¿ |
| | | if (activity.isShen) return "Edit"; |
| | | return ""; |
| | | }; |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | currentQuotation.value = {}; |
| | | currentPurchase.value = {}; |
| | | userListNoPageByTenantId().then(res => { |
| | | userList.value = res.data; |
| | | }); |
| | | form.value = { ...row }; |
| | | // ç«å³æ¸
é¤è¡¨åéªè¯ç¶æï¼å ä¸ºåæ®µæ¯disabledçï¼ä¸éè¦éªè¯ï¼ |
| | | nextTick(() => { |
| | | if (formRef.value) { |
| | | formRef.value.clearValidate(); |
| | | } |
| | | }); |
| | | // ç¡®ä¿é项å è½½å®æååå¹é
å¼ç±»å |
| | | getProductOptions().then(() => { |
| | | // ç¡®ä¿å¼ç±»åå¹é
ï¼å¦æé项已å è½½ï¼ |
| | | if (productOptions.value.length > 0 && form.value.approveDeptId) { |
| | | const matchedOption = productOptions.value.find( |
| | | opt => |
| | | opt.deptId == form.value.approveDeptId || |
| | | String(opt.deptId) === String(form.value.approveDeptId) |
| | | ); |
| | | if (matchedOption) { |
| | | form.value.approveDeptId = matchedOption.deptId; |
| | | } |
| | | } |
| | | // 忬¡æ¸
é¤éªè¯ï¼ç¡®ä¿é项å è½½åå¼å¹é
æ£ç¡® |
| | | nextTick(() => { |
| | | if (formRef.value) { |
| | | formRef.value.clearValidate(); |
| | | } |
| | | }); |
| | | }); |
| | | |
| | | // æ¥ä»·å®¡æ¹ï¼ç¨å®¡æ¹äºç±å段æ¿è½½ç"æ¥ä»·åå·"廿¥æ¥ä»·å表 |
| | | if (isQuotationApproval.value) { |
| | | const quotationNo = row?.approveReason; |
| | | if (quotationNo) { |
| | | quotationLoading.value = true; |
| | | getQuotationList({ quotationNo }) |
| | | .then(res => { |
| | | const records = res?.data?.records || []; |
| | | currentQuotation.value = records[0] || {}; |
| | | }) |
| | | .finally(() => { |
| | | quotationLoading.value = false; |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // éè´å®¡æ¹ï¼ç¨å®¡æ¹äºç±å段æ¿è½½ç"éè´ååå·"廿¥éè´è¯¦æ
|
| | | if (isPurchaseApproval.value) { |
| | | const purchaseContractNumber = row?.approveReason; |
| | | if (purchaseContractNumber) { |
| | | purchaseLoading.value = true; |
| | | getPurchaseByCode({ purchaseContractNumber }) |
| | | .then(res => { |
| | | currentPurchase.value = res; |
| | | }) |
| | | .catch(err => { |
| | | console.error("æ¥è¯¢éè´è¯¦æ
失败:", err); |
| | | proxy.$modal.msgError("æ¥è¯¢éè´è¯¦æ
失败"); |
| | | }) |
| | | .finally(() => { |
| | | purchaseLoading.value = false; |
| | | }); |
| | | } |
| | | } |
| | | |
| | | approveProcessDetails(row.approveId).then(res => { |
| | | activities.value = res.data; |
| | | // å¢å isApprovalåæ®µ |
| | | activities.value.forEach(item => { |
| | | if (item.url && item.url.includes("word")) { |
| | | item.urlTem = item.url.replaceAll("word", "img"); |
| | | } else { |
| | | item.urlTem = item.url; |
| | | } |
| | | if (item.approveNodeStatus === 2) { |
| | | item.isApproval = "已驳å"; |
| | | } else if (item.approveNodeStatus === 1) { |
| | | item.isApproval = "å·²åæ"; |
| | | } else { |
| | | item.isApproval = "æªå®¡æ¹"; |
| | | } |
| | | }); |
| | | }); |
| | | }; |
| | | const getProductOptions = () => { |
| | | return getDept().then(res => { |
| | | productOptions.value = res.data; |
| | | }); |
| | | }; |
| | | // æäº¤å®¡æ¹ |
| | | const submitForm = status => { |
| | | const filteredActivities = activities.value.filter( |
| | | activity => activity.isShen |
| | | ); |
| | | if (!filteredActivities || filteredActivities.length === 0) { |
| | | proxy.$modal.msgError("æªæ¾å°å¾
审æ¹çèç¹"); |
| | | return; |
| | | } |
| | | const currentActivity = filteredActivities[0]; |
| | | if (!currentActivity) { |
| | | proxy.$modal.msgError("æªæ¾å°å¾
审æ¹çèç¹"); |
| | | return; |
| | | } |
| | | currentActivity.approveNodeStatus = status; |
| | | // 夿æ¯å¦ä¸ºæå䏿¥ |
| | | const isLast = |
| | | activities.value.findIndex(a => a.isShen) === activities.value.length - 1; |
| | | updateApproveNode({ ...currentActivity, isLast }).then(() => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }); |
| | | }; |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | quotationLoading.value = false; |
| | | currentQuotation.value = {}; |
| | | purchaseLoading.value = false; |
| | | currentPurchase.value = {}; |
| | | emit("close"); |
| | | }; |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .node-user { |
| | | margin: 10px 0; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | .node-status { |
| | | color: #1890ff; |
| | | margin-left: 8px; |
| | | font-size: 14px; |
| | | } |
| | | .node-reason { |
| | | font-size: 15px; |
| | | color: #333; |
| | | margin: 10px 0; |
| | | } |
| | | .user-avatar { |
| | | cursor: pointer; |
| | | width: 30px; |
| | | height: 30px; |
| | | border-radius: 50px; |
| | | } |
| | | .signImg { |
| | | cursor: pointer; |
| | | width: 200px; |
| | | height: 60px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? 'æ°å¢å®¡æ¹æµç¨' : 'ç¼è¾å®¡æ¹æµç¨'" |
| | | width="50%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef"> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="æµç¨ç¼å·ï¼" |
| | | prop="approveId"> |
| | | <el-input v-model="form.approveId" |
| | | placeholder="èªå¨ç¼å·" |
| | | clearable |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="ç³è¯·é¨é¨ï¼" |
| | | prop="approveDeptName"> |
| | | <!-- <el-input v-model="form.approveDeptName" placeholder="请è¾å
¥" clearable/>--> |
| | | <el-select v-model="form.approveDeptId" |
| | | placeholder="éæ©é¨é¨" |
| | | @change="handleDeptChange"> |
| | | <el-option v-for="user in productOptions" |
| | | :key="user.deptId" |
| | | :label="user.deptName" |
| | | :value="user.deptId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item :label="props.approveType == 5 ? 'éè´ååå·ï¼' : '审æ¹äºç±ï¼'" |
| | | prop="approveReason"> |
| | | <el-input v-model="form.approveReason" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | type="textarea" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- è¯·åæ¶é´ï¼ä»
å½ approveType 为 2 æ¶æ¾ç¤ºï¼ --> |
| | | <el-row :gutter="30" |
| | | v-if="props.approveType == 2"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="请åå¼å§æ¶é´ï¼" |
| | | prop="startDate"> |
| | | <el-date-picker v-model="form.startDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©å¼å§æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="请åç»ææ¶é´ï¼" |
| | | prop="endDate"> |
| | | <el-date-picker v-model="form.endDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©ç»ææ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- æ¥ééé¢ï¼ä»
å½ approveType 为 4 æ¶æ¾ç¤ºï¼ --> |
| | | <el-row v-if="props.approveType == 4"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="æ¥ééé¢ï¼" |
| | | prop="price"> |
| | | <el-input-number v-model="form.price" |
| | | placeholder="请è¾å
¥æ¥ééé¢" |
| | | :min="0" |
| | | :precision="2" |
| | | :step="0.01" |
| | | style="width: 100%" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- åºå·®å°ç¹ï¼ä»
å½ approveType 为 3 æ¶æ¾ç¤ºï¼ --> |
| | | <el-row v-if="props.approveType == 3"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="åºå·®å°ç¹ï¼" |
| | | prop="location"> |
| | | <el-input v-model="form.location" |
| | | placeholder="请è¾å
¥åºå·®å°ç¹" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- 审æ¹äººéæ©ï¼å¨æèç¹ï¼ --> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item> |
| | | <template #label> |
| | | <span>审æ¹äººéæ©ï¼</span> |
| | | <el-button type="primary" |
| | | @click="addApproverNode" |
| | | style="margin-left: 8px;">æ°å¢èç¹</el-button> |
| | | </template> |
| | | <div style="display: flex; align-items: flex-end; flex-wrap: wrap;"> |
| | | <div v-for="(node, index) in approverNodes" |
| | | :key="node.id" |
| | | style="margin-right: 30px; text-align: center; margin-bottom: 10px;"> |
| | | <div> |
| | | <span>审æ¹äºº</span> |
| | | â |
| | | </div> |
| | | <el-select v-model="node.userId" |
| | | placeholder="éæ©äººå" |
| | | style="width: 120px; margin-bottom: 8px;"> |
| | | <el-option v-for="user in userList" |
| | | :key="user.userId" |
| | | :label="user.nickName" |
| | | :value="user.userId" /> |
| | | </el-select> |
| | | <div> |
| | | <el-button type="danger" |
| | | size="small" |
| | | @click="removeApproverNode(index)" |
| | | v-if="approverNodes.length > 1">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç³è¯·äººï¼" |
| | | prop="approveUser"> |
| | | <el-select v-model="form.approveUser" |
| | | placeholder="éæ©äººå" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false"> |
| | | <el-option v-for="user in userList" |
| | | :key="user.userId" |
| | | :label="user.nickName" |
| | | :value="user.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç³è¯·æ¥æï¼" |
| | | prop="approveTime"> |
| | | <el-date-picker v-model="form.approveTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="éä»¶ææï¼" |
| | | prop="remark"> |
| | | <el-upload v-model:file-list="fileList" |
| | | :action="upload.url" |
| | | multiple |
| | | ref="fileUpload" |
| | | auto-upload |
| | | :headers="upload.headers" |
| | | :before-upload="handleBeforeUpload" |
| | | :on-error="handleUploadError" |
| | | :on-success="handleUploadSuccess" |
| | | :on-remove="handleRemove"> |
| | | <el-button type="primary" |
| | | v-if="operationType !== 'view'">ä¸ä¼ </el-button> |
| | | <template #tip |
| | | v-if="operationType !== 'view'"> |
| | | <div class="el-upload__tip"> |
| | | æä»¶æ ¼å¼æ¯æ |
| | | docï¼docxï¼xlsï¼xlsxï¼pptï¼pptxï¼pdfï¼txtï¼xmlï¼jpgï¼jpegï¼pngï¼gifï¼bmpï¼rarï¼zipï¼7z |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, toRefs, getCurrentInstance } from "vue"; |
| | | import { |
| | | approveProcessAdd, |
| | | approveProcessGetInfo, |
| | | approveProcessUpdate, |
| | | getDept, |
| | | } from "@/api/collaborativeApproval/approvalProcess.js"; |
| | | import { delLedgerFile } from "@/api/salesManagement/salesLedger.js"; |
| | | import { userListNoPageByTenantId } from "@/api/system/user.js"; |
| | | import { getToken } from "@/utils/auth"; |
| | | const { proxy } = getCurrentInstance(); |
| | | const emit = defineEmits(["close"]); |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | import log from "@/views/monitor/job/log.vue"; |
| | | const userStore = useUserStore(); |
| | | |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref(""); |
| | | const fileList = ref([]); |
| | | const upload = reactive({ |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/file/upload", |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | }); |
| | | const data = reactive({ |
| | | form: { |
| | | approveTime: "", |
| | | approveId: "", |
| | | approveUser: "", |
| | | approveDeptId: "", |
| | | approveDeptName: "", |
| | | approveReason: "", |
| | | checkResult: "", |
| | | tempFileIds: [], |
| | | approverList: [], // æ°å¢å段ï¼å卿æèç¹ç审æ¹äººid |
| | | startDate: "", // 请åå¼å§æ¶é´ |
| | | endDate: "", // 请åç»ææ¶é´ |
| | | price: null, // æ¥ééé¢ |
| | | location: "", // åºå·®å°ç¹ |
| | | }, |
| | | rules: { |
| | | approveTime: [{ required: false, message: "请è¾å
¥", trigger: "change" }], |
| | | approveId: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveUser: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveDeptName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveReason: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkResult: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | startDate: [ |
| | | { required: true, message: "è¯·éæ©è¯·åå¼å§æ¶é´", trigger: "change" }, |
| | | ], |
| | | endDate: [ |
| | | { required: true, message: "è¯·éæ©è¯·åç»ææ¶é´", trigger: "change" }, |
| | | ], |
| | | price: [{ required: true, message: "请è¾å
¥æ¥ééé¢", trigger: "blur" }], |
| | | location: [{ required: true, message: "请è¾å
¥åºå·®å°ç¹", trigger: "blur" }], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const productOptions = ref([]); |
| | | const currentApproveStatus = ref(0); |
| | | const props = defineProps({ |
| | | approveType: { |
| | | type: [Number, String], |
| | | default: 0, |
| | | }, |
| | | }); |
| | | |
| | | // 审æ¹äººèç¹ç¸å
³ |
| | | const approverNodes = ref([{ id: 1, userId: null }]); |
| | | let nextApproverId = 2; |
| | | const userList = ref([]); |
| | | function addApproverNode() { |
| | | approverNodes.value.push({ id: nextApproverId++, userId: null }); |
| | | } |
| | | function removeApproverNode(index) { |
| | | approverNodes.value.splice(index, 1); |
| | | } |
| | | // å¤çé¨é¨éæ©åå |
| | | const handleDeptChange = deptId => { |
| | | if (deptId) { |
| | | const selectedDept = productOptions.value.find( |
| | | dept => dept.deptId === deptId |
| | | ); |
| | | if (selectedDept) { |
| | | form.value.approveDeptName = selectedDept.deptName; |
| | | } |
| | | } else { |
| | | form.value.approveDeptName = ""; |
| | | } |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | userListNoPageByTenantId().then(res => { |
| | | userList.value = res.data; |
| | | }); |
| | | form.value = {}; |
| | | approverNodes.value = [{ id: 1, userId: null }]; |
| | | form.value.approveUser = userStore.id; |
| | | form.value.approveTime = getCurrentDate(); |
| | | |
| | | // è·åå½åç¨æ·ä¿¡æ¯å¹¶è®¾ç½®é¨é¨ID |
| | | form.value.approveDeptId = userStore.currentDeptId; |
| | | |
| | | // å è½½é¨é¨é项ï¼å¹¶å¨å è½½å®æå设置é¨é¨åç§° |
| | | getProductOptions(); |
| | | if (operationType.value === "edit") { |
| | | fileList.value = row.commonFileList; |
| | | form.value.tempFileIds = fileList.value.map(file => file.id); |
| | | currentApproveStatus.value = row.approveStatus; |
| | | approveProcessGetInfo({ id: row.approveId, approveReason: "1" }).then( |
| | | res => { |
| | | form.value = { ...res.data }; |
| | | // 忾审æ¹äºº |
| | | if (res.data && res.data.approveUserIds) { |
| | | const userIds = res.data.approveUserIds.split(","); |
| | | approverNodes.value = userIds.map((userId, idx) => ({ |
| | | id: idx + 1, |
| | | userId: parseInt(userId.trim()), |
| | | })); |
| | | nextApproverId = userIds.length + 1; |
| | | } else { |
| | | approverNodes.value = [{ id: 1, userId: null }]; |
| | | nextApproverId = 2; |
| | | } |
| | | } |
| | | ); |
| | | } |
| | | }; |
| | | const getProductOptions = () => { |
| | | return getDept().then(res => { |
| | | productOptions.value = res.data; |
| | | // 妿已æé¨é¨IDï¼èªå¨è®¾ç½®é¨é¨åç§°ï¼ç¨äºéªè¯ï¼ |
| | | if (form.value.approveDeptId && productOptions.value.length > 0) { |
| | | const matchedDept = productOptions.value.find( |
| | | dept => |
| | | dept.deptId == form.value.approveDeptId || |
| | | String(dept.deptId) === String(form.value.approveDeptId) |
| | | ); |
| | | if (matchedDept) { |
| | | form.value.approveDeptName = matchedDept.deptName; |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | function convertIdToValue(data) { |
| | | return data.map(item => { |
| | | const { id, children, ...rest } = item; |
| | | const newItem = { |
| | | ...rest, |
| | | value: id, // å° id æ¹ä¸º value |
| | | }; |
| | | if (children && children.length > 0) { |
| | | newItem.children = convertIdToValue(children); |
| | | } |
| | | |
| | | return newItem; |
| | | }); |
| | | } |
| | | // æäº¤äº§å表å |
| | | const submitForm = () => { |
| | | // æ¶éææèç¹ç审æ¹äººid |
| | | form.value.approveUserIds = approverNodes.value |
| | | .map(node => node.userId) |
| | | .join(","); |
| | | form.value.approveType = props.approveType; |
| | | // 审æ¹äººå¿
å¡«æ ¡éª |
| | | const hasEmptyApprover = approverNodes.value.some(node => !node.userId); |
| | | if (hasEmptyApprover) { |
| | | proxy.$modal.msgError("请为ææå®¡æ¹èç¹éæ©å®¡æ¹äººï¼"); |
| | | return; |
| | | } |
| | | // å½ approveType 为 2 æ¶ï¼æ ¡éªè¯·åæ¶é´ |
| | | if (props.approveType == 2) { |
| | | if (!form.value.startDate) { |
| | | proxy.$modal.msgError("è¯·éæ©è¯·åå¼å§æ¶é´ï¼"); |
| | | return; |
| | | } |
| | | if (!form.value.endDate) { |
| | | proxy.$modal.msgError("è¯·éæ©è¯·åç»ææ¶é´ï¼"); |
| | | return; |
| | | } |
| | | // æ ¡éªç»ææ¶é´ä¸è½æ©äºå¼å§æ¶é´ |
| | | if (new Date(form.value.endDate) < new Date(form.value.startDate)) { |
| | | proxy.$modal.msgError("请åç»ææ¶é´ä¸è½æ©äºå¼å§æ¶é´ï¼"); |
| | | return; |
| | | } |
| | | } |
| | | // å½ approveType 为 3 æ¶ï¼æ ¡éªåºå·®å°ç¹ |
| | | if (props.approveType == 3) { |
| | | if (!form.value.location || form.value.location.trim() === "") { |
| | | proxy.$modal.msgError("请è¾å
¥åºå·®å°ç¹ï¼"); |
| | | return; |
| | | } |
| | | } |
| | | // å½ approveType 为 4 æ¶ï¼æ ¡éªæ¥ééé¢ |
| | | if (props.approveType == 4) { |
| | | if (!form.value.price || form.value.price <= 0) { |
| | | proxy.$modal.msgError("请è¾å
¥ææçæ¥ééé¢ï¼"); |
| | | return; |
| | | } |
| | | } |
| | | proxy.$refs.formRef.validate(valid => { |
| | | if (valid) { |
| | | if (operationType.value === "add" || currentApproveStatus.value == 3) { |
| | | approveProcessAdd(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }); |
| | | } else { |
| | | approveProcessUpdate(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | fileList.value = []; |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | emit("close"); |
| | | }; |
| | | |
| | | // ä¸ä¼ åæ ¡æ£ |
| | | function handleBeforeUpload(file) { |
| | | // æ ¡æ£æä»¶å¤§å° |
| | | // if (file.size > 1024 * 1024 * 10) { |
| | | // proxy.$modal.msgError("ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿10MB!"); |
| | | // return false; |
| | | // } |
| | | proxy.$modal.loading("æ£å¨ä¸ä¼ æä»¶ï¼è¯·ç¨å..."); |
| | | return true; |
| | | } |
| | | // ä¸ä¼ 失败 |
| | | function handleUploadError(err) { |
| | | proxy.$modal.msgError("ä¸ä¼ æä»¶å¤±è´¥"); |
| | | proxy.$modal.closeLoading(); |
| | | } |
| | | // ä¸ä¼ æååè° |
| | | function handleUploadSuccess(res, file, uploadFiles) { |
| | | proxy.$modal.closeLoading(); |
| | | if (res.code === 200) { |
| | | // ç¡®ä¿ tempFileIds åå¨ä¸ä¸ºæ°ç» |
| | | if (!form.value.tempFileIds) { |
| | | form.value.tempFileIds = []; |
| | | } |
| | | form.value.tempFileIds.push(res.data.tempId); |
| | | proxy.$modal.msgSuccess("ä¸ä¼ æå"); |
| | | } else { |
| | | proxy.$modal.msgError(res.msg); |
| | | proxy.$refs.fileUpload.handleRemove(file); |
| | | } |
| | | } |
| | | // ç§»é¤æä»¶ |
| | | function handleRemove(file) { |
| | | if (operationType.value === "edit") { |
| | | let ids = []; |
| | | ids.push(file.id); |
| | | delLedgerFile(ids).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog v-model="dialogVisible" title="éä»¶" width="40%" :before-close="handleClose" draggable> |
| | | <el-table :data="tableData" border height="40vh"> |
| | | <el-table-column label="éä»¶åç§°" prop="name" min-width="400" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" width="150" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">ä¸è½½</el-button> |
| | | <el-button link type="primary" size="small" @click="lookFile(scope.row)">é¢è§</el-button> |
| | | <el-button link type="danger" size="small" @click="handleDelete(scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-dialog> |
| | | <filePreview ref="filePreviewRef" /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import filePreview from '@/components/filePreview/index.vue' |
| | | import { ElMessageBox, ElMessage } from 'element-plus' |
| | | import { delCommonFile } from '@/api/publicApi/commonFile.js' |
| | | |
| | | const dialogVisible = ref(false) |
| | | const tableData = ref([]) |
| | | const { proxy } = getCurrentInstance(); |
| | | const filePreviewRef = ref() |
| | | const handleClose = () => { |
| | | dialogVisible.value = false |
| | | } |
| | | const open = (list) => { |
| | | dialogVisible.value = true |
| | | tableData.value = list |
| | | } |
| | | const downLoadFile = (row) => { |
| | | proxy.$download.name(row.url); |
| | | |
| | | } |
| | | const lookFile = (row) => { |
| | | filePreviewRef.value.open(row.url) |
| | | } |
| | | // å é¤éä»¶ |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm(`确认å é¤éä»¶"${row.name}"åï¼`, 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | delCommonFile([row.id]).then(() => { |
| | | ElMessage.success('å 餿å') |
| | | // ä»å表ä¸ç§»é¤å·²å é¤çéä»¶ |
| | | const index = tableData.value.findIndex(item => item.id === row.id) |
| | | if (index !== -1) { |
| | | tableData.value.splice(index, 1) |
| | | } |
| | | }).catch(() => { |
| | | ElMessage.error('å é¤å¤±è´¥') |
| | | }) |
| | | }).catch(() => { |
| | | ElMessage.info('已忶å é¤') |
| | | }) |
| | | } |
| | | defineExpose({ |
| | | open |
| | | }) |
| | | </script> |
| | | |
| | | <style></style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- æ ç¾é¡µåæ¢ä¸åç审æ¹ç±»å --> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">æµç¨ç¼å·ï¼</span> |
| | | <el-input v-model="searchForm.approveId" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥æµç¨ç¼å·æç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | <span class="search_title ml10">审æ¹ç¶æï¼</span> |
| | | <el-select v-model="searchForm.approveStatus" |
| | | clearable |
| | | @change="handleQuery" |
| | | style="width: 240px"> |
| | | <el-option label="å¾
å®¡æ ¸" |
| | | :value="0" /> |
| | | <el-option label="å®¡æ ¸ä¸" |
| | | :value="1" /> |
| | | <el-option label="å®¡æ ¸å®æ" |
| | | :value="2" /> |
| | | <el-option label="å®¡æ ¸æªéè¿" |
| | | :value="3" /> |
| | | <el-option label="已鿰æäº¤" |
| | | :value="4" /> |
| | | </el-select> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px">æç´¢</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">æ°å¢</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumnCopy" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | <info-form-dia ref="infoFormDia" |
| | | @close="handleQuery" |
| | | :approveType="currentApproveType"></info-form-dia> |
| | | <approval-dia ref="approvalDia" |
| | | @close="handleQuery" |
| | | :approveType="currentApproveType"></approval-dia> |
| | | <FileList ref="fileListRef" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FileList from "./fileList.vue"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { |
| | | onMounted, |
| | | ref, |
| | | computed, |
| | | reactive, |
| | | toRefs, |
| | | nextTick, |
| | | getCurrentInstance, |
| | | } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { useRoute } from "vue-router"; |
| | | import InfoFormDia from "@/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue"; |
| | | import ApprovalDia from "@/views/collaborativeApproval/approvalProcess/components/approvalDia.vue"; |
| | | import { |
| | | approveProcessDelete, |
| | | approveProcessListPage, |
| | | } from "@/api/collaborativeApproval/approvalProcess.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | const userStore = useUserStore(); |
| | | const route = useRoute(); |
| | | |
| | | // å½å审æ¹ç±»åï¼æ ¹æ®éä¸çæ ç¾é¡µè®¡ç® |
| | | const currentApproveType = computed(() => { |
| | | return Number(8); |
| | | }); |
| | | |
| | | // æ ç¾é¡µåæ¢å¤ç |
| | | const handleTabChange = tabName => { |
| | | // 忢æ ç¾é¡µæ¶éç½®æç´¢æ¡ä»¶åå页ï¼å¹¶éæ°å è½½æ°æ® |
| | | searchForm.value.approveId = ""; |
| | | searchForm.value.approveStatus = ""; |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | approveId: "", |
| | | approveStatus: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | // å¨æè¡¨æ ¼åé
ç½®ï¼æ ¹æ®å®¡æ¹ç±»åçæå |
| | | const tableColumnCopy = computed(() => { |
| | | // åºç¡åé
ç½® |
| | | const baseColumns = [ |
| | | { |
| | | label: "审æ¹ç¶æ", |
| | | prop: "approveStatus", |
| | | dataType: "tag", |
| | | width: 100, |
| | | formatData: params => { |
| | | if (params == 0) { |
| | | return "å¾
å®¡æ ¸"; |
| | | } else if (params == 1) { |
| | | return "å®¡æ ¸ä¸"; |
| | | } else if (params == 2) { |
| | | return "å®¡æ ¸å®æ"; |
| | | } else if (params == 4) { |
| | | return "已鿰æäº¤"; |
| | | } else { |
| | | return "ä¸éè¿"; |
| | | } |
| | | }, |
| | | formatType: params => { |
| | | if (params == 0) { |
| | | return "warning"; |
| | | } else if (params == 1) { |
| | | return "primary"; |
| | | } else if (params == 2) { |
| | | return "success"; |
| | | } else if (params == 4) { |
| | | return "info"; |
| | | } else { |
| | | return "danger"; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "æµç¨ç¼å·", |
| | | prop: "approveId", |
| | | width: 170, |
| | | }, |
| | | { |
| | | label: "ç³è¯·é¨é¨", |
| | | prop: "approveDeptName", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "审æ¹äºç±", |
| | | prop: "approveReason", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "ç³è¯·äºº", |
| | | prop: "approveUserName", |
| | | width: 120, |
| | | }, |
| | | ]; |
| | | |
| | | // æ¥æåï¼æ ¹æ®ç±»å卿é
ç½®ï¼ |
| | | baseColumns.push( |
| | | { |
| | | label: "ç³è¯·æ¥æ", |
| | | prop: "approveTime", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "ç»ææ¥æ", |
| | | prop: "approveOverTime", |
| | | width: 120, |
| | | } |
| | | ); |
| | | |
| | | // å½å审æ¹äººå |
| | | baseColumns.push({ |
| | | label: "å½å审æ¹äºº", |
| | | prop: "approveUserCurrentName", |
| | | width: 120, |
| | | }); |
| | | |
| | | // æä½å |
| | | baseColumns.push({ |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 230, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: row => |
| | | row.approveStatus == 2 || |
| | | row.approveStatus == 1 || |
| | | row.approveStatus == 4, |
| | | }, |
| | | { |
| | | name: "å®¡æ ¸", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openApprovalDia("approval", row); |
| | | }, |
| | | disabled: row => |
| | | row.approveUserCurrentId == null || |
| | | row.approveStatus == 2 || |
| | | row.approveStatus == 3 || |
| | | row.approveStatus == 4 || |
| | | row.approveUserCurrentId !== userStore.id, |
| | | }, |
| | | { |
| | | name: "详æ
", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openApprovalDia("view", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: row => { |
| | | downLoadFile(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }); |
| | | |
| | | return baseColumns; |
| | | }); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const infoFormDia = ref(); |
| | | const approvalDia = ref(); |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const fileListRef = ref(null); |
| | | const downLoadFile = row => { |
| | | fileListRef.value.open(row.commonFileList); |
| | | }; |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | approveProcessListPage({ |
| | | ...page, |
| | | ...searchForm.value, |
| | | approveType: currentApproveType.value, |
| | | }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | const type = currentApproveType.value; |
| | | const urlMap = { |
| | | 0: "/approveProcess/exportZero", |
| | | 1: "/approveProcess/exportOne", |
| | | 2: "/approveProcess/exportTwo", |
| | | 3: "/approveProcess/exportThree", |
| | | 4: "/approveProcess/exportFour", |
| | | 5: "/approveProcess/exportFive", |
| | | 6: "/approveProcess/exportSix", |
| | | 7: "/approveProcess/exportSeven", |
| | | 8: "/approveProcess/exportEight", |
| | | }; |
| | | const url = urlMap[type] || urlMap[0]; |
| | | const nameMap = { |
| | | 0: "åå审æ¹ç®¡ç表", |
| | | 1: "å
¬åºç®¡ç审æ¹è¡¨", |
| | | 2: "请å管ç审æ¹è¡¨", |
| | | 3: "åºå·®ç®¡ç审æ¹è¡¨", |
| | | 4: "æ¥é管ç审æ¹è¡¨", |
| | | 5: "éè´ç³è¯·å®¡æ¹è¡¨", |
| | | 6: "æ¥ä»·å®¡æ¹è¡¨", |
| | | 7: "å货审æ¹è¡¨", |
| | | 8: "å±é©ä½ä¸å®¡æ¹è¡¨", |
| | | }; |
| | | const fileName = nameMap[type] || nameMap[0]; |
| | | proxy.download(url, {}, `${fileName}.xlsx`); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æå¼æ°å¢ãç¼è¾å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | infoFormDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | // æå¼æ°å¢æ£éªå¼¹æ¡ |
| | | const openApprovalDia = (type, row) => { |
| | | nextTick(() => { |
| | | approvalDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map(item => item.approveId); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | approveProcessDelete(ids).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | const approveId = route.query.approveId; |
| | | |
| | | if (approveId) { |
| | | // 设置æµç¨ç¼å·æ¥è¯¢æ¡ä»¶ |
| | | searchForm.value.approveId = String(approveId); |
| | | } |
| | | |
| | | // æ¥è¯¢å表 |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .approval-tabs { |
| | | margin-bottom: 10px; |
| | | } |
| | | </style> |
| | |
| | | proxy.$modal.msgError("è¯·éæ©è³å°ä¸æ¡æ°æ®"); |
| | | return; |
| | | } |
| | | const validRows = selectedRows.value.filter((item) => item.noReceiptAmount !== 0); |
| | | // ä»
å
许âå¾
忬¾éé¢ > 0âçè®°å½è¿å
¥æ°å¢å款弹çªï¼å¹¶è¿æ»¤æå¯è½æ··å
¥ç空对象 |
| | | const validRows = selectedRows.value.filter((item) => { |
| | | if (!item || !item.id) return false; |
| | | return Number(item.pendingInvoiceTotal ?? 0) > 0; |
| | | }); |
| | | if (validRows.length === 0) { |
| | | proxy.$modal.msgWarning("æéè®°å½åæ é忬¾"); |
| | | return; |
| | |
| | | const closeDia = () => { |
| | | forms.value = []; |
| | | dialogFormVisible.value = false; |
| | | // é¿å
äºæ¬¡æå¼å¼¹çªæ¶ä»æºå¸¦ä¸ä¸æ¬¡ç鿩坼è´âå¤åºä¸è¡/èæ°æ®â |
| | | selectedRows.value = []; |
| | | }; |
| | | |
| | | // å é¤åæ¬¾è®°å½ |
| | |
| | | <FormDialog v-model="dialogFormVisible" :title="operationType === 'add' ? 'æ°å¢éå®å°è´¦é¡µé¢' : 'ç¼è¾éå®å°è´¦é¡µé¢'" :width="'70%'" |
| | | :operation-type="operationType" @close="closeDia" @confirm="submitForm" @cancel="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <!-- æ¥ä»·å导å
¥å
¥å£ï¼æ¾å¨è¡¨åé¡¶é¨ï¼éæ©å忾客æ·/ä¸å¡åç --> |
| | | <el-row v-if="operationType === 'add'" style="margin-bottom: 10px;"> |
| | | <el-col :span="24" style="text-align: right;"> |
| | | <el-button type="primary" plain @click="openQuotationDialog"> |
| | | ä»é宿¥ä»·å¯¼å
¥ |
| | | </el-button> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éå®ååå·ï¼" prop="salesContractNo"> |
| | |
| | | selectedQuotation.value = row; |
| | | |
| | | // ä¸å¡å |
| | | form.value.salesman = row.salesperson || ""; |
| | | form.value.salesman = (row.salesperson || "").trim(); |
| | | |
| | | // 客æ·åç§° -> customerId |
| | | const customer = (customerOption.value || []).find((c) => c.customerName === row.customer); |
| | | const qCustomerName = String(row.customer || "").trim(); |
| | | const customer = (customerOption.value || []).find((c) => { |
| | | const name = String(c.customerName || "").trim(); |
| | | return name === qCustomerName || name.includes(qCustomerName) || qCustomerName.includes(name); |
| | | }); |
| | | if (customer?.id) { |
| | | form.value.customerId = customer.id; |
| | | } else { |