Merge remote-tracking branch 'origin/dev_New' into dev_New
# Conflicts:
# src/views/salesManagement/salesLedger/index.vue
已添加10个文件
已修改48个文件
已删除11个文件
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | // è·ååºå®èµäº§æ±æ»ä¿¡æ¯ |
| | | export const getAccountingTotal = (params) => { |
| | | return request({ |
| | | url: "/accounting/total", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // è·å设å¤ç±»åå叿°æ®ï¼é¥¼å¾åæçº¿å¾ï¼ |
| | | export const getDeviceTypeDistribution = (params) => { |
| | | return request({ |
| | | url: "/accounting/deviceTypeDistribution", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // è·åææ§è®¡ç®æ°æ®ï¼è¡¨æ ¼æ°æ®ï¼ |
| | | export const getCalculateDepreciation = (params) => { |
| | | return request({ |
| | | url: "/accounting/calculateDepreciation", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from '@/utils/request' |
| | | |
| | | // æ¥è¯¢å¨èåå·¥å°è´¦ |
| | | export function staffOnJobListPage(query) { |
| | | return request({ |
| | | url: '/staff/staffOnJob/listPage', |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| | | // æ¥è¯¢åå·¥å
¥èä¿¡æ¯ |
| | | export function staffOnJobInfo(query) { |
| | | return request({ |
| | | url: '/staff/staffOnJob/staffNo', |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| | | |
| | | // 导åºåå坿¬ |
| | | export function staffOnJobExportCopy(data) { |
| | | return request({ |
| | | url: '/staff/staffOnJob/exportCopy', |
| | | method: 'post', |
| | | data: data, |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request.js"; |
| | | |
| | | export function findStaffLeaveListPage(query) { |
| | | return request({ |
| | | url: "/staff/staffLeave/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function createStaffLeave(data) { |
| | | return request({ |
| | | url: "/staff/staffLeave", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | export function updateStaffLeave(id, data) { |
| | | return request({ |
| | | url: "/staff/staffLeave/" + id, |
| | | method: "put", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | export function batchDeleteStaffLeaves(data) { |
| | | return request({ |
| | | url: "/staff/staffLeave/del", |
| | | method: "delete", |
| | | data: data, |
| | | }); |
| | | } |
| | |
| | | method: "delete", |
| | | data: query, |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // ç»ç¾åå |
| | | export function renewContract(id, params) { |
| | | return request({ |
| | | url: "/staff/staffOnJob/renewContract/" + id, |
| | | method: "post", |
| | | data: params, |
| | | }); |
| | | } |
| | |
| | | // å页æ¥è¯¢ |
| | | export function paymentLedgerList(query) { |
| | | return request({ |
| | | url: "/purchase/paymentRegistration/supplierNameListPage", |
| | | url: "/purchase/paymentRegistration/paymentLedgerList", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function paymentRecordList(query) { |
| | | export function paymentRecordList(supplierId) { |
| | | return request({ |
| | | url: "/purchase/paymentRegistration/supplierNameListPageDetails", |
| | | url: "/purchase/paymentRegistration/getPaymentRecordList/" + supplierId, |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | |
| | | } |
| | | |
| | | // å 餿æ å表 |
| | | export function qualityInspectDetailByProductId(productId) { |
| | | export function qualityInspectDetailByProductId(params) { |
| | | return request({ |
| | | url: "/qualityTestStandard/product/" + productId, |
| | | url: "/qualityTestStandard/getQualityTestStandardByProductId", |
| | | method: "get", |
| | | params: params, |
| | | }); |
| | | } |
| | | |
| | |
| | | data: ids, |
| | | }); |
| | | } |
| | | |
| | | // æ ¹æ®æ åIDè·åæ ååæ° |
| | | export function getQualityTestStandardParamByTestStandardId(testStandardId) { |
| | | return request({ |
| | | url: "/qualityTestStandard/getQualityTestStandardParamByTestStandardId", |
| | | method: "get", |
| | | params: { testStandardId }, |
| | | }); |
| | | } |
| | |
| | | </div> |
| | | |
| | | <!-- æé® --> |
| | | <div v-else-if="item.dataType == 'action'"> |
| | | <div v-else-if="item.dataType == 'action'" @click.stop> |
| | | <template v-for="(o, key) in item.operation" :key="key"> |
| | | <el-button |
| | | v-show="o.type != 'upload'" |
| | |
| | | : o.color, |
| | | }" |
| | | link |
| | | @click="o.clickFun(scope.row)" |
| | | @click.stop="o.clickFun(scope.row)" |
| | | :key="key" |
| | | > |
| | | {{ o.name }} |
| | |
| | | getEmployeeDetail |
| | | } from '@/api/collaborativeApproval/enterpriseBook.js' |
| | | import { getUserProfile } from '@/api/system/user.js' |
| | | import {staffJoinListPage} from "@/api/personnelManagement/onboarding.js"; |
| | | import { |
| | | changeUserStatus, |
| | | listUser, |
| | |
| | | addUser, |
| | | deptTreeSelect, |
| | | } from "@/api/system/user"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | // æ ç¾é¡µç¶æ |
| | | const activeTab = ref('personal') |
| | |
| | | } |
| | | //è·ååå·¥å表 |
| | | const getEmployeeList = async () => { |
| | | staffJoinListPage(publicSearch.value).then(res => { |
| | | staffOnJobListPage(Object.assign({current: -1, size: -1},publicSearch.value)).then(res => { |
| | | console.log(res.data.records) |
| | | EmployeeList.value = res.data.records |
| | | }).catch(err => {}) |
| | |
| | | // è·ååä½é讯å½å表 |
| | | const getCompanyContactsList = async () => { |
| | | loading.value = true |
| | | staffJoinListPage(companySearch.value).then(res => { |
| | | staffOnJobListPage(Object.assign({current: -1, size: -1},companySearch.value)).then(res => { |
| | | // console.log(res.data.records) |
| | | companyContacts.value = res.data.records |
| | | }).catch(err => {}) |
| | |
| | | <el-option |
| | | v-for="person in employees" |
| | | :key="person.id" |
| | | :label="`${person.staffName} (${person.postJob})`" |
| | | :label="`${person.staffName} (${person.postName})`" |
| | | :value="person.id" |
| | | /> |
| | | </el-select> |
| | |
| | | import {ElMessage} from 'element-plus' |
| | | import {Plus, Document, Promotion, Bell} from '@element-plus/icons-vue' |
| | | import {getRoomEnum, saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js' |
| | | import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | // å½åç³è¯·ç±»å |
| | | const currentType = ref('department') // approval: å®¡æ¹æµç¨, department: é¨é¨çº§, notification: éç¥åå¸ |
| | |
| | | getRoomEnum().then(res => { |
| | | meetingRooms.value = res.data |
| | | }) |
| | | getStaffOnJob().then(res => { |
| | | employees.value = res.data.sort((a, b) => a.postJob.localeCompare(b.postJob)) |
| | | staffOnJobListPage({ |
| | | current: -1, |
| | | size: -1, |
| | | staffState: 1 |
| | | }).then(res => { |
| | | employees.value = res.data.records.sort((a, b) => a.postName.localeCompare(b.postName)) |
| | | }) |
| | | }) |
| | | </script> |
| | |
| | | import {ElMessage, ElMessageBox} from 'element-plus' |
| | | import Pagination from '@/components/Pagination/index.vue' |
| | | import {getRoomEnum, getExamineList,saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js' |
| | | import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; |
| | | import dayjs from "dayjs"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | // æ°æ®å表å è½½ç¶æ |
| | | const loading = ref(false) |
| | |
| | | it.participants = staffList.value.filter(staff => staffs.some(id=>id === staff.id)).map(staff => { |
| | | return { |
| | | id: staff.id, |
| | | name: `${staff.staffName}(${staff.postJob})` |
| | | name: `${staff.staffName}(${staff.postName})` |
| | | } |
| | | }) |
| | | |
| | |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(async () => { |
| | | const [resp1, resp2]= await Promise.all([getRoomEnum(), getStaffOnJob()]) |
| | | const [resp1, resp2]= await Promise.all([getRoomEnum(), staffOnJobListPage({current: -1, size: -1, staffState: 1})]) |
| | | roomEnum.value = resp1.data |
| | | staffList.value = resp2.data |
| | | staffList.value = resp2.data.records |
| | | |
| | | await getList() |
| | | }) |
| | |
| | | import {ElMessage, ElMessageBox} from 'element-plus' |
| | | import Pagination from '@/components/Pagination/index.vue' |
| | | import {getRoomEnum, getMeetingPublish,saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js' |
| | | import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; |
| | | import dayjs from "dayjs"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | // æ°æ®å表å è½½ç¶æ |
| | | const loading = ref(false) |
| | |
| | | it.participants = staffList.value.filter(staff => staffs.some(id=>id === staff.id)).map(staff => { |
| | | return { |
| | | id: staff.id, |
| | | name: `${staff.staffName}(${staff.postJob})` |
| | | name: `${staff.staffName}(${staff.postName})` |
| | | } |
| | | }) |
| | | |
| | |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(async () => { |
| | | const [resp1, resp2]= await Promise.all([getRoomEnum(), getStaffOnJob()]) |
| | | const [resp1, resp2]= await Promise.all([getRoomEnum(), staffOnJobListPage({current: -1, size: -1, staffState: 1})]) |
| | | roomEnum.value = resp1.data |
| | | staffList.value = resp2.data |
| | | staffList.value = resp2.data.records |
| | | |
| | | await getList() |
| | | }) |
| | |
| | | import Pagination from '@/components/Pagination/index.vue' |
| | | import Editor from '@/components/Editor/index.vue' |
| | | import { getRoomEnum, getMeetingPublish ,getMeetingMinutesByMeetingId,saveMeetingMinutes} from '@/api/collaborativeApproval/meeting.js' |
| | | import { getStaffOnJob } from "@/api/personnelManagement/onboarding.js" |
| | | import dayjs from "dayjs" |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | // æ°æ®å表å è½½ç¶æ |
| | | const loading = ref(false) |
| | |
| | | it.participants = staffList.value.filter(staff => staffs.some(id => id === staff.id)).map(staff => { |
| | | return { |
| | | id: staff.id, |
| | | name: `${staff.staffName}(${staff.postJob})` |
| | | name: `${staff.staffName}(${staff.postName})` |
| | | } |
| | | }) |
| | | |
| | |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(async () => { |
| | | const [resp1, resp2] = await Promise.all([getRoomEnum(), getStaffOnJob()]) |
| | | const [resp1, resp2] = await Promise.all([getRoomEnum(), staffOnJobListPage({current: -1, size: -1, staffState: 1})]) |
| | | roomEnum.value = resp1.data |
| | | staffList.value = resp2.data |
| | | staffList.value = resp2.data.records |
| | | |
| | | await getList() |
| | | }) |
| | |
| | | import { listSealApplication, addSealApplication, updateSealApplication,listRuleManagement,addRuleManagement,updateRuleManagement,delRuleManagement,getReadingStatusByRuleId,getReadingStatusList,addReadingStatus,updateReadingStatus } from '@/api/collaborativeApproval/sealManagement.js' |
| | | import { el } from 'element-plus/es/locales.mjs' |
| | | import { getUserProfile, userListNoPageByTenantId } from '@/api/system/user.js' |
| | | import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js"; |
| | | import useUserStore from '@/store/modules/user' |
| | | import { userLoginFacotryList } from "@/api/system/user.js" |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const currentUser = ref(null) |
| | |
| | | currentUser.value = res.data.userName |
| | | } |
| | | }) |
| | | staffJoinListPage({staffState: 1, ...page}).then(res => { |
| | | staffOnJobListPage({staffState: 1, ...page}).then(res => { |
| | | tableLoading.value = false; |
| | | // tableData.value = res.data.records |
| | | // //çéåºåcurrentUserååç人å |
| | |
| | | <template> |
| | | <el-form :model="form" label-width="100px" :rules="formRules" ref="formRef"> |
| | | <el-form :model="form" label-width="120px" :rules="formRules" ref="formRef"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤åç§°" prop="deviceName"> |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤åç" prop="deviceBrand"> |
| | | <el-input v-model="form.deviceBrand" placeholder="请è¾å
¥è®¾å¤åç" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤ç±»å" prop="type"> |
| | | <el-select |
| | | v-model="form.type" |
| | | placeholder="è¯·éæ©æè¾å
¥è®¾å¤ç±»å" |
| | | clearable |
| | | filterable |
| | | allow-create |
| | | default-first-option |
| | | style="width: 100%" |
| | | @change="handleDeviceTypeChange" |
| | | > |
| | | <el-option |
| | | v-for="item in deviceTypeOptions" |
| | | :key="item" |
| | | :label="item" |
| | | :value="item" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¯ç¨ææ§" prop="enableDepreciation"> |
| | | <el-switch v-model="form.enableDepreciation" :active-value="true" :inactive-value="false" /> |
| | | <el-form-item label="å¯ç¨ææ§" prop="isDepr"> |
| | | <el-switch v-model="form.isDepr" :active-value="1" :inactive-value="2" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.isDepr === 1"> |
| | | <el-form-item label="æ¯å¹´ææ§éé¢" prop="annualDepreciationAmount"> |
| | | <el-input-number |
| | | :step="0.01" |
| | | :min="0" |
| | | style="width: 100%" |
| | | v-model="form.annualDepreciationAmount" |
| | | placeholder="请è¾å
¥æ¯å¹´ææ§éé¢" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | }); |
| | | const formRef = ref(null); |
| | | const operationType = ref(''); |
| | | // 设å¤ç±»ååºå®é项 |
| | | const deviceTypeOptions = ref([ |
| | | 'ç产设å¤', |
| | | 'åå
¬è®¾å¤', |
| | | 'æ£æµè®¾å¤', |
| | | 'è¿è¾è®¾å¤', |
| | | 'å
¶ä»è®¾å¤' |
| | | ]); |
| | | const formRules = { |
| | | deviceName: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | deviceModel: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | type: [{ required: true, trigger: "change", message: "è¯·éæ©æè¾å
¥è®¾å¤ç±»å" }], |
| | | supplierName: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | unit: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | number: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | taxIncludingPriceUnit: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | taxRate: [{ required: true, trigger: "change", message: "请è¾å
¥" }], |
| | | planRuntimeTime: [{ required: true, trigger: "change", message: "è¯·éæ©" }], |
| | | annualDepreciationAmount: [ |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (form.isDepr === 1 && (value === undefined || value === null || value === '')) { |
| | | callback(new Error('å¯ç¨ææ§æ¶ï¼è¯·è¾å
¥æ¯å¹´ææ§éé¢')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: "blur" |
| | | } |
| | | ], |
| | | } |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | deviceName: undefined, // 设å¤åç§° |
| | | deviceModel: undefined, // è§æ ¼åå· |
| | | deviceBrand: undefined, // 设å¤åç |
| | | type: undefined, // 设å¤ç±»å |
| | | supplierName: undefined, // ä¾åºå |
| | | storageLocation: undefined, // åæ¾ä½ç½® |
| | | enableDepreciation: false, // æ¯å¦å¯ç¨ææ§ |
| | | isDepr: 2, // æ¯å¦å¯ç¨ææ§ 1-æ¯ 2-å¦ |
| | | annualDepreciationAmount: undefined, // æ¯å¹´ææ§éé¢ |
| | | unit: undefined, // åä½ |
| | | number: 1, // æ°é |
| | | taxIncludingPriceUnit: undefined, // å«ç¨åä»· |
| | |
| | | form.deviceName = data.deviceName; |
| | | form.deviceModel = data.deviceModel; |
| | | form.deviceBrand = data.deviceBrand; |
| | | form.type = data.type; |
| | | form.supplierName = data.supplierName; |
| | | form.storageLocation = data.storageLocation; |
| | | form.enableDepreciation = data.enableDepreciation; |
| | | form.isDepr = data.isDepr; |
| | | form.annualDepreciationAmount = data.annualDepreciationAmount; |
| | | form.unit = data.unit; |
| | | form.number = 1; |
| | | form.taxIncludingPriceUnit = data.taxIncludingPriceUnit; |
| | |
| | | } |
| | | }; |
| | | |
| | | const handleDeviceTypeChange = (value) => { |
| | | // 妿è¾å
¥çæ°å¼ä¸å¨åºå®é项ä¸ï¼åæ·»å å°é项å表 |
| | | if (value && !deviceTypeOptions.value.includes(value)) { |
| | | deviceTypeOptions.value.push(value); |
| | | } |
| | | }; |
| | | |
| | | const mathNum = () => { |
| | | if (!form.taxIncludingPriceUnit) { |
| | | ElMessage.error("请è¾å
¥åä»·"); |
| | |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥è®¾å¤åç§°" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ä¾åºå" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="åä½"> |
| | | <el-input |
| | | v-model="filters.unit" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥åä½" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | |
| | | deviceName: undefined, |
| | | deviceModel: undefined, |
| | | supplierName: undefined, |
| | | unit: undefined, |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | [ |
| | | { |
| | | label: "设å¤åç§°", |
| | | align: "center", |
| | | prop: "deviceName", |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | align: "center", |
| | | prop: "deviceModel", |
| | | }, |
| | | { |
| | | label: "设å¤åç", |
| | | align: "center", |
| | | prop: "deviceBrand", |
| | | }, |
| | | { |
| | | label: "设å¤ç±»å", |
| | | prop: "type", |
| | | }, |
| | | { |
| | | label: "ä¾åºå", |
| | | align: "center", |
| | | prop: "supplierName", |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | align: "center", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "åæ¾ä½ç½®", |
| | | align: "center", |
| | | prop: "storageLocation", |
| | | }, |
| | | { |
| | | label: "æ°é", |
| | | align: "center", |
| | | prop: "number", |
| | | }, |
| | | { |
| | | label: "å«ç¨åä»·", |
| | | align: "center", |
| | | prop: "taxIncludingPriceUnit", |
| | | }, |
| | | { |
| | | label: "å«ç¨æ»ä»·", |
| | | align: "center", |
| | | prop: "taxIncludingPriceTotal", |
| | | }, |
| | | { |
| | | label: "ç¨ç", |
| | | align: "center", |
| | | prop: "taxRate", |
| | | }, |
| | | { |
| | | label: "ä¸å«ç¨æ»ä»·", |
| | | align: "center", |
| | | prop: "unTaxIncludingPriceTotal", |
| | | }, |
| | | { |
| | | label: "å¯ç¨ææ§", |
| | | align: "center", |
| | | prop: "enableDepreciation", |
| | | formatData: (v) => (v ? "æ¯" : "å¦"), |
| | | }, |
| | | { |
| | | label: "å½å
¥äºº", |
| | | align: "center", |
| | | prop: "createUser", |
| | | }, |
| | | { |
| | | label: "å½å
¥æ¥æ", |
| | | align: "center", |
| | | prop: "createTime", |
| | | formatData: (v) => { |
| | | if (!v) return ''; |
| | | // 妿å
嫿¶åç§ï¼åªåæ¥æé¨å |
| | | if (v.includes(' ')) { |
| | | return v.split(' ')[0]; |
| | | } |
| | | return v; |
| | | }, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | edit(row.id) |
| | | }, |
| | | }, |
| | | { |
| | | name: "çæäºç»´ç ", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | showQRCode(row) |
| | | }, |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="modalOptions.title" direction="ltr" draggable> |
| | | <MaintainForm ref="maintainFormRef" /> |
| | | <template #footer> |
| | | <el-button type="primary" @click="sendForm" :loading="loading"> |
| | | {{ modalOptions.confirmText }} |
| | | </el-button> |
| | | <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | <FormDialog |
| | | v-model="visible" |
| | | :title="'设å¤ç»´ä¿®'" |
| | | width="500px" |
| | | @confirm="sendForm" |
| | | @cancel="handleCancel" |
| | | @close="handleClose" |
| | | > |
| | | <el-form :model="form" label-width="80px"> |
| | | <el-form-item label="维修人"> |
| | | <el-input v-model="form.maintenanceName" placeholder="请è¾å
¥ç»´ä¿®äºº" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç»´ä¿®ç»æ"> |
| | | <el-input v-model="form.maintenanceResult" placeholder="请è¾å
¥ç»´ä¿®ç»æ" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç»´ä¿®ç¶æ"> |
| | | <el-select v-model="form.status"> |
| | | <el-option label="å¾
æ¥ä¿®" :value="0"></el-option> |
| | | <el-option label="å®ç»" :value="1"></el-option> |
| | | <el-option label="失败" :value="2"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="ç»´ä¿®æ¥æ"> |
| | | <el-date-picker |
| | | v-model="form.maintenanceTime" |
| | | placeholder="è¯·éæ©ç»´ä¿®æ¥æ" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | type="datetime" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useModal } from "@/hooks/useModal"; |
| | | import MaintainForm from "../Form/MaintainForm.vue"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { addMaintain } from "@/api/equipmentManagement/repair"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage } from "element-plus"; |
| | | |
| | | defineOptions({ |
| | | name: "ç»´ä¿®æ¨¡ææ¡", |
| | | }); |
| | | |
| | | const maintainFormRef = ref(); |
| | | const emits = defineEmits(["ok"]); |
| | | |
| | | const { |
| | | id, |
| | | visible, |
| | | loading, |
| | | openModal, |
| | | modalOptions, |
| | | handleConfirm, |
| | | closeModal, |
| | | } = useModal({ title: "设å¤ç»´ä¿®" }); |
| | | // ä¿åæ¥ä¿®è®°å½çid |
| | | const repairId = ref(); |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | |
| | | const userStore = useUserStore(); |
| | | const { form, resetForm } = useFormData({ |
| | | maintenanceName: undefined, // ç»´ä¿®åç§° |
| | | maintenanceResult: undefined, // ç»´ä¿®ç»æ |
| | | maintenanceTime: undefined, // ç»´ä¿®æ¥æ |
| | | status: 0, |
| | | }); |
| | | |
| | | const setForm = (data) => { |
| | | form.maintenanceName = data.maintenanceName ?? userStore.nickName; |
| | | form.maintenanceResult = data.maintenanceResult; |
| | | form.maintenanceTime = |
| | | data.maintenanceTime |
| | | ? dayjs(data.maintenanceTime).format("YYYY-MM-DD HH:mm:ss") |
| | | : dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | form.status = 1; // é»è®¤ç¶æä¸ºå®ç» |
| | | }; |
| | | |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | const form = await maintainFormRef.value.getForm(); |
| | | const { code } = await addMaintain({ id: id.value, ...form }); |
| | | if (code == 200) { |
| | | emits("ok"); |
| | | maintainFormRef.value.resetForm(); |
| | | closeModal(); |
| | | try { |
| | | const { code } = await addMaintain({ id: repairId.value, ...form }); |
| | | if (code == 200) { |
| | | ElMessage.success("ç»´ä¿®æå"); |
| | | emits("ok"); |
| | | resetForm(); |
| | | visible.value = false; |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | loading.value = false; |
| | | }; |
| | | |
| | | const handleCancel = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const handleClose = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const open = async (id, row) => { |
| | | openModal(id); |
| | | repairId.value = id; // ä¿åæ¥ä¿®è®°å½çid |
| | | visible.value = true; |
| | | await nextTick(); |
| | | maintainFormRef.value.setForm(row); |
| | | setForm(row); |
| | | }; |
| | | |
| | | defineExpose({ |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="modalOptions.title" @close="close" draggable> |
| | | <RepairForm ref="repairFormRef" :id="id" /> |
| | | <template #footer> |
| | | <el-button type="primary" @click="sendForm" :loading="loading"> |
| | | {{ modalOptions.confirmText }} |
| | | </el-button> |
| | | <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | <FormDialog |
| | | v-model="visible" |
| | | :title="id ? 'ç¼è¾è®¾å¤æ¥ä¿®' : 'æ°å¢è®¾å¤æ¥ä¿®'" |
| | | width="800px" |
| | | @confirm="sendForm" |
| | | @cancel="handleCancel" |
| | | @close="handleClose" |
| | | > |
| | | <el-form :model="form" label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤åç§°"> |
| | | <el-select v-model="form.deviceLedgerId" @change="setDeviceModel" filterable> |
| | | <el-option |
| | | v-for="(item, index) in deviceOptions" |
| | | :key="index" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | ></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è§æ ¼åå·"> |
| | | <el-input |
| | | v-model="form.deviceModel" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¥ä¿®æ¥æ"> |
| | | <el-date-picker |
| | | v-model="form.repairTime" |
| | | placeholder="è¯·éæ©æ¥ä¿®æ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | type="date" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¥ä¿®äºº"> |
| | | <el-input v-model="form.repairName" placeholder="请è¾å
¥æ¥ä¿®äºº" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row v-if="id"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¥ä¿®ç¶æ"> |
| | | <el-select v-model="form.status"> |
| | | <el-option label="å¾
ç»´ä¿®" :value="0"></el-option> |
| | | <el-option label="å®ç»" :value="1"></el-option> |
| | | <el-option label="失败" :value="2"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="æ
éç°è±¡"> |
| | | <el-input |
| | | v-model="form.remark" |
| | | :rows="2" |
| | | type="textarea" |
| | | placeholder="请è¾å
¥æ
éç°è±¡" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useModal } from "@/hooks/useModal"; |
| | | import RepairForm from "../Form/RepairForm.vue"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { |
| | | addRepair, |
| | | editRepair, |
| | | getRepairById, |
| | | } from "@/api/equipmentManagement/repair"; |
| | | import { ElMessage } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | defineOptions({ |
| | | name: "è®¾å¤æ¥ä¿®å¼¹çª", |
| | |
| | | |
| | | const emits = defineEmits(["ok"]); |
| | | |
| | | const repairFormRef = ref(); |
| | | const { |
| | | id, |
| | | visible, |
| | | loading, |
| | | openModal, |
| | | modalOptions, |
| | | handleConfirm, |
| | | closeModal, |
| | | } = useModal({ title: "è®¾å¤æ¥ä¿®" }); |
| | | const id = ref(); |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | |
| | | const userStore = useUserStore(); |
| | | const deviceOptions = ref([]); |
| | | |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | }; |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | deviceLedgerId: undefined, // 设å¤Id |
| | | deviceName: undefined, // 设å¤åç§° |
| | | deviceModel: undefined, // è§æ ¼åå· |
| | | repairTime: dayjs().format("YYYY-MM-DD"), // æ¥ä¿®æ¥æï¼é»è®¤å½å¤© |
| | | repairName: userStore.nickName, // æ¥ä¿®äºº |
| | | remark: undefined, // æ
éç°è±¡ |
| | | status: 0, // æ¥ä¿®ç¶æ |
| | | }); |
| | | |
| | | const setDeviceModel = (deviceId) => { |
| | | const option = deviceOptions.value.find((item) => item.id === deviceId); |
| | | form.deviceModel = option.deviceModel; |
| | | }; |
| | | |
| | | const setForm = (data) => { |
| | | form.deviceLedgerId = data.deviceLedgerId; |
| | | form.deviceName = data.deviceName; |
| | | form.deviceModel = data.deviceModel; |
| | | form.repairTime = data.repairTime; |
| | | form.repairName = data.repairName; |
| | | form.remark = data.remark; |
| | | form.status = data.status; |
| | | }; |
| | | |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | const form = await repairFormRef.value.getForm(); |
| | | const { code } = id.value |
| | | ? await editRepair({ id: unref(id), ...form }) |
| | | : await addRepair(form); |
| | | if (code == 200) { |
| | | ElMessage.success(`${id ? "ç¼è¾" : "æ°å¢"}æ¥ä¿®æå`); |
| | | closeModal(); |
| | | emits("ok"); |
| | | try { |
| | | const { code } = id.value |
| | | ? await editRepair({ id: unref(id), ...form }) |
| | | : await addRepair(form); |
| | | if (code == 200) { |
| | | ElMessage.success(`${id.value ? "ç¼è¾" : "æ°å¢"}æ¥ä¿®æå`); |
| | | visible.value = false; |
| | | emits("ok"); |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | loading.value = false; |
| | | }; |
| | | |
| | | const handleCancel = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const handleClose = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const openAdd = async () => { |
| | | openModal(); |
| | | id.value = undefined; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | await repairFormRef.value.loadDeviceName(); |
| | | await loadDeviceName(); |
| | | }; |
| | | |
| | | const openEdit = async (id) => { |
| | | const { data } = await getRepairById(id); |
| | | openModal(id); |
| | | const openEdit = async (editId) => { |
| | | const { data } = await getRepairById(editId); |
| | | id.value = editId; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | await repairFormRef.value.loadDeviceName(); |
| | | await repairFormRef.value.setForm(data); |
| | | }; |
| | | |
| | | const close = () => { |
| | | repairFormRef.value.resetForm(); |
| | | closeModal(); |
| | | await loadDeviceName(); |
| | | setForm(data); |
| | | }; |
| | | |
| | | defineExpose({ |
| | |
| | | openEdit, |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| | |
| | | <div class="actions"> |
| | | <el-text class="mx-1" size="large">è®¾å¤æ¥ä¿®</el-text> |
| | | <div> |
| | | <el-button |
| | | type="primary" |
| | | icon="Plus" |
| | | :disabled="multipleList.length !== 1" |
| | | @click="addMaintain" |
| | | > |
| | | æ°å¢ç»´ä¿® |
| | | </el-button> |
| | | <el-button type="success" icon="Van" @click="addRepair"> |
| | | æ°å¢æ¥ä¿® |
| | | </el-button> |
| | |
| | | <el-button |
| | | type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0" |
| | | :disabled="multipleList.length <= 0 || hasFinishedStatus" |
| | | @click="delRepairByIds(multipleList.map((item) => item.id))" |
| | | > |
| | | æ¹éå é¤ |
| | |
| | | <template #operation="{ row }"> |
| | | <el-button |
| | | type="primary" |
| | | text |
| | | icon="editPen" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="editRepair(row.id)" |
| | | > |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | type="success" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="addMaintain(row)" |
| | | > |
| | | ç»´ä¿® |
| | | </el-button> |
| | | <el-button |
| | | type="danger" |
| | | text |
| | | icon="delete" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="delRepairByIds(row.id)" |
| | | > |
| | | å é¤ |
| | |
| | | <script setup> |
| | | import { usePaginationApi } from "@/hooks/usePaginationApi"; |
| | | import { getRepairPage, delRepair } from "@/api/equipmentManagement/repair"; |
| | | import { onMounted, getCurrentInstance } from "vue"; |
| | | import { onMounted, getCurrentInstance, computed } from "vue"; |
| | | import RepairModal from "./Modal/RepairModal.vue"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | |
| | | multipleList.value = selectionList; |
| | | }; |
| | | |
| | | // æ£æ¥éä¸çè®°å½ä¸æ¯å¦æå®ç»ç¶æç |
| | | const hasFinishedStatus = computed(() => { |
| | | return multipleList.value.some(item => item.status === 1) |
| | | }) |
| | | |
| | | // æ°å¢æ¥ä¿® |
| | | const addRepair = () => { |
| | | repairModalRef.value.openAdd(); |
| | |
| | | }; |
| | | |
| | | // æ°å¢ç»´ä¿® |
| | | const addMaintain = () => { |
| | | const row = multipleList.value[0]; |
| | | const addMaintain = (row) => { |
| | | maintainModalRef.value.open(row.id, row); |
| | | }; |
| | | |
| | |
| | | |
| | | // åè¡å é¤ |
| | | const delRepairByIds = async (ids) => { |
| | | // æ£æ¥æ¯å¦æå®ç»ç¶æçè®°å½ |
| | | const idsArray = Array.isArray(ids) ? ids : [ids]; |
| | | const hasFinished = idsArray.some(id => { |
| | | const record = dataList.value.find(item => item.id === id); |
| | | return record && record.status === 1; |
| | | }); |
| | | |
| | | if (hasFinished) { |
| | | ElMessage.warning('ä¸è½å é¤ç¶æä¸ºå®ç»çè®°å½'); |
| | | return; |
| | | } |
| | | |
| | | ElMessageBox.confirm("确认å 餿¥ä¿®æ°æ®, æ¤æä½ä¸å¯é?", "è¦å", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <FormDialog |
| | | v-model="visible" |
| | | :title="'设å¤ä¿å
»'" |
| | | width="500px" |
| | | @confirm="sendForm" |
| | | @cancel="handleCancel" |
| | | @close="handleClose" |
| | | > |
| | | <el-form :model="form" label-width="100px"> |
| | | <el-form-item label="å®é
ä¿å
»äºº"> |
| | | <el-input |
| | | v-model="form.maintenanceActuallyName" |
| | | placeholder="请è¾å
¥å®é
ä¿å
»äºº" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="å®é
ä¿å
»æ¥æ"> |
| | | <el-date-picker |
| | | v-model="form.maintenanceActuallyTime" |
| | | placeholder="è¯·éæ©å®é
ä¿å
»æ¥æ" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | type="datetime" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¿å
»ç¶æ"> |
| | | <el-select v-model="form.status"> |
| | | <el-option label="å¾
ä¿å
»" :value="0"></el-option> |
| | | <el-option label="å®ç»" :value="1"></el-option> |
| | | <el-option label="失败" :value="2"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="ä¿å
ȍȾ"> |
| | | <el-input |
| | | v-model="form.maintenanceResult" |
| | | placeholder="请è¾å
¥ä¿å
ȍȾ" |
| | | type="text" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { addMaintenance } from "@/api/equipmentManagement/upkeep"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import dayjs from "dayjs"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { ElMessage } from "element-plus"; |
| | | |
| | | defineOptions({ |
| | | name: "ä¿å
»æ¨¡ææ¡", |
| | | }); |
| | | |
| | | const emits = defineEmits(["ok"]); |
| | | |
| | | // ä¿å计åä¿å
»è®°å½çid |
| | | const planId = ref(); |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | const userStore = useUserStore(); |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | maintenanceActuallyName: undefined, // å®é
ä¿å
»äºº |
| | | maintenanceActuallyTime: undefined, // å®é
ä¿å
»æ¥æ |
| | | maintenanceResult: undefined, // ä¿å
ȍȾ |
| | | status: 0, // ä¿å
»ç¶æ |
| | | }); |
| | | |
| | | const setForm = (data) => { |
| | | form.maintenanceActuallyName = |
| | | data.maintenanceActuallyName ?? userStore.nickName; |
| | | form.maintenanceActuallyTime = |
| | | data.maintenanceActuallyTime |
| | | ? dayjs(data.maintenanceActuallyTime).format("YYYY-MM-DD HH:mm:ss") |
| | | : dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | form.maintenanceResult = data.maintenanceResult; |
| | | form.status = 1; // é»è®¤ç¶æä¸ºå®ç» |
| | | }; |
| | | |
| | | /** |
| | | * @desc ä¿åä¿å
» |
| | | */ |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | try { |
| | | const { code } = await addMaintenance({ id: planId.value, ...form }); |
| | | if (code == 200) { |
| | | ElMessage.success("ä¿å
»æå"); |
| | | emits("ok"); |
| | | resetForm(); |
| | | visible.value = false; |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | const handleCancel = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const handleClose = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const open = async (id, row) => { |
| | | planId.value = id; // ä¿å计åä¿å
»è®°å½çid |
| | | visible.value = true; |
| | | await nextTick(); |
| | | setForm(row); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | open, |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <FormDialog |
| | | v-model="visible" |
| | | :title="id ? 'ç¼è¾è®¾å¤ä¿å
»è®¡å' : 'æ°å¢è®¾å¤ä¿å
»è®¡å'" |
| | | width="500px" |
| | | @confirm="sendForm" |
| | | @cancel="handleCancel" |
| | | @close="handleClose" |
| | | > |
| | | <el-form :model="form" label-width="100px"> |
| | | <el-form-item label="设å¤åç§°"> |
| | | <el-select |
| | | v-model="form.deviceLedgerId" |
| | | @change="setDeviceModel" |
| | | placeholder="è¯·éæ©è®¾å¤" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | > |
| | | <el-option |
| | | v-for="(item, index) in deviceOptions" |
| | | :key="index" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | ></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="è§æ ¼åå·"> |
| | | <el-input |
| | | v-model="form.deviceModel" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="å½å
¥äºº"> |
| | | <el-select |
| | | v-model="form.createUser" |
| | | placeholder="è¯·éæ©" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item v-if="id" label="ä¿ä¿®ç¶æ"> |
| | | <el-select v-model="form.status"> |
| | | <el-option label="å¾
ä¿ä¿®" :value="0"></el-option> |
| | | <el-option label="å®ç»" :value="1"></el-option> |
| | | <el-option label="失败" :value="2"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="计åä¿å
»æ¥æ"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.maintenancePlanTime" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | type="date" |
| | | placeholder="è¯·éæ©è®¡åä¿å
»æ¥ææ¥æ" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { |
| | | addUpkeep, |
| | | editUpkeep, |
| | | getUpkeepById, |
| | | } from "@/api/equipmentManagement/upkeep"; |
| | | import { ElMessage } from "element-plus"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import { onMounted } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | |
| | | defineOptions({ |
| | | name: "设å¤ä¿å
»æ°å¢è®¡å", |
| | | }); |
| | | |
| | | const emits = defineEmits(["ok"]); |
| | | |
| | | const id = ref(); |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | |
| | | const deviceOptions = ref([]); |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | }; |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | deviceLedgerId: undefined, // 设å¤Id |
| | | deviceName: undefined, // 设å¤åç§° |
| | | deviceModel: undefined, // è§æ ¼åå· |
| | | maintenancePlanTime: undefined, // 计åä¿å
»æ¥æ |
| | | createUser: undefined, // å½å
¥äºº |
| | | status: 0, //ä¿ä¿®ç¶æ |
| | | }); |
| | | |
| | | const setDeviceModel = (deviceId) => { |
| | | const option = deviceOptions.value.find((item) => item.id === deviceId); |
| | | form.deviceModel = option.deviceModel; |
| | | }; |
| | | |
| | | /** |
| | | * @desc 设置表åå
容 |
| | | * @param data 设å¤ä¿¡æ¯ |
| | | */ |
| | | const setForm = (data) => { |
| | | form.deviceLedgerId = data.deviceLedgerId; |
| | | form.deviceName = data.deviceName; |
| | | form.deviceModel = data.deviceModel; |
| | | form.createUser = Number(data.createUser); |
| | | form.status = data.status; |
| | | form.maintenancePlanTime = dayjs(data.maintenancePlanTime).format( |
| | | "YYYY-MM-DD HH:mm:ss" |
| | | ); |
| | | }; |
| | | |
| | | // ç¨æ·å表 |
| | | const userList = ref([]); |
| | | |
| | | onMounted(() => { |
| | | loadDeviceName(); |
| | | userListNoPage().then((res) => { |
| | | userList.value = res.data; |
| | | }); |
| | | }); |
| | | |
| | | const openEdit = async (editId) => { |
| | | const { data } = await getUpkeepById(editId); |
| | | id.value = editId; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | setForm(data); |
| | | }; |
| | | |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | try { |
| | | const { code } = id.value |
| | | ? await editUpkeep({ id: unref(id), ...form }) |
| | | : await addUpkeep(form); |
| | | if (code == 200) { |
| | | ElMessage.success(`${id.value ? "ç¼è¾" : "æ°å¢"}计åæå`); |
| | | visible.value = false; |
| | | emits("ok"); |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | const handleCancel = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const handleClose = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const openModal = () => { |
| | | id.value = undefined; |
| | | visible.value = true; |
| | | }; |
| | | |
| | | defineExpose({ |
| | | openModal, |
| | | openEdit, |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <FormDialog |
| | | v-model="dialogVisitable" |
| | | :title="operationType === 'add' ? 'æ°å¢ä¿å
»ä»»å¡' : 'ç¼è¾ä¿å
»ä»»å¡'" |
| | | width="800px" |
| | | :operation-type="operationType" |
| | | @confirm="submitForm" |
| | | @cancel="cancel" |
| | | @close="cancel" |
| | | > |
| | | <el-form ref="formRef" :model="form" :rules="rules" label-width="120px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤åç§°" prop="taskId"> |
| | | <el-select v-model="form.taskId" @change="setDeviceModel" filterable> |
| | | <el-option |
| | | v-for="(item, index) in deviceOptions" |
| | | :key="index" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | ></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è§æ ¼åå·"> |
| | | <el-input |
| | | v-model="form.deviceModel" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥äºº" prop="inspector"> |
| | | <el-select |
| | | v-model="form.inspector" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="item in userList" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | :key="item.userId" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»è®°æ¶é´" prop="registrationDate"> |
| | | <el-date-picker |
| | | v-model="form.registrationDate" |
| | | type="date" |
| | | placeholder="éæ©ç»è®°æ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä»»å¡é¢ç" prop="frequencyType"> |
| | | <el-select v-model="form.frequencyType" placeholder="è¯·éæ©" clearable> |
| | | <el-option label="æ¯æ¥" value="DAILY"/> |
| | | <el-option label="æ¯å¨" value="WEEKLY"/> |
| | | <el-option label="æ¯æ" value="MONTHLY"/> |
| | | <el-option label="å£åº¦" value="QUARTERLY"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'DAILY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" prop="frequencyDetail"> |
| | | <el-time-picker v-model="form.frequencyDetail" placeholder="éæ©æ¶é´" format="HH:mm" |
| | | value-format="HH:mm" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'WEEKLY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" prop="frequencyDetail"> |
| | | <el-select v-model="form.week" placeholder="è¯·éæ©" clearable style="width: 50%"> |
| | | <el-option label="å¨ä¸" value="MON"/> |
| | | <el-option label="å¨äº" value="TUE"/> |
| | | <el-option label="å¨ä¸" value="WED"/> |
| | | <el-option label="å¨å" value="THU"/> |
| | | <el-option label="å¨äº" value="FRI"/> |
| | | <el-option label="å¨å
" value="SAT"/> |
| | | <el-option label="卿¥" value="SUN"/> |
| | | </el-select> |
| | | <el-time-picker v-model="form.time" placeholder="éæ©æ¶é´" format="HH:mm" |
| | | value-format="HH:mm" style="width: 50%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'MONTHLY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" prop="frequencyDetail"> |
| | | <el-date-picker |
| | | v-model="form.frequencyDetail" |
| | | type="datetime" |
| | | clearable |
| | | placeholder="éæ©å¼å§æ¥æ" |
| | | format="DD,HH:mm" |
| | | value-format="DD,HH:mm" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" prop="frequencyDetail"> |
| | | <el-date-picker |
| | | v-model="form.frequencyDetail" |
| | | type="datetime" |
| | | clearable |
| | | placeholder="éæ©å¼å§æ¥æ" |
| | | format="MM,DD,HH:mm" |
| | | value-format="MM,DD,HH:mm" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="夿³¨" prop="remarks"> |
| | | <el-input v-model="form.remarks" placeholder="请è¾å
¥å¤æ³¨" type="textarea" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { reactive, ref, getCurrentInstance, toRefs } from "vue"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import { deviceMaintenanceTaskAdd, deviceMaintenanceTaskEdit } from "@/api/equipmentManagement/upkeep"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits() |
| | | const dialogVisitable = ref(false); |
| | | const operationType = ref('add'); |
| | | const deviceOptions = ref([]); |
| | | const userStore = useUserStore(); |
| | | const data = reactive({ |
| | | form: { |
| | | taskId: undefined, |
| | | taskName: undefined, |
| | | // å½å
¥äººï¼åéä¸ä¸ªç¨æ· id |
| | | inspector: undefined, |
| | | remarks: '', |
| | | frequencyType: '', |
| | | frequencyDetail: '', |
| | | week: '', |
| | | time: '', |
| | | deviceModel: undefined, // è§æ ¼åå· |
| | | registrationDate: '' |
| | | }, |
| | | rules: { |
| | | taskId: [{ required: true, message: "è¯·éæ©è®¾å¤", trigger: "change" },], |
| | | inspector: [{ required: true, message: "è¯·éæ©å½å
¥äºº", trigger: "blur" },], |
| | | registrationDate: [{ required: true, message: "è¯·éæ©ç»è®°æ¶é´", trigger: "change" }] |
| | | } |
| | | }) |
| | | const { form, rules } = toRefs(data) |
| | | const userList = ref([]) |
| | | |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | }; |
| | | |
| | | // éæ©è®¾å¤æ¶ï¼å填设å¤åç§°(taskName)åè§æ ¼åå·(deviceModel) |
| | | const setDeviceModel = (id) => { |
| | | const option = deviceOptions.value.find((item) => item.id === id); |
| | | if (option) { |
| | | form.value.taskId = option.id; |
| | | form.value.taskName = option.deviceName; |
| | | form.value.deviceModel = option.deviceModel; |
| | | } |
| | | } |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = async (type, row) => { |
| | | dialogVisitable.value = true |
| | | operationType.value = type |
| | | |
| | | // é置表å |
| | | resetForm(); |
| | | |
| | | // å è½½ç¨æ·å表 |
| | | userListNoPageByTenantId().then((res) => { |
| | | userList.value = res.data; |
| | | }); |
| | | |
| | | // å 载设å¤å表 |
| | | await loadDeviceName(); |
| | | |
| | | if (type === 'edit' && row) { |
| | | form.value = { ...row } |
| | | // ç¼è¾æ¶ç¨æ¥å£è¿åç registrantId åæ¾å½å
¥äºº |
| | | if (row.registrantId) { |
| | | form.value.inspector = row.registrantId |
| | | } |
| | | |
| | | // 妿æè®¾å¤IDï¼èªå¨è®¾ç½®è®¾å¤ä¿¡æ¯ |
| | | if (form.value.taskId) { |
| | | setDeviceModel(form.value.taskId); |
| | | } |
| | | } else if (type === 'add') { |
| | | // æ°å¢æ¶è®¾ç½®ç»è®°æ¥æä¸ºå½å¤© |
| | | form.value.registrationDate = getCurrentDate(); |
| | | // æ°å¢æ¶è®¾ç½®å½å
¥äººä¸ºå½åç»å½è´¦æ· |
| | | form.value.inspector = userStore.id; |
| | | } |
| | | } |
| | | |
| | | // å
³éå¯¹è¯æ¡ |
| | | const cancel = () => { |
| | | resetForm() |
| | | dialogVisitable.value = false |
| | | emit('closeDia') |
| | | } |
| | | |
| | | // é置表å彿° |
| | | const resetForm = () => { |
| | | if (proxy.$refs.formRef) { |
| | | proxy.$refs.formRef.resetFields() |
| | | } |
| | | // éç½®è¡¨åæ°æ®ç¡®ä¿è®¾å¤ä¿¡æ¯æ£ç¡®éç½® |
| | | form.value = { |
| | | taskId: undefined, |
| | | taskName: undefined, |
| | | inspector: undefined, |
| | | inspector: undefined, |
| | | remarks: '', |
| | | frequencyType: '', |
| | | frequencyDetail: '', |
| | | week: '', |
| | | time: '', |
| | | deviceModel: undefined, |
| | | registrationDate: '' |
| | | } |
| | | } |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(async valid => { |
| | | if (valid) { |
| | | try { |
| | | const payload = { ...form.value } |
| | | // ä¸åååç«¯ä¼ ä¿å
»äººå段ï¼ä»
ä½¿ç¨æ¥å£è¦æ±ç registrant / registrantId |
| | | // æ ¹æ®éæ©ç"å½å
¥äºº"设置 registrant / registrantId |
| | | if (payload.inspector) { |
| | | const selectedUser = userList.value.find( |
| | | (u) => String(u.userId) === String(payload.inspector) |
| | | ) |
| | | if (selectedUser) { |
| | | payload.registrantId = selectedUser.userId |
| | | payload.registrant = selectedUser.nickName |
| | | } |
| | | } |
| | | delete payload.inspector |
| | | delete payload.inspectorIds |
| | | |
| | | if (payload.frequencyType === 'WEEKLY') { |
| | | let frequencyDetail = '' |
| | | frequencyDetail = payload.week + ',' + payload.time |
| | | payload.frequencyDetail = frequencyDetail |
| | | } |
| | | |
| | | // å½å
¥æ¥æï¼ç´æ¥ä½¿ç¨è¡¨åéç registrationDate åæ®µ |
| | | // ä¸äºé»è®¤ç¶æå段 |
| | | if (payload.status === undefined || payload.status === null || payload.status === '') { |
| | | payload.status = '0' // é»è®¤ç¶æï¼å¯æå®é
æä¸¾è°æ´ |
| | | } |
| | | payload.active = true |
| | | payload.deleted = 0 |
| | | |
| | | if (operationType.value === 'edit') { |
| | | await deviceMaintenanceTaskEdit(payload) |
| | | } else { |
| | | await deviceMaintenanceTaskAdd(payload) |
| | | } |
| | | cancel() |
| | | proxy.$modal.msgSuccess('æäº¤æå') |
| | | } catch (error) { |
| | | proxy.$modal.msgError('æäº¤å¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | defineExpose({ openDialog }) |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
| | |
| | | <template #operation="{ row }"> |
| | | <el-button |
| | | type="primary" |
| | | text |
| | | icon="editPen" |
| | | link |
| | | @click="editScheduledTask(row)" |
| | | > |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | type="danger" |
| | | text |
| | | icon="delete" |
| | | link |
| | | @click="delScheduledTaskByIds(row.id)" |
| | | > |
| | | å é¤ |
| | |
| | | <div class="actions"> |
| | | <el-text class="mx-1" size="large">ä»»å¡è®°å½</el-text> |
| | | <div> |
| | | <el-button |
| | | type="primary" |
| | | icon="Plus" |
| | | :disabled="multipleList.length !== 1" |
| | | @click="addMaintain" |
| | | > |
| | | æ°å¢ä¿å
» |
| | | </el-button> |
| | | <el-button type="success" icon="Van" @click="addPlan"> |
| | | æ°å¢è®¡å |
| | | </el-button> |
| | |
| | | <el-button |
| | | type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0" |
| | | :disabled="multipleList.length <= 0 || hasFinishedStatus" |
| | | @click="delRepairByIds(multipleList.map((item) => item.id))" |
| | | > |
| | | æ¹éå é¤ |
| | |
| | | <template #operation="{ row }"> |
| | | <el-button |
| | | type="primary" |
| | | text |
| | | icon="editPen" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="editPlan(row.id)" |
| | | > |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | type="success" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="addMaintain(row)" |
| | | > |
| | | ä¿å
» |
| | | </el-button> |
| | | <el-button |
| | | type="danger" |
| | | text |
| | | icon="delete" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="delRepairByIds(row.id)" |
| | | > |
| | | å é¤ |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, reactive, getCurrentInstance, nextTick } from 'vue' |
| | | import { ref, onMounted, reactive, getCurrentInstance, nextTick, computed } from 'vue' |
| | | import { Search } from '@element-plus/icons-vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import PlanModal from './Modal/PlanModal.vue' |
| | | import MaintenanceModal from './Modal/MaintenanceModal.vue' |
| | | import FormDia from './Modal/formDia.vue' |
| | | import PlanModal from './Form/PlanModal.vue' |
| | | import MaintenanceModal from './Form/MaintenanceModal.vue' |
| | | import FormDia from './Form/formDia.vue' |
| | | import { |
| | | getUpkeepPage, |
| | | delUpkeep, |
| | |
| | | multipleList.value = selection |
| | | } |
| | | |
| | | // æ£æ¥éä¸çè®°å½ä¸æ¯å¦æå®ç»ç¶æç |
| | | const hasFinishedStatus = computed(() => { |
| | | return multipleList.value.some(item => item.status === 1) |
| | | }) |
| | | |
| | | const changePage = (page) => { |
| | | pagination.value.currentPage = page.page |
| | | pagination.value.pageSize = page.limit |
| | | getTableData() |
| | | } |
| | | |
| | | const addMaintain = () => { |
| | | const row = multipleList.value[0] |
| | | const addMaintain = (row) => { |
| | | maintainModalRef.value.open(row.id, row) |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | const delRepairByIds = async (ids) => { |
| | | // æ£æ¥æ¯å¦æå®ç»ç¶æçè®°å½ |
| | | const hasFinished = multipleList.value.some(item => item.status === 1) |
| | | if (hasFinished) { |
| | | ElMessage.warning('ä¸è½å é¤ç¶æä¸ºå®ç»çè®°å½') |
| | | return |
| | | } |
| | | |
| | | try { |
| | | await ElMessageBox.confirm('确认å é¤ä¿å
»æ°æ®, æ¤æä½ä¸å¯é?', 'è¦å', { |
| | | confirmButtonText: 'ç¡®å®', |
| | |
| | | <div style="padding: 20px;"> |
| | | <!-- 页颿 é¢åç鿡件 --> |
| | | <div class="w-full md:w-auto flex items-center gap-3" style="margin-bottom: 20px;"> |
| | | <el-button |
| | | type="primary" |
| | | icon="Refresh" |
| | | @click="resetFilters" |
| | | size="default" |
| | | > |
| | | æ¥è¯¢ |
| | | </el-button> |
| | | <el-form :inline="true"> |
| | | <el-form-item label="年份"> |
| | | <el-date-picker |
| | | v-model="selectedYear" |
| | | type="year" |
| | | placeholder="è¯·éæ©å¹´ä»½" |
| | | format="YYYY" |
| | | value-format="YYYY" |
| | | clearable |
| | | @change="fetchData()" |
| | | style="width: 200px" |
| | | :disabled-date="(date) => date.getFullYear() > new Date().getFullYear()" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="Refresh" |
| | | @click="resetFilters" |
| | | size="default" |
| | | > |
| | | éç½® |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <main class="container mx-auto px-4 pb-10"> |
| | |
| | | <el-card class="bg3"> |
| | | <p>èµäº§åå¼</p> |
| | | <h3> |
| | | ¥{{ assetInfo.totalOriginalValue }} |
| | | ¥{{ formatCurrency(assetInfo.totalOriginalValue) }} |
| | | </h3> |
| | | </el-card> |
| | | |
| | |
| | | <el-card class="bg4"> |
| | | <p>ç´¯è®¡ææ§</p> |
| | | <h3> |
| | | ¥{{ assetInfo.totalDepreciation }} |
| | | ¥{{ formatCurrency(assetInfo.totalDepreciation) }} |
| | | </h3> |
| | | </el-card> |
| | | |
| | |
| | | <el-card class="bg5"> |
| | | <p>åå¼</p> |
| | | <h3> |
| | | ¥{{ assetInfo.totalNetValue }} |
| | | ¥{{ formatCurrency(assetInfo.totalNetValue) }} |
| | | </h3> |
| | | </el-card> |
| | | <!-- è´åº --> |
| | | <el-card class="bg2"> |
| | | <p>è´åº</p> |
| | | <h3> |
| | | ¥{{ formatCurrency(assetInfo.debt) }} |
| | | </h3> |
| | | </el-card> |
| | | <!-- åºåèµäº§ --> |
| | | <el-card class="bg3"> |
| | | <p>åºåèµäº§</p> |
| | | <h3> |
| | | ¥{{ formatCurrency(assetInfo.inventoryValue) }} |
| | | </h3> |
| | | </el-card> |
| | | </div> |
| | |
| | | style="height: 260px; width: 35%;"> |
| | | <div class="chart-num"> |
| | | <span style="font-size: 22px;">设å¤ç±»å</span> |
| | | <span style="font-size: 36px; font-weight: 500; font-family: 'MyCustomFont', sans-serif;">{{ assetInfo.totalEquipment }}</span> |
| | | <span style="font-size: 36px; font-weight: 500; font-family: 'MyCustomFont', sans-serif;">{{ deviceTypeTotalCount }}</span> |
| | | </div> |
| | | </Echarts> |
| | | <Echarts |
| | |
| | | style="width: 100%" |
| | | :header-cell-style="{ background: '#f5f7fa', color: '#606266' }" |
| | | > |
| | | <el-table-column prop="id" label="èµäº§ç¼å·" width="120" /> |
| | | <el-table-column prop="deviceName" label="设å¤åç§°" width="250" /> |
| | | <el-table-column prop="deviceModel" label="åå·è§æ ¼" min-width="150" /> |
| | | <el-table-column prop="supplierName" label="ä¾åºå" min-width="120" /> |
| | |
| | | <el-table-column prop="number" label="æ°é" width="120" /> |
| | | <el-table-column prop="originalValue" label="åå¼(å
)" width="120"> |
| | | <template #default="{ row }"> |
| | | ¥{{ formatCurrency(row.taxIncludingPriceTotal) }} |
| | | {{ formatCurrency(row.taxIncludingPriceTotal) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="depreciation" label="ç´¯è®¡ææ§(å
)" width="140"> |
| | | <template #default="{ row }"> |
| | | ¥{{ formatCurrency(row.taxIncludingPriceTotal-row.unTaxIncludingPriceTotal) }} |
| | | {{ formatCurrency(row.deprAmount) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="netValue" label="åå¼(å
)" width="120"> |
| | | <template #default="{ row }"> |
| | | ¥{{ formatCurrency(row.unTaxIncludingPriceTotal) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="status" label="ç¶æ" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-tag |
| | | :type="getStatusTagType(row.status)" |
| | | size="small" |
| | | > |
| | | {{ row.status }} |
| | | </el-tag> |
| | | {{ formatCurrency(row.netValue) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | import 'element-plus/dist/index.css'; |
| | | import Echarts from "@/components/Echarts/echarts.vue"; |
| | | import { getLedgerPage } from "@/api/equipmentManagement/ledger"; |
| | | import { getAccountingTotal, getDeviceTypeDistribution, getCalculateDepreciation } from "@/api/financialManagement/accounting"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | // ç鿡件 |
| | | const dateRange = ref(null); |
| | | const equipmentType = ref(''); |
| | | const selectedYear = ref(dayjs().format('YYYY')); // é»è®¤å½å年份 |
| | | |
| | | |
| | | // åºå®èµäº§ä¿¡æ¯ |
| | | const assetInfo = ref({ |
| | | totalEquipment: 0, |
| | | totalOriginalValue: 0, |
| | | totalDepreciation: 0, |
| | | totalNetValue: 0 |
| | | totalEquipment: 0, // deviceTotal |
| | | totalOriginalValue: 0, // deviceAmount |
| | | totalDepreciation: 0, // deprAmount |
| | | totalNetValue: 0, // netValue |
| | | debt: 0, // è´åº |
| | | inventoryValue: 0 // åºåèµäº§ |
| | | }); |
| | | |
| | | // 设å¤ç±»åæ»æ°ï¼ç¨äºå¾è¡¨æ¾ç¤ºï¼ |
| | | const deviceTypeTotalCount = ref(0); |
| | | |
| | | // 设å¤å表 |
| | | const equipmentList = ref([]); |
| | |
| | | const fetchData = async () => { |
| | | try { |
| | | // è·ååºå®èµäº§æ±æ»ä¿¡æ¯ |
| | | const assetInfoRes = await getAssetInfo({ |
| | | const assetInfoRes = await getAccountingTotal({ |
| | | startDate: dateRange.value ? dateRange.value[0] : null, |
| | | endDate: dateRange.value ? dateRange.value[1] : null, |
| | | equipmentType: equipmentType.value |
| | | equipmentType: equipmentType.value, |
| | | year: selectedYear.value |
| | | }); |
| | | |
| | | if (assetInfoRes.code === 200) { |
| | | assetInfo.value = assetInfoRes.data; |
| | | // æ å°åç«¯åæ®µå°åç«¯åæ®µ |
| | | const data = assetInfoRes.data; |
| | | assetInfo.value = { |
| | | totalEquipment: data.deviceTotal || 0, // è®¾å¤æ»æ° |
| | | totalOriginalValue: data.deviceAmount || 0, // èµäº§åå¼ |
| | | totalDepreciation: data.deprAmount || 0, // ç´¯è®¡ææ§ |
| | | totalNetValue: data.netValue || 0, // åå¼ |
| | | debt: data.debt || 0, // è´åº |
| | | inventoryValue: data.inventoryValue || 0 // åºåèµäº§ |
| | | }; |
| | | } |
| | | |
| | | // è·å设å¤å表 |
| | | const equipmentListRes = await getLedgerPage({ |
| | | current: pagination.value.currentPage, |
| | | size: pagination.value.pageSize, |
| | | // è·å设å¤ç±»åå叿°æ®ï¼é¥¼å¾åæçº¿å¾ï¼ |
| | | const distributionRes = await getDeviceTypeDistribution({ |
| | | startDate: dateRange.value ? dateRange.value[0] : null, |
| | | endDate: dateRange.value ? dateRange.value[1] : null, |
| | | equipmentType: equipmentType.value |
| | | equipmentType: equipmentType.value, |
| | | year: selectedYear.value |
| | | }); |
| | | |
| | | if (equipmentListRes.code === 200) { |
| | | equipmentList.value = equipmentListRes.data.records; |
| | | pagination.value.total = equipmentListRes.data.total; |
| | | |
| | | // æ ¹æ® equipmentList æ deviceName è¿è¡åç±»ç»è®¡ |
| | | const deviceNameMap = {}; |
| | | equipmentList.value.forEach(item => { |
| | | const deviceName = item.deviceName; |
| | | if (!deviceNameMap[deviceName]) { |
| | | deviceNameMap[deviceName] = { |
| | | name: deviceName, |
| | | count: 0, |
| | | totalValue: 0 |
| | | }; |
| | | } |
| | | deviceNameMap[deviceName].count += item.number || 1; // å设 number ä¸ºè®¾å¤æ°é |
| | | deviceNameMap[deviceName].totalValue += item.taxIncludingPriceTotal || 0; // ç´¯å å«ç¨æ»ä»· |
| | | }); |
| | | |
| | | // 转æ¢ä¸º typeDistributionData æ ¼å¼ |
| | | typeDistributionData.value = Object.values(deviceNameMap).map(item => ({ |
| | | name: item.name, |
| | | value: item.count, |
| | | count: item.count, |
| | | amount: `Â¥${formatCurrency(item.totalValue)}` |
| | | })); |
| | | if (distributionRes.code === 200) { |
| | | const data = distributionRes.data; |
| | | |
| | | // æ´æ°è®¾å¤ç±»åæ»æ° |
| | | deviceTypeTotalCount.value = data.totalCount || 0; |
| | | |
| | | // 转æ¢é¥¼å¾æ°æ®æ ¼å¼ |
| | | if (data.details && data.details.length > 0) { |
| | | typeDistributionData.value = data.details.map(item => ({ |
| | | name: item.type || '', |
| | | value: Number(item.count || 0), |
| | | count: Number(item.count || 0), |
| | | amount: `Â¥${formatCurrency(item.amount || 0)}` |
| | | })); |
| | | } else if (data.categories && data.categories.length > 0) { |
| | | // å¦ææ²¡æ detailsï¼ä½¿ç¨ categoriesãcountData å amountData æå»º |
| | | typeDistributionData.value = data.categories.map((category, index) => ({ |
| | | name: category, |
| | | value: Number(data.countData[index] || 0), |
| | | count: Number(data.countData[index] || 0), |
| | | amount: `Â¥${formatCurrency(data.amountData[index] || 0)}` |
| | | })); |
| | | } else { |
| | | typeDistributionData.value = []; |
| | | } |
| | | |
| | | // æ´æ°xè½´æ°æ® |
| | | xAxis.value[0].data = typeDistributionData.value.map(item => item.name); |
| | | xAxis.value[0].data = data.categories || typeDistributionData.value.map(item => item.name); |
| | | |
| | | // æå»ºæçº¿å¾æ°æ® |
| | | typeDistributionLineSeries.value = [ |
| | | { |
| | | name: 'è®¾å¤æ°é', |
| | | type: 'line', |
| | | data: typeDistributionData.value.map(item => item.count) |
| | | data: data.countData || typeDistributionData.value.map(item => item.count) |
| | | } |
| | | ]; |
| | | } |
| | | |
| | | // è·å设å¤åè¡¨ï¼ææ§è®¡ç®æ°æ®ï¼ |
| | | const equipmentListRes = await getCalculateDepreciation({ |
| | | current: pagination.value.currentPage, |
| | | size: pagination.value.pageSize, |
| | | startDate: dateRange.value ? dateRange.value[0] : null, |
| | | endDate: dateRange.value ? dateRange.value[1] : null, |
| | | equipmentType: equipmentType.value, |
| | | year: selectedYear.value |
| | | }); |
| | | |
| | | if (equipmentListRes.code === 200) { |
| | | // 妿è¿åçæ¯åé¡µæ°æ® |
| | | if (equipmentListRes.data.records) { |
| | | equipmentList.value = equipmentListRes.data.records; |
| | | pagination.value.total = equipmentListRes.data.total; |
| | | } else if (Array.isArray(equipmentListRes.data)) { |
| | | // 妿è¿åçæ¯æ°ç» |
| | | equipmentList.value = equipmentListRes.data; |
| | | pagination.value.total = equipmentListRes.data.length; |
| | | } else { |
| | | equipmentList.value = []; |
| | | pagination.value.total = 0; |
| | | } |
| | | } |
| | | } catch (error) { |
| | | console.error('è·ååºå®èµäº§æ°æ®å¤±è´¥ï¼', error); |
| | |
| | | const resetFilters = () => { |
| | | dateRange.value = null; |
| | | equipmentType.value = ''; |
| | | selectedYear.value = dayjs().format('YYYY'); // é置为å½å年份 |
| | | fetchData(); |
| | | }; |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /* 大å±å¹åä»¥ä¸ (lg:grid-cols-5) */ |
| | | /* 大å±å¹åä»¥ä¸ (lg:grid-cols-6) */ |
| | | @media (min-width: 1024px) { |
| | | .grid-container { |
| | | grid-template-columns: repeat(5, minmax(0, 1fr)); |
| | | grid-template-columns: repeat(6, minmax(0, 1fr)); |
| | | } |
| | | } |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog v-model="dialogFormVisible" :title="getDialogTitle()" width="70%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-form-item label="éè´è®¢åå·" prop="purchaseContractNumber"> |
| | | <el-select |
| | | v-model="form.purchaseContractNumber" |
| | | placeholder="è¯·éæ©éè´è®¢åå·" |
| | | clearable |
| | | filterable |
| | | :loading="loadingPurchaseOptions" |
| | | @change="handlePurchaseChange" |
| | | :disabled="operationType === 'edit'" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="item in purchaseOptions" |
| | | :key="item.purchaseContractNumber" |
| | | :label="formatPurchaseOption(item)" |
| | | :value="item.purchaseContractNumber" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-table |
| | | :data="productList" |
| | | border |
| | | v-loading="loadingProducts" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column |
| | | align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" /> |
| | | <el-table-column label="åä½" prop="unit" width="70" /> |
| | | <!-- <el-table-column label="ä¾åºå" prop="supplierName" width="100" /> --> |
| | | <el-table-column label="éè´æ°é" prop="quantity" width="100" /> |
| | | <el-table-column label="å¾
å
¥åºæ°é" prop="quantity0" width="100" /> |
| | | <el-table-column label="æ¬æ¬¡å
¥åºæ°é" prop="quantityStock" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" @change="() => calculateTotalPrice(scope.row)" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="120" /> |
| | | <el-table-column label="åä»·(å
)" prop="taxInclusiveUnitPrice" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.taxInclusiveUnitPrice" @change="() => calculateTotalPrice(scope.row)" :disabled="operationType === 'edit'"/> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æ»ä»·(å
)" |
| | | :formatter="formattedNumber" |
| | | prop="taxInclusiveTotalPrice" |
| | | width="150" |
| | | > |
| | | </el-table-column> |
| | | </el-table> |
| | | </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> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, toRefs, getCurrentInstance } from 'vue' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { |
| | | updateStockIn, |
| | | addSutockIn, |
| | | selectProductRecordListByPuechaserId |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | import { purchaseListPage } from "@/api/procurementManagement/procurementLedger.js"; |
| | | |
| | | const userStore = useUserStore() |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close', 'success']) |
| | | |
| | | const operationType = ref('')// æä½ç±»å: 'add' æ 'edit' |
| | | const dialogFormVisible = ref(false)// å¼¹æ¡æ¾ç¤ºç¶æ |
| | | const productList = ref([]);// 产ååè¡¨æ°æ® |
| | | const loadingProducts = ref(false);// 产åå è½½ç¶æ |
| | | const selectedRows = ref([]) // 产åè¡¨æ ¼éä¸è¡ |
| | | const purchaseOptions = ref([]) |
| | | const loadingPurchaseOptions = ref(false) |
| | | const loading = ref(false); |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | id: null, |
| | | purchaseContractNumber: '', // éè´è®¢åå· |
| | | supplierId: null, // ä¾åºåID |
| | | supplierName: '', // ä¾åºååç§° |
| | | inboundTime: '', // å
¥åºæ¶é´ |
| | | inboundBatch: '', // å
¥åºæ¹æ¬¡ |
| | | recorderId: userStore.userId, // å½å
¥äººID |
| | | recorderName: userStore.name, // å½å
¥äººå§å |
| | | entryDate: getCurrentDate(), // å½å
¥æ¥æ |
| | | remark: '', // 夿³¨ |
| | | }, |
| | | rules: { |
| | | purchaseContractNumber: [{ required: true, message: "请è¾å
¥éè´ååå·", trigger: "blur" }], |
| | | supplierId: [{ required: true, message: "è¯·éæ©ä¾åºå", trigger: "change" }], |
| | | inboundTime: [{ required: true, message: "è¯·éæ©å
¥åºæ¶é´", trigger: "change" }], |
| | | inboundBatch: [{ required: true, message: "请è¾å
¥å
¥åºæ¹æ¬¡", trigger: "blur" }] |
| | | } |
| | | }) |
| | | const { form, rules } = toRefs(data) |
| | | |
| | | // å¨æè®¡ç®å¯¹è¯æ¡æ é¢ |
| | | const getDialogTitle = () => { |
| | | return operationType.value === 'add' ? 'æ°å¢å
¥åº' : 'ç¼è¾å
¥åº' |
| | | } |
| | | |
| | | const formatPurchaseOption = (item = {}) => { |
| | | const contract = item.purchaseContractNumber || '--'; |
| | | const supplier = item.supplierName ? ` · ${item.supplierName}` : ''; |
| | | return `${contract}${supplier}`; |
| | | }; |
| | | |
| | | const loadPurchaseOptions = async (keyword = '') => { |
| | | try { |
| | | loadingPurchaseOptions.value = true; |
| | | const res = await purchaseListPage({ |
| | | current: -1, |
| | | size: -1, |
| | | purchaseContractNumber: keyword, |
| | | }); |
| | | const records = res.data?.records || []; |
| | | purchaseOptions.value = records; |
| | | if ( |
| | | form.value.purchaseContractNumber && |
| | | !purchaseOptions.value.find( |
| | | (item) => item.purchaseContractNumber === form.value.purchaseContractNumber |
| | | ) |
| | | ) { |
| | | purchaseOptions.value.push({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber, |
| | | supplierName: form.value.supplierName, |
| | | supplierId: form.value.supplierId, |
| | | }); |
| | | } |
| | | } finally { |
| | | loadingPurchaseOptions.value = false; |
| | | } |
| | | }; |
| | | |
| | | const handlePurchaseChange = (value) => { |
| | | form.value.purchaseContractNumber = value || ''; |
| | | const matched = purchaseOptions.value.find( |
| | | (item) => item.purchaseContractNumber === value |
| | | ); |
| | | if (matched) { |
| | | form.value.supplierName = matched.supplierName || form.value.supplierName; |
| | | form.value.supplierId = matched.supplierId || form.value.supplierId; |
| | | } |
| | | if (!value) { |
| | | productList.value = []; |
| | | return; |
| | | } |
| | | fetchProductsByContract(); |
| | | }; |
| | | |
| | | const exceedsAddLimit = (product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | const waiting = Number(product?.quantity0 ?? 0); |
| | | if (!Number.isFinite(stock) || !Number.isFinite(waiting)) { |
| | | return false; |
| | | } |
| | | return stock > waiting; |
| | | }; |
| | | |
| | | const exceedsEditLimit = (product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | const waiting = Number(product?.quantity0 ?? 0); |
| | | const original = Number(product?.originalQuantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || !Number.isFinite(waiting) || !Number.isFinite(original)) { |
| | | return false; |
| | | } |
| | | return stock > waiting + original; |
| | | }; |
| | | |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | }; |
| | | |
| | | // è®¡ç®æ»ä»· |
| | | const calculateTotalPrice = (row) => { |
| | | const quantityStock = Number(row?.quantityStock ?? 0); |
| | | const taxInclusiveUnitPrice = Number(row?.taxInclusiveUnitPrice ?? 0); |
| | | |
| | | if (Number.isFinite(quantityStock) && Number.isFinite(taxInclusiveUnitPrice)) { |
| | | row.taxInclusiveTotalPrice = quantityStock * taxInclusiveUnitPrice; |
| | | } else { |
| | | row.taxInclusiveTotalPrice = 0; |
| | | } |
| | | }; |
| | | |
| | | const fetchProductsByContract = async () => { |
| | | if (!form.value.purchaseContractNumber) { |
| | | proxy.$modal.msgWarning('è¯·éæ©ååå·') |
| | | return |
| | | } |
| | | try { |
| | | loadingProducts.value = true |
| | | const productRes = await selectProductRecordListByPuechaserId({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber |
| | | }); |
| | | if (!productRes.data || productRes.data.length === 0) { |
| | | proxy.$modal.msgWarning('该åå䏿²¡æäº§åè®°å½') |
| | | productList.value = []; |
| | | return |
| | | } |
| | | productList.value = productRes.data.map(item => ({ |
| | | ...item, |
| | | quantityStock: 0, |
| | | taxInclusiveUnitPrice: Number(item?.taxInclusiveUnitPrice ?? 0), |
| | | taxInclusiveTotalPrice: 0, |
| | | originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? 0), |
| | | })) |
| | | } catch (error) { |
| | | console.error('æ¥è¯¢äº§åè®°å½å¤±è´¥:', error) |
| | | proxy.$modal.msgError('æ¥è¯¢äº§åè®°å½å¤±è´¥') |
| | | productList.value = []; |
| | | } finally { |
| | | loadingProducts.value = false |
| | | } |
| | | } |
| | | |
| | | const updatePro = async () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning('请å
éæ©äº§å'); |
| | | return; |
| | | } |
| | | const target = selectedRows.value[0]; |
| | | const stock = Number(target?.quantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | proxy.$modal.msgWarning('è¯·å¡«åææçå
¥åºæ°é'); |
| | | return; |
| | | } |
| | | if (exceedsEditLimit(target)) { |
| | | proxy.$modal.msgError('æ¬æ¬¡å
¥åºæ°éä¸è½è¶
è¿åå
¥åºæ°éä¸å¾
å
¥åºæ°éä¹å'); |
| | | return; |
| | | } |
| | | const stockInData = { |
| | | id: selectedRows.value[0].recordId, |
| | | quantityStock: Number(selectedRows.value[0].quantityStock), |
| | | }; |
| | | await updateStockIn(stockInData) |
| | | proxy.$modal.msgSuccess('ä¿®æ¹å
¥åºæå') |
| | | closeDia() |
| | | emit('success') |
| | | } |
| | | |
| | | const submitForm = async () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning('请å
éæ©éè´ååå¹¶éæ©äº§å') |
| | | return |
| | | } |
| | | if(operationType.value !== 'add'){ |
| | | await updatePro() |
| | | return |
| | | } |
| | | try { |
| | | await proxy.$refs.formRef.validate() |
| | | const invalidProducts = selectedRows.value.filter((product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | return true; |
| | | } |
| | | return exceedsAddLimit(product); |
| | | }) |
| | | |
| | | if (invalidProducts.length > 0) { |
| | | proxy.$modal.msgError('æ¬æ¬¡å
¥åºæ°éé大äº0ï¼ä¸ä¸è½è¶
è¿å¾
å
¥åºæ°é') |
| | | return |
| | | } |
| | | |
| | | const stockInData = { |
| | | ...form.value, |
| | | inboundTime: formatDateTime(form.value.inboundTime), |
| | | nickName: userStore.nickName, |
| | | details: selectedRows.value.map(product => ({ |
| | | id: product.id, |
| | | inboundQuantity: Number(product.quantityStock), |
| | | unitPrice: Number(product.taxInclusiveUnitPrice), |
| | | taxRate: Number(product.taxRate), |
| | | taxInclusiveTotalPrice: Number(product.taxInclusiveTotalPrice) |
| | | })), |
| | | }; |
| | | loading.value = true |
| | | await addSutockIn(stockInData) |
| | | |
| | | proxy.$modal.msgSuccess('æ°å¢å
¥åºæå') |
| | | closeDia() |
| | | emit('success') |
| | | |
| | | } catch (error) { |
| | | console.error('æäº¤å¤±è´¥:', error) |
| | | if (!error.errors) { |
| | | proxy.$modal.msgError('æä½å¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | const closeDia = () => { |
| | | proxy.$refs.formRef.resetFields() |
| | | dialogFormVisible.value = false |
| | | emit('close') |
| | | } |
| | | |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection.filter(item => item.id); |
| | | } |
| | | |
| | | function formatDateTime(date = new Date(), includeTime = true) { |
| | | const d = new Date(date); |
| | | const year = d.getFullYear(); |
| | | const month = String(d.getMonth() + 1).padStart(2, '0'); |
| | | const day = String(d.getDate()).padStart(2, '0'); |
| | | |
| | | if (!includeTime) { |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | |
| | | const hours = String(d.getHours()).padStart(2, '0'); |
| | | const minutes = String(d.getMinutes()).padStart(2, '0'); |
| | | const seconds = String(d.getSeconds()).padStart(2, '0'); |
| | | |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | } |
| | | |
| | | function getCurrentDate() { |
| | | return formatDateTime(new Date(), false); |
| | | } |
| | | |
| | | const openDialog = async (type, row) => { |
| | | operationType.value = type |
| | | dialogFormVisible.value = true |
| | | selectedRows.value = [] |
| | | await loadPurchaseOptions(); |
| | | |
| | | if (type === 'add') { |
| | | form.value = { |
| | | id: null, |
| | | purchaseContractNumber: '', |
| | | supplierId: null, |
| | | supplierName: '', |
| | | inboundTime: '', |
| | | inboundBatch: '', |
| | | recorderId: userStore.userId, |
| | | recorderName: userStore.name, |
| | | entryDate: getCurrentDate(), |
| | | remark: '' |
| | | } |
| | | productList.value = [] |
| | | } else { |
| | | form.value = JSON.parse(JSON.stringify(row)) |
| | | try { |
| | | loadingProducts.value = true |
| | | const res = await selectProductRecordListByPuechaserId({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber, |
| | | id: row.id |
| | | }); |
| | | productList.value = res.data.map(item => ({ |
| | | ...item, |
| | | quantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0), |
| | | taxInclusiveUnitPrice: Number(item?.taxInclusiveUnitPrice ?? 0), |
| | | taxInclusiveTotalPrice: Number(item?.quantityStock ?? 0) * Number(item?.taxInclusiveUnitPrice ?? 0), |
| | | originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0), |
| | | })) |
| | | selectedRows.value = productList.value |
| | | } catch (error) { |
| | | console.error('å 载产å失败:', error) |
| | | proxy.$modal.msgError('å 载产å失败') |
| | | productList.value = [] |
| | | } finally { |
| | | loadingProducts.value = false |
| | | } |
| | | } |
| | | } |
| | | |
| | | defineExpose({ |
| | | openDialog, |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"></style> |
| | | |
| | | |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? 'æ°å¢èªå®ä¹å
¥åº' : 'ç¼è¾èªå®ä¹å
¥åº'" width="70%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <div style="margin-bottom: 10px;" v-if="operationType === 'add'"> |
| | | <el-button type="primary" @click="addProductRow">æ°å¢</el-button> |
| | | </div> |
| | | <el-table |
| | | :data="productList" |
| | | border |
| | | v-loading="loadingProducts" |
| | | > |
| | | <el-table-column |
| | | align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="产å大类" prop="productCategory" width="200"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.productCategory" placeholder="请è¾å
¥äº§å大类" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" width="200"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.specificationModel" placeholder="请è¾å
¥è§æ ¼åå·" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åä½" prop="unit" width="100"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.unit" placeholder="请è¾å
¥åä½" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å
¥åºæ°é" prop="inboundNum" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.inboundNum" @change="() => calculateTotalPrice(scope.row)" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å
¥åºæ¥æ" prop="inboundDate" width="180"> |
| | | <template #default="scope"> |
| | | <el-date-picker |
| | | v-model="scope.row.inboundDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©å
¥åºæ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | style="width: 100%" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åä»·(å
)" prop="unitPrice" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.unitPrice" @change="() => calculateTotalPrice(scope.row)" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æ»ä»·(å
)" |
| | | prop="totalPrice" |
| | | width="150" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="80" v-if="operationType === 'add'"> |
| | | <template #default="scope"> |
| | | <el-button type="danger" size="small" @click="removeProductRow(scope.$index)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </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> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, toRefs, getCurrentInstance } from 'vue' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { |
| | | addStockInCustom, updateProduct |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | |
| | | const userStore = useUserStore() |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close', 'success']) |
| | | |
| | | const operationType = ref('')// æä½ç±»å: 'add' æ 'edit' |
| | | const dialogFormVisible = ref(false)// å¼¹æ¡æ¾ç¤ºç¶æ |
| | | const productList = ref([]);// 产ååè¡¨æ°æ® |
| | | const loadingProducts = ref(false);// 产åå è½½ç¶æ |
| | | const loading = ref(false); |
| | | |
| | | function formatDateTime(date = new Date(), includeTime = true) { |
| | | const d = new Date(date); |
| | | const year = d.getFullYear(); |
| | | const month = String(d.getMonth() + 1).padStart(2, '0'); |
| | | const day = String(d.getDate()).padStart(2, '0'); |
| | | |
| | | if (!includeTime) { |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | |
| | | const hours = String(d.getHours()).padStart(2, '0'); |
| | | const minutes = String(d.getMinutes()).padStart(2, '0'); |
| | | const seconds = String(d.getSeconds()).padStart(2, '0'); |
| | | |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | } |
| | | |
| | | function getCurrentDate() { |
| | | return formatDateTime(new Date(), false); |
| | | } |
| | | |
| | | const itemTypeOptions = [ |
| | | { label: 'ç©æ', value: 'ç©æ' }, |
| | | { label: 'åæ', value: 'åæ' }, |
| | | { label: 'æå', value: 'æå' }, |
| | | { label: 'å
¶ä»', value: 'å
¶ä»' }, |
| | | ] |
| | | |
| | | const taxRateOptions = [ |
| | | { label: '1', value: 1 }, |
| | | { label: '6', value: 6 }, |
| | | { label: '13', value: 13 }, |
| | | ] |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | id: null, |
| | | supplierId: null, // ä¾åºåID |
| | | supplierName: '', // ä¾åºååç§° |
| | | recorderId: userStore.userId, // å½å
¥äººID |
| | | recorderName: userStore.name, // å½å
¥äººå§å |
| | | entryDate: getCurrentDate(), // å½å
¥æ¥æ |
| | | remark: '', // 夿³¨ |
| | | }, |
| | | rules: { |
| | | supplierName: [{ required: true, message: "请è¾å
¥ä¾åºååç§°", trigger: "blur" }] |
| | | } |
| | | }) |
| | | const { form, rules } = toRefs(data) |
| | | |
| | | // æ°å¢äº§åè¡ |
| | | const addProductRow = () => { |
| | | productList.value.push({ |
| | | id: null, |
| | | productCategory: '', |
| | | specificationModel: '', |
| | | unit: '', |
| | | supplierName: form.value.supplierName || '', |
| | | itemType: '', |
| | | inboundNum: 0, |
| | | inboundDate: '', |
| | | quantityStock: 0, |
| | | unitPrice: 0, |
| | | totalPrice: 0, |
| | | taxRate: null, |
| | | taxExclusiveTotalPrice: 0, |
| | | }); |
| | | }; |
| | | |
| | | // å é¤äº§åè¡ |
| | | const removeProductRow = (index) => { |
| | | productList.value.splice(index, 1); |
| | | }; |
| | | |
| | | // è®¡ç®æ»ä»·ï¼æ ¹æ®æ°éãåä»·åå«ç¨åä»·ï¼ |
| | | const calculateTotalPrice = (row) => { |
| | | // è®¡ç®æ®éæ»ä»·ï¼inboundNum * unitPrice |
| | | const quantity = Number(row.inboundNum || 0); |
| | | const unitPrice = Number(row.unitPrice || 0); |
| | | row.totalPrice = quantity * unitPrice; |
| | | calculateExclusivePrice(row); |
| | | }; |
| | | |
| | | // 计ç®ä¸å«ç¨æ»ä»·ï¼æ ¹æ®å«ç¨æ»ä»·åç¨çï¼ |
| | | const calculateExclusivePrice = (row) => { |
| | | const totalPrice = Number(row.totalPrice || 0); |
| | | const taxRate = Number(row.taxRate || 0); |
| | | row.taxExclusiveTotalPrice = totalPrice / (1 + taxRate / 100); |
| | | }; |
| | | |
| | | const submitForm = async () => { |
| | | try { |
| | | await proxy.$refs.formRef.validate() |
| | | |
| | | if (!productList.value.length) { |
| | | proxy.$modal.msgError('请è³å°æ·»å 䏿¡äº§åæ°æ®') |
| | | return |
| | | } |
| | | |
| | | // éªè¯èªå®ä¹æ·»å çæ°æ®å¿
å¡«åæ®µ |
| | | for (let i = 0; i < productList.value.length; i++) { |
| | | const product = productList.value[i]; |
| | | if (!product.productCategory || !product.specificationModel || !product.unit) { |
| | | proxy.$modal.msgError(`第${i + 1}è¡äº§åæ°æ®æªå¡«å宿´ï¼äº§å大类ãè§æ ¼åå·ãåä½ä¸ºå¿
å¡«ï¼`) |
| | | return |
| | | } |
| | | if (!product.inboundDate) { |
| | | proxy.$modal.msgError(`第${i + 1}è¡è¯·éæ©å
¥åºæ¥æ`) |
| | | return |
| | | } |
| | | const stock = Number(product?.inboundNum ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | proxy.$modal.msgError(`第${i + 1}è¡æ¬æ¬¡å
¥åºæ°éé大äº0`) |
| | | return |
| | | } |
| | | } |
| | | |
| | | const payloadList = productList.value.map(product => ({ |
| | | id: product.id ?? null, |
| | | inboundNum: Number(product.inboundNum), |
| | | productCategory: product.productCategory, |
| | | specificationModel: product.specificationModel, |
| | | unit: product.unit, |
| | | supplierName: product.supplierName || form.value.supplierName, |
| | | itemType: product.itemType, |
| | | inboundDate: formatDateTime(product.inboundDate, false), |
| | | taxRate: Number(product.taxRate || 0), |
| | | taxExclusiveTotalPrice: Number(product.taxExclusiveTotalPrice || 0), |
| | | unitPrice: Number(product.unitPrice || 0), |
| | | })); |
| | | loading.value = true |
| | | if (operationType.value === 'edit') { |
| | | const editPayload = payloadList[0] |
| | | await updateProduct(editPayload) |
| | | } else { |
| | | await addStockInCustom(payloadList) |
| | | } |
| | | |
| | | proxy.$modal.msgSuccess(operationType.value === 'edit' ? 'ç¼è¾èªå®ä¹å
¥åºæå' : 'æ°å¢èªå®ä¹å
¥åºæå') |
| | | closeDia() |
| | | emit('success') |
| | | |
| | | } catch (error) { |
| | | console.error('æäº¤å¤±è´¥:', error) |
| | | if (!error.errors) { |
| | | proxy.$modal.msgError('æä½å¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | const closeDia = () => { |
| | | proxy.$refs.formRef.resetFields() |
| | | dialogFormVisible.value = false |
| | | productList.value = [] |
| | | emit('close') |
| | | } |
| | | |
| | | const openDialog = async (type, row) => { |
| | | operationType.value = type |
| | | dialogFormVisible.value = true |
| | | |
| | | if (type === 'add') { |
| | | form.value = { |
| | | id: null, |
| | | supplierId: null, |
| | | supplierName: '', |
| | | recorderId: userStore.userId, |
| | | recorderName: userStore.name, |
| | | entryDate: getCurrentDate(), |
| | | remark: '' |
| | | } |
| | | productList.value = [] |
| | | } else { |
| | | // ç¼è¾æ¨¡å¼ï¼å°è¡æ°æ®å¡«å
å°è¡¨æ ¼ä¸ä»¥æ¯æä¿®æ¹ |
| | | form.value = { |
| | | id: row?.id ?? null, |
| | | supplierId: row?.supplierId ?? null, |
| | | supplierName: row?.supplierName ?? '', |
| | | recorderId: userStore.userId, |
| | | recorderName: userStore.name, |
| | | entryDate: getCurrentDate(), |
| | | remark: row?.remark ?? '' |
| | | } |
| | | productList.value = [{ |
| | | id: row?.id ?? null, |
| | | productCategory: row?.productCategory ?? '', |
| | | specificationModel: row?.specificationModel ?? '', |
| | | unit: row?.unit ?? '', |
| | | supplierName: row?.supplierName ?? '', |
| | | itemType: row?.itemType ?? '', |
| | | inboundNum: Number(row?.inboundNum ?? row?.inboundQuantity ?? 0), |
| | | inboundDate: row?.inboundDate ?? row?.createTime ?? '', |
| | | taxRate: Number(row?.taxRate ?? 0), |
| | | unitPrice: Number(row?.unitPrice ?? 0), |
| | | taxExclusiveTotalPrice: Number(row?.taxExclusiveTotalPrice ?? 0), |
| | | }] |
| | | } |
| | | } |
| | | |
| | | defineExpose({ |
| | | openDialog, |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"></style> |
| | | |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">ä¾åºååç§°ï¼</span> |
| | | <el-input v-model="searchForm.supplierName" style="width: 240px" placeholder="请è¾å
¥" @change="handleQuery" |
| | | clearable prefix-icon="Search" /> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery" |
| | | /> |
| | | <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"> |
| | | <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%" |
| | | :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="å
¥åºæ¶é´" prop="createTime" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ¹æ¬¡" prop="inboundBatches" width="160" show-overflow-tooltip /> |
| | | <el-table-column label="ä¾åºååç§°" prop="supplierName" width="240" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" width="200" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="70" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ°é" prop="inboundNum" width="90" show-overflow-tooltip /> |
| | | <el-table-column label="å«ç¨åä»·" prop="taxInclusiveUnitPrice" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å«ç¨æ»ä»·" prop="taxInclusiveTotalPrice" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="80" show-overflow-tooltip /> |
| | | <el-table-column label="ä¸å«ç¨æ»ä»·" prop="taxExclusiveTotalPrice" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºäºº" prop="createBy" width="80" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" min-width="60" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm('edit', 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> |
| | | |
| | | <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? 'æ°å¢å
¥åº' : 'ç¼è¾å
¥åº'" width="70%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-form-item label="éè´è®¢åå·" prop="purchaseContractNumber"> |
| | | <el-select |
| | | v-model="form.purchaseContractNumber" |
| | | placeholder="è¯·éæ©éè´è®¢åå·" |
| | | clearable |
| | | filterable |
| | | remote |
| | | :remote-method="loadPurchaseOptions" |
| | | :loading="loadingPurchaseOptions" |
| | | @change="handlePurchaseChange" |
| | | :disabled="operationType === 'edit'" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="item in purchaseOptions" |
| | | :key="item.purchaseContractNumber" |
| | | :label="formatPurchaseOption(item)" |
| | | :value="item.purchaseContractNumber" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-table |
| | | :data="productList" |
| | | border |
| | | v-loading="loadingProducts" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column |
| | | align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" /> |
| | | <el-table-column label="åä½" prop="unit" width="70" /> |
| | | <el-table-column label="ä¾åºå" prop="supplierName" width="100" /> |
| | | <el-table-column label="éè´æ°é" prop="quantity" width="100" /> |
| | | <el-table-column label="å¾
å
¥åºæ°é" prop="quantity0" width="100" /> |
| | | <el-table-column label="æ¬æ¬¡å
¥åºæ°é" prop="quantityStock" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="120" /> |
| | | <el-table-column |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | </el-table> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | <el-tabs v-model="activeTab" |
| | | @tab-change="handleTabChange"> |
| | | <el-tab-pane label="æåå
¥åº" |
| | | name="production"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | | <el-date-picker v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery"/> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input v-model="searchForm.productCategory" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable/> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px">æç´¢ |
| | | </el-button> |
| | | </div> |
| | | <div> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <div class="table_list"> |
| | | <el-table :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="row => row.id" |
| | | show-summary |
| | | style="width: 100%" |
| | | :summary-method="summarizeMainTable" |
| | | height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" |
| | | type="selection" |
| | | width="55"/> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60"/> |
| | | <el-table-column label="å
¥åºæ¶é´" |
| | | prop="createTime" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="éå®ååå·" |
| | | prop="salesContractNo" |
| | | width="180" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="产å大类" |
| | | prop="productCategory" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="è§æ ¼åå·" |
| | | prop="specificationModel" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="åä½" |
| | | prop="unit" |
| | | width="70" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="å
¥åºæ°é" |
| | | prop="inboundNum" |
| | | width="100" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="åä»·(å
)" |
| | | prop="unitPrice" |
| | | width="150"></el-table-column> |
| | | <el-table-column label="æ»ä»·(å
)" |
| | | prop="totalPrice" |
| | | width="150"></el-table-column> |
| | | <!-- <el-table-column fixed="right" |
| | | label="æä½" |
| | | min-width="60" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button link |
| | | type="primary" |
| | | size="small" |
| | | @click="openForm('edit', scope.row, 'production');">ç¼è¾</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> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="åæå
¥åº" |
| | | name="purchase"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | | <el-date-picker v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery"/> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input v-model="searchForm.productCategory" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable/> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px">æç´¢ |
| | | </el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" |
| | | @click="openForm('add', 'purchase')">æ°å¢å
¥åº |
| | | </el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <el-table :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="row => row.id" |
| | | show-summary |
| | | style="width: 100%" |
| | | :summary-method="summarizeMainTable" |
| | | height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" |
| | | type="selection" |
| | | width="55"/> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60"/> |
| | | <el-table-column label="å
¥åºæ¶é´" |
| | | prop="createTime" |
| | | width="100" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="éè´ååå·" |
| | | prop="purchaseContractNumber" |
| | | width="180" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="ä¾åºååç§°" |
| | | prop="supplierName" |
| | | width="240" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="产å大类" |
| | | prop="productCategory" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="è§æ ¼åå·" |
| | | prop="specificationModel" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="åä½" |
| | | prop="unit" |
| | | width="70" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="å
¥åºæ°é" |
| | | prop="inboundNum" |
| | | width="100" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | width="150"></el-table-column> |
| | | <el-table-column label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | width="150"></el-table-column> |
| | | <el-table-column label="å
¥åºäºº" |
| | | prop="createBy" |
| | | width="80" |
| | | show-overflow-tooltip/> |
| | | <el-table-column fixed="right" |
| | | label="æä½" |
| | | min-width="60" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button link |
| | | :disabled="scope.row.type == 1" |
| | | type="primary" |
| | | size="small" |
| | | @click="openForm('edit', scope.row, 'purchase');">ç¼è¾ |
| | | </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> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="ç产å
¥åº" |
| | | name="product"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | | <el-date-picker v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery"/> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input v-model="searchForm.productCategory" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable/> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px">æç´¢ |
| | | </el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" |
| | | @click="openForm('add', 'purchase')">æ°å¢å
¥åº |
| | | </el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <el-table :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="row => row.id" |
| | | show-summary |
| | | style="width: 100%" |
| | | :summary-method="summarizeMainTable" |
| | | height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" |
| | | type="selection" |
| | | width="55"/> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60"/> |
| | | <el-table-column label="å
¥åºæ¶é´" |
| | | prop="createTime" |
| | | width="100" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="产å大类" |
| | | prop="productCategory" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="è§æ ¼åå·" |
| | | prop="specificationModel" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="åä½" |
| | | prop="unit" |
| | | width="220" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="å
¥åºæ°é" |
| | | prop="inboundNum" |
| | | width="220" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="å
¥åºäºº" |
| | | prop="createBy" |
| | | width="220" |
| | | show-overflow-tooltip/> |
| | | </el-table> |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | @pagination="pageProductChange"/> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | <form-dia ref="formDia" |
| | | @close="handleQuery" |
| | | @success="handleQuery"></form-dia> |
| | | <form-dia-product ref="formDiaProduct" |
| | | @close="handleQuery" |
| | | @success="handleQuery"></form-dia-product> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import pagination from '@/components/PIMTable/Pagination.vue' |
| | | import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue' |
| | | import { ElMessageBox } from "element-plus"; |
| | | import useUserStore from '@/store/modules/user' |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import { |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | onMounted, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | } from "vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | import { |
| | | getStockInPage, |
| | | updateStockIn, |
| | | addSutockIn, |
| | | getStockInPageByProduction, |
| | | getStockInPageByProductProduction, |
| | | delStockIn, |
| | | selectProductRecordListByPuechaserId |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | import { purchaseListPage } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | import FormDia from "./components/formDia.vue"; |
| | | import FormDiaProduct from "./components/formDiaProduct.vue"; |
| | | |
| | | const userStore = useUserStore() |
| | | const { proxy } = getCurrentInstance() |
| | | // è·åå½åæ¥æ |
| | | function getCurrentDate() { |
| | | return dayjs().format("YYYY-MM-DD"); |
| | | } |
| | | |
| | | const tableData = ref([]) |
| | | const selectedRows = ref([]) |
| | | const userList = ref([]) |
| | | const {proxy} = getCurrentInstance(); |
| | | |
| | | const purchaseOptions = ref([]) |
| | | const loadingPurchaseOptions = ref(false) |
| | | |
| | | |
| | | const loading = ref(false); |
| | | const tableLoading = ref(false) |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const formDia = ref(); |
| | | const formDiaProduct = ref(); |
| | | const activeTab = ref("production"); // å½åæ¿æ´»ç tab |
| | | |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | }) |
| | | const total = ref(0) |
| | | }); |
| | | const total = ref(0); |
| | | |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const operationType = ref('')// æä½ç±»å: 'add' æ 'edit' |
| | | const dialogFormVisible = ref(false)// å¼¹æ¡æ¾ç¤ºç¶æ |
| | | const productList = ref([]);// 产ååè¡¨æ°æ® |
| | | const loadingProducts = ref(false);// 产åå è½½ç¶æ |
| | | const productSelectedRows = ref([]) // 产åè¡¨æ ¼éä¸è¡ |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplierName: '', |
| | | timeStr: '', |
| | | supplierName: "", |
| | | customerName: "", |
| | | productCategory: "", |
| | | timeStr: "", |
| | | }, |
| | | form: { |
| | | id: null, |
| | | purchaseContractNumber: '', // éè´è®¢åå· |
| | | supplierId: null, // ä¾åºåID |
| | | supplierName: '', // ä¾åºååç§° |
| | | inboundTime: '', // å
¥åºæ¶é´ |
| | | inboundBatch: '', // å
¥åºæ¹æ¬¡ |
| | | recorderId: userStore.userId, // å½å
¥äººID |
| | | recorderName: userStore.name, // å½å
¥äººå§å |
| | | entryDate: getCurrentDate(), // å½å
¥æ¥æ |
| | | remark: '', // 夿³¨ |
| | | }, |
| | | rules: { |
| | | purchaseContractNumber: [{ required: true, message: "请è¾å
¥éè´ååå·", trigger: "blur" }], |
| | | supplierId: [{ required: true, message: "è¯·éæ©ä¾åºå", trigger: "change" }], |
| | | inboundTime: [{ required: true, message: "è¯·éæ©å
¥åºæ¶é´", trigger: "change" }], |
| | | inboundBatch: [{ required: true, message: "请è¾å
¥å
¥åºæ¹æ¬¡", trigger: "blur" }] |
| | | } |
| | | }) |
| | | const { searchForm, form, rules } = toRefs(data) |
| | | |
| | | const formatPurchaseOption = (item = {}) => { |
| | | const contract = item.purchaseContractNumber || '--'; |
| | | const supplier = item.supplierName ? ` · ${item.supplierName}` : ''; |
| | | return `${contract}${supplier}`; |
| | | }; |
| | | |
| | | const loadPurchaseOptions = async (keyword = '') => { |
| | | try { |
| | | loadingPurchaseOptions.value = true; |
| | | const res = await purchaseListPage({ |
| | | current: -1, |
| | | size: -1, |
| | | purchaseContractNumber: keyword, |
| | | }); |
| | | const records = res.data?.records || []; |
| | | purchaseOptions.value = records; |
| | | if ( |
| | | form.value.purchaseContractNumber && |
| | | !purchaseOptions.value.find( |
| | | (item) => item.purchaseContractNumber === form.value.purchaseContractNumber |
| | | ) |
| | | ) { |
| | | purchaseOptions.value.push({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber, |
| | | supplierName: form.value.supplierName, |
| | | supplierId: form.value.supplierId, |
| | | }); |
| | | } |
| | | } finally { |
| | | loadingPurchaseOptions.value = false; |
| | | } |
| | | }; |
| | | |
| | | const handlePurchaseChange = (value) => { |
| | | form.value.purchaseContractNumber = value || ''; |
| | | const matched = purchaseOptions.value.find( |
| | | (item) => item.purchaseContractNumber === value |
| | | ); |
| | | if (matched) { |
| | | form.value.supplierName = matched.supplierName || form.value.supplierName; |
| | | form.value.supplierId = matched.supplierId || form.value.supplierId; |
| | | } |
| | | if (!value) { |
| | | productList.value = []; |
| | | return; |
| | | } |
| | | fetchProductsByContract(); |
| | | }; |
| | | const exceedsAddLimit = (product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | const waiting = Number(product?.quantity0 ?? 0); |
| | | if (!Number.isFinite(stock) || !Number.isFinite(waiting)) { |
| | | return false; |
| | | } |
| | | return stock > waiting; |
| | | }; |
| | | |
| | | const exceedsEditLimit = (product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | const waiting = Number(product?.quantity0 ?? 0); |
| | | const original = Number(product?.originalQuantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || !Number.isFinite(waiting) || !Number.isFinite(original)) { |
| | | return false; |
| | | } |
| | | return stock > waiting + original; |
| | | }; |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | }; |
| | | }); |
| | | const {searchForm} = toRefs(data); |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1 |
| | | getList() |
| | | } |
| | | const paginationChange = (obj) => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const paginationChange = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList() |
| | | } |
| | | getList(); |
| | | }; |
| | | const pageProductChange = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true |
| | | getStockInPage({ ...searchForm.value, ...page }).then(res => { |
| | | tableLoading.value = false |
| | | tableData.value = res.data.records |
| | | total.value = res.data.total |
| | | console.log('tableData:', tableData.value) |
| | | }).catch(() => { |
| | | tableLoading.value = false |
| | | }) |
| | | } |
| | | tableLoading.value = true; |
| | | const params = {...page}; |
| | | |
| | | |
| | | // è°ç¨selectProductRecordListByPuechaserIdè¿ä¸ªæ¹æ³æ ¹æ®ååæ¥è¯¢å°idï¼åè°ç¨getProductRecordByhetongè¿ä¸ªæ¹æ³æ ¹æ®idæ¥è¯¢å°äº§å订åè®°å½ |
| | | // æ°å¢æ ¹æ®ååå·æ¥è¯¢äº§åè®°å½çæ¹æ³ |
| | | const fetchProductsByContract = async () => |
| | | { |
| | | if (!form.value.purchaseContractNumber) { |
| | | proxy.$modal.msgWarning('è¯·éæ©ååå·') |
| | | return |
| | | // æ ¹æ®ä¸åç tab ç±»åä¼ éä¸åçæ¥è¯¢åæ° |
| | | if (activeTab.value === "production") { |
| | | params.customerName = searchForm.value.customerName; |
| | | params.timeStr = searchForm.value.timeStr; |
| | | } else { |
| | | params.supplierName = searchForm.value.supplierName; |
| | | params.timeStr = searchForm.value.timeStr; |
| | | } |
| | | try { |
| | | loadingProducts.value = true |
| | | // æ ¹æ®ååæ¥è¯¢äº§åè®°å½ |
| | | const productRes = await selectProductRecordListByPuechaserId({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber |
| | | }); |
| | | console.log('productRes:', productRes) |
| | | if (!productRes.data || productRes.data.length === 0) { |
| | | proxy.$modal.msgWarning('该åå䏿²¡æäº§åè®°å½') |
| | | productList.value = []; |
| | | return |
| | | } |
| | | // å¤çäº§åæ°æ®ï¼æ·»å æ¬æ¬¡å
¥åºæ°éåæ®µ |
| | | productList.value = productRes.data.map(item => ({ |
| | | ...item, |
| | | quantityStock: 0, |
| | | originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? 0), |
| | | })) |
| | | } catch (error) { |
| | | console.error('æ¥è¯¢äº§åè®°å½å¤±è´¥:', error) |
| | | proxy.$modal.msgError('æ¥è¯¢äº§åè®°å½å¤±è´¥') |
| | | productList.value = []; |
| | | } finally { |
| | | loadingProducts.value = false |
| | | } |
| | | } |
| | | params.productCategory = searchForm.value.productCategory; |
| | | if (activeTab.value === "product") { |
| | | getStockInPageByProductProduction(params) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | }); |
| | | |
| | | }else { |
| | | // æ ¹æ®ä¸åç tab ç±»åè°ç¨ä¸åçæ¥å£ |
| | | const apiCall = |
| | | activeTab.value === "production" |
| | | ? getStockInPageByProduction(params) |
| | | : getStockInPage(params); |
| | | |
| | | apiCall |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | |
| | | // åç«¯è®¡ç®æ»ä»·ï¼æ»ä»· = unitPrice * inboundNum |
| | | tableData.value = tableData.value.map(item => { |
| | | // 使ç¨å
¥åºæ°éè®¡ç®æ»ä»· |
| | | const inboundNum = Number(item.inboundNum) || 0; |
| | | const unitPrice = Number(item.unitPrice) || 0; |
| | | const taxInclusiveUnitPrice = Number(item.taxInclusiveUnitPrice) || 0; |
| | | |
| | | // æ ¹æ®æ ç¾é¡µç±»å计ç®ä¸åçæ»ä»· |
| | | if (activeTab.value === "production") { |
| | | // æååºåï¼æ»ä»· = unitPrice * å
¥åºæ°é |
| | | item.totalPrice = (unitPrice * inboundNum).toFixed(2); |
| | | } else { |
| | | // åæåææåºåï¼å«ç¨æ»ä»· = taxInclusiveUnitPrice * å
¥åºæ°é |
| | | item.taxInclusiveTotalPrice = ( |
| | | taxInclusiveUnitPrice * inboundNum |
| | | ).toFixed(2); |
| | | } |
| | | |
| | | return item; |
| | | }); |
| | | |
| | | total.value = res.data.total; |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | } |
| | | |
| | | }; |
| | | |
| | | // 忢 tab |
| | | const handleTabChange = tabName => { |
| | | page.current = 1; |
| | | // 忢 tab æ¶æ¸
空æç´¢æ¡ä»¶ |
| | | searchForm.value.supplierName = ""; |
| | | searchForm.value.customerName = ""; |
| | | searchForm.value.timeStr = ""; |
| | | searchForm.value.productCategory = ""; |
| | | getList(); |
| | | }; |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = async (type, row) => { |
| | | operationType.value = type |
| | | dialogFormVisible.value = true |
| | | selectedRows.value = [] |
| | | await loadPurchaseOptions(); |
| | | |
| | | if (type === 'add') { |
| | | // æ°å¢æ¶åå§å表å |
| | | form.value = { |
| | | id: null, |
| | | purchaseContractNumber: '', |
| | | supplierId: null, |
| | | supplierName: '', |
| | | inboundTime: '', |
| | | inboundBatch: '', |
| | | recorderId: userStore.userId, |
| | | recorderName: userStore.name, |
| | | entryDate: getCurrentDate(), |
| | | remark: '' |
| | | } |
| | | productList.value = [] // æ¸
空产åå表 |
| | | const openForm = async (type, row, tabType) => { |
| | | const currentTab = tabType || activeTab.value; |
| | | await nextTick(() => { |
| | | if (currentTab === "production") { |
| | | formDiaProduct.value?.openDialog(type, row); |
| | | } else { |
| | | form.value = JSON.parse(JSON.stringify(row)) |
| | | try { |
| | | loadingProducts.value = true |
| | | // æ ¹æ®ååå·å 载对åºç产åå表ï¼å设 getProductByContract æ¯å¯ç¨æ¥å£ï¼ |
| | | const res = await selectProductRecordListByPuechaserId({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber, |
| | | id: row.id |
| | | }); |
| | | productList.value = res.data.map(item => ({ |
| | | ...item, |
| | | quantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0), |
| | | originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0), |
| | | })) |
| | | selectedRows.value = productList.value |
| | | } catch (error) { |
| | | console.error('å 载产å失败:', error) |
| | | proxy.$modal.msgError('å 载产å失败') |
| | | productList.value = [] |
| | | } finally { |
| | | loadingProducts.value = false |
| | | } |
| | | formDia.value?.openDialog(type, row); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const updatePro = async () => { |
| | | // åå¤æäº¤æ°æ® |
| | | // åå¤æäº¤æ°æ® - ä¿®æ¹ä¸ºå端éè¦çæ ¼å¼ |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning('请å
éæ©äº§å'); |
| | | return; |
| | | } |
| | | const target = selectedRows.value[0]; |
| | | const stock = Number(target?.quantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | proxy.$modal.msgWarning('è¯·å¡«åææçå
¥åºæ°é'); |
| | | return; |
| | | } |
| | | if (exceedsEditLimit(target)) { |
| | | proxy.$modal.msgError('æ¬æ¬¡å
¥åºæ°éä¸è½è¶
è¿åå
¥åºæ°éä¸å¾
å
¥åºæ°éä¹å'); |
| | | return; |
| | | } |
| | | const stockInData = { |
| | | id: selectedRows.value[0].recordId, |
| | | quantityStock: Number(selectedRows.value[0].quantityStock),// ä½¿ç¨æ°æ ¼å¼å彿° |
| | | }; |
| | | await updateStockIn(stockInData) |
| | | proxy.$modal.msgSuccess('ä¿®æ¹å
¥åºæå') |
| | | closeDia() |
| | | getList() // å·æ°å表 |
| | | } |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | // éªè¯è³å°éæ©äºä¸ä¸ªäº§å |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning('请å
éæ©éè´ååå¹¶éæ©äº§å') |
| | | return |
| | | } |
| | | if(operationType.value !== 'add'){ |
| | | await updatePro() |
| | | return |
| | | } |
| | | try { |
| | | await proxy.$refs.formRef.validate() |
| | | // éªè¯å
¥åºæ°é |
| | | const invalidProducts = selectedRows.value.filter((product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | return true; |
| | | } |
| | | return exceedsAddLimit(product); |
| | | }) |
| | | |
| | | if (invalidProducts.length > 0) { |
| | | proxy.$modal.msgError('æ¬æ¬¡å
¥åºæ°éé大äº0ï¼ä¸ä¸è½è¶
è¿å¾
å
¥åºæ°é') |
| | | return |
| | | } |
| | | |
| | | // åå¤æäº¤æ°æ® - ä¿®æ¹ä¸ºå端éè¦çæ ¼å¼ |
| | | const stockInData = { |
| | | // å
¥åºååºæ¬ä¿¡æ¯ |
| | | ...form.value, |
| | | inboundTime: formatDateTime(form.value.inboundTime), |
| | | nickName: userStore.nickName, |
| | | details: selectedRows.value.map(product => ({ |
| | | id: product.id, |
| | | // id: product.salesLedgerProductId, |
| | | inboundQuantity: Number(product.quantityStock) |
| | | })), |
| | | }; |
| | | // è°ç¨API |
| | | loading.value = true |
| | | await addSutockIn(stockInData) |
| | | |
| | | proxy.$modal.msgSuccess('æ°å¢å
¥åºæå') |
| | | closeDia() |
| | | getList() // å·æ°å表 |
| | | |
| | | } catch (error) { |
| | | console.error('æäº¤å¤±è´¥:', error) |
| | | if (!error.errors) { |
| | | proxy.$modal.msgError('æä½å¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.$refs.formRef.resetFields() |
| | | dialogFormVisible.value = false |
| | | |
| | | } |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | // è¿æ»¤æåæ°æ® |
| | | selectedRows.value = selection.filter(item => item.id); |
| | | } |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection.filter(item => item.id); |
| | | }; |
| | | |
| | | const expandedRowKeys = ref([]) |
| | | const expandedRowKeys = ref([]); |
| | | |
| | | // 主表åè®¡æ¹æ³ |
| | | const summarizeMainTable = (param) => { |
| | | return proxy.summarizeTable(param, ['contractAmount', 'taxInclusiveTotalPrice', 'taxExclusiveTotalPrice']); |
| | | }; |
| | | const summarizeMainTable = param => { |
| | | return proxy.summarizeTable(param, [ |
| | | "contractAmount", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | ]); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm( |
| | | 'æ¯å¦ç¡®è®¤å¯¼åºï¼', |
| | | '导åº', { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning', |
| | | } |
| | | ).then(() => { |
| | | proxy.download("/stockin/export", {}, 'å
¥åºå°è´¦.xlsx') |
| | | }).catch(() => { |
| | | proxy.$modal.msg("已忶") |
| | | }) |
| | | } |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | let ids = [] |
| | | if (selectedRows.value.length > 0) { |
| | | // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® |
| | | const unauthorizedData = selectedRows.value.filter(item => item.createUser !== userStore.id); |
| | | if (unauthorizedData.length > 0) { |
| | | proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); |
| | | return; |
| | | } |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning('è¯·éæ©æ°æ®') |
| | | return |
| | | } |
| | | ElMessageBox.confirm( |
| | | 'éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼', |
| | | '导åº', { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning', |
| | | } |
| | | ).then(() => { |
| | | delStockIn({ids:ids}).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å") |
| | | getList() |
| | | }) |
| | | }).catch(() => { |
| | | proxy.$modal.msg("已忶") |
| | | }) |
| | | } |
| | | |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | // ä¿®æ¹ä¸ºæ´éç¨çæ¥ææ¶é´æ ¼å¼å彿° |
| | | function formatDateTime(date = new Date(), includeTime = true) { |
| | | const d = new Date(date); |
| | | const year = d.getFullYear(); |
| | | const month = String(d.getMonth() + 1).padStart(2, '0'); |
| | | const day = String(d.getDate()).padStart(2, '0'); |
| | | |
| | | if (!includeTime) { |
| | | return `${year}-${month}-${day}`; // ä¿æåæ getCurrentDate åè½ |
| | | } |
| | | |
| | | // æ°å¢æ¶é´é¨åæ ¼å¼å |
| | | const hours = String(d.getHours()).padStart(2, '0'); |
| | | const minutes = String(d.getMinutes()).padStart(2, '0'); |
| | | const seconds = String(d.getSeconds()).padStart(2, '0'); |
| | | |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | // æ ¹æ®ä¸åç tab ç±»åè°ç¨ä¸åçå¯¼åºæ¥å£ |
| | | let exportUrl = "/stockin/export"; |
| | | if (activeTab.value === "production") { |
| | | exportUrl = "/stockin/exportOne"; |
| | | } |
| | | proxy.download(exportUrl, {}, "å
¥åºå°è´¦.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | const ids = selectedRows.value.map(item => item.id); |
| | | |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | // æ ¹æ®å½å tab ç±»åéæ©ä¸åçå 餿¥å£åtypeåæ° |
| | | let deleteApi, deleteParams; |
| | | |
| | | if (activeTab.value === "production") { |
| | | // æåå é¤ï¼typeä¼ 2 |
| | | deleteApi = delStockIn; |
| | | deleteParams = {ids, type: 2}; |
| | | } else { |
| | | // åæå é¤ï¼typeä¼ 1 |
| | | deleteApi = delStockIn; |
| | | deleteParams = {ids, type: 1}; |
| | | } |
| | | |
| | | deleteApi(deleteParams) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("å é¤å¤±è´¥"); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"></style> |
| | | |
| | | |
| | | |
| | |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import {ref,onMounted} from "vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; |
| | | import {deepCopySameProperties} from '@/utils/util' |
| | | const userStore = useUserStore(); |
| | | import { |
| | | getDept |
| | | } from "@/api/collaborativeApproval/approvalProcess.js"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | |
| | |
| | | issueDate: undefined, |
| | | }); |
| | | const getPersonList = () => { |
| | | getStaffOnJob().then(res => { |
| | | personList.value = res.data |
| | | staffOnJobListPage({ |
| | | current: -1, |
| | | size: -1, |
| | | staffState: 1 |
| | | }).then(res => { |
| | | personList.value = res.data.records |
| | | }) |
| | | }; |
| | | const loadForm = (data) => { |
| | |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <Files ref="filesDia"></Files> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {staffOnJobInfo} from "@/api/personnelManagement/staffOnJob.js"; |
| | | import {findStaffContractListPage} from "@/api/personnelManagement/staffContract.js"; |
| | | const Files = defineAsyncComponent(() => import( "@/views/personnelManagement/contractManagement/filesDia.vue")); |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | | const filesDia = ref() |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const tableColumn = ref([ |
| | | // { |
| | | // label: "ååå¹´é", |
| | | // prop: "contractTerm", |
| | | // }, |
| | | { |
| | | label: "ååå¹´é", |
| | | prop: "contractTerm", |
| | | }, |
| | | { |
| | | label: "ååå¼å§æ¥æ", |
| | | prop: "contractStartTime", |
| | |
| | | { |
| | | label: "ååç»ææ¥æ", |
| | | prop: "contractEndTime", |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | width: 120, |
| | | operation: [ |
| | | { |
| | | name: "ä¸ä¼ éä»¶", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | filesDia.value.openDialog( row,'åå') |
| | | }, |
| | | } |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | |
| | | } |
| | | } |
| | | |
| | | const openUploadFile = (row) => { |
| | | filesDia.value.open = true |
| | | filesDia.value.row = row |
| | | } |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | dialogFormVisible.value = false; |
| | |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | height="500" |
| | | @pagination="paginationSearch" |
| | | :total="page.total" |
| | | > |
| | | </PIMTable> |
| | | <pagination |
| | | style="margin: 10px 0" |
| | | v-show="total > 0" |
| | | @pagination="paginationSearch" |
| | | :total="total" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/staff/staffOnJob/export", {}, "åå管ç.xlsx"); |
| | | proxy.download("/staff/staffOnJob/export", {staffState: 1}, "åå管ç.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | |
| | | <el-form :model="form" label-width="200px" label-position="left" :rules="rules" ref="formRef" style="margin-top: 20px"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å§åï¼" prop="staffName"> |
| | | <el-select v-model="form.staffName" placeholder="è¯·éæ©äººå" style="width: 100%" @change="handleSelect"> |
| | | <el-form-item label="å§åï¼" prop="staffOnJobId"> |
| | | <el-select v-model="form.staffOnJobId" |
| | | placeholder="è¯·éæ©äººå" |
| | | style="width: 100%" |
| | | :disabled="operationType === 'edit'" |
| | | @change="handleSelect"> |
| | | <el-option |
| | | v-for="item in personList" |
| | | :key="item.id" |
| | | :label="item.staffName" |
| | | :value="item.staffName" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åå·¥ç¼å·ï¼"> |
| | | {{ form.staffNo || '-' }} |
| | | {{ currentStaffRecord.staffNo || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ§å«ï¼"> |
| | | {{ form.sex || '-' }} |
| | | {{ currentStaffRecord.sex || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ·ç±ä½åï¼"> |
| | | {{ form.nativePlace || '-' }} |
| | | {{ currentStaffRecord.nativePlace || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å²ä½ï¼"> |
| | | {{ form.postName || '-' }} |
| | | {{ currentStaffRecord.postName || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç°ä½åï¼"> |
| | | {{ form.adress || '-' }} |
| | | {{ currentStaffRecord.adress || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="第ä¸å¦åï¼"> |
| | | {{ form.firstStudy || '-' }} |
| | | {{ currentStaffRecord.firstStudy || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸ä¸ï¼"> |
| | | {{ form.profession || '-' }} |
| | | {{ currentStaffRecord.profession || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¹´é¾ï¼"> |
| | | {{ form.age || '-' }} |
| | | {{ currentStaffRecord.age || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="èç³»çµè¯ï¼"> |
| | | {{ form.phone || '-' }} |
| | | {{ currentStaffRecord.phone || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç´§æ¥è系人ï¼"> |
| | | {{ form.emergencyContact || '-' }} |
| | | {{ currentStaffRecord.emergencyContact || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç´§æ¥è系人èç³»çµè¯ï¼"> |
| | | {{ form.emergencyContactPhone || '-' }} |
| | | {{ currentStaffRecord.emergencyContactPhone || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ååå¼å§æ¥æï¼"> |
| | | {{ form.contractStartTime || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ååç»ææ¥æï¼"> |
| | | {{ form.contractEndTime || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="离èåå ï¼" prop="dimissionReason"> |
| | | <el-select v-model="form.dimissionReason" placeholder="è¯·éæ©ç¦»èåå " style="width: 100%" @change="handleSelectDimissionReason"> |
| | | <el-form-item label="离èåå ï¼" prop="reason"> |
| | | <el-select v-model="form.reason" placeholder="è¯·éæ©ç¦»èåå " style="width: 100%" @change="handleSelectDimissionReason"> |
| | | <el-option |
| | | v-for="(item, index) in dimissionReasonOptions" |
| | | :key="index" |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="夿³¨ï¼" prop="dimissionRemark" v-show="form.dimissionReason === 'other'"> |
| | | <el-form-item label="夿³¨ï¼" prop="remark" v-if="form.reason === 'other'"> |
| | | <el-input |
| | | v-model="form.dimissionRemark" |
| | | v-model="form.remark" |
| | | type="textarea" |
| | | v-show="form.dimissionReason === 'other'" |
| | | :rows="3" |
| | | placeholder="夿³¨" |
| | | maxlength="500" |
| | |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <div class="info-item">--> |
| | | <!-- <span class="info-label">离èåå ï¼</span>--> |
| | | <!-- <el-select v-model="form.dimissionReason" placeholder="è¯·éæ©äººå" style="width: 100%" @change="handleSelect">--> |
| | | <!-- <el-select v-model="form.reason" placeholder="è¯·éæ©äººå" style="width: 100%" @change="handleSelect">--> |
| | | <!-- <el-option--> |
| | | <!-- v-for="(item, index) in dimissionReasonOptions"--> |
| | | <!-- :key="index"--> |
| | |
| | | |
| | | <script setup> |
| | | import {ref, reactive, toRefs, getCurrentInstance} from "vue"; |
| | | import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | import { staffOnJobListPage } from "@/api/personnelManagement/staffOnJob.js"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | import {createStaffLeave, updateStaffLeave} from "@/api/personnelManagement/staffLeave.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | |
| | | const operationType = ref('') |
| | | const data = reactive({ |
| | | form: { |
| | | staffNo: "", |
| | | staffName: "", |
| | | sex: "", |
| | | nativePlace: "", |
| | | postName: "", |
| | | sysPostId: 0, |
| | | adress: "", |
| | | firstStudy: "", |
| | | profession: "", |
| | | age: 0, |
| | | phone: "", |
| | | emergencyContact: "", |
| | | emergencyContactPhone: "", |
| | | contractTerm: 0, |
| | | contractStartTime: "", |
| | | contractEndTime: "", |
| | | dimissionDate: "", |
| | | dimissionReason: "", |
| | | dimissionRemark: "", |
| | | staffState: "", |
| | | staffOnJobId: undefined, |
| | | reason: "", |
| | | remark: "", |
| | | }, |
| | | rules: { |
| | | staffName: [{ required: true, message: "è¯·éæ©äººå" }], |
| | | dimissionReason: [{ required: true, message: "è¯·éæ©ç¦»èåå "}], |
| | | reason: [{ required: true, message: "è¯·éæ©ç¦»èåå "}], |
| | | }, |
| | | dimissionReasonOptions: [ |
| | | {label: 'èªèµå¾
é', value: 'salary'}, |
| | |
| | | {label: 'å·¥ä½ç¯å¢', value: 'work_environment'}, |
| | | {label: '个人åå ', value: 'personal_reason'}, |
| | | {label: 'å
¶ä»', value: 'other'}, |
| | | ] |
| | | ], |
| | | currentStaffRecord: {}, |
| | | }); |
| | | const { form, rules, dimissionReasonOptions } = toRefs(data); |
| | | const { form, rules, dimissionReasonOptions, currentStaffRecord } = toRefs(data); |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | getList() |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | if (operationType.value === 'edit') { |
| | | getStaffJoinInfo(row.id).then(res => { |
| | | form.value = {...res.data} |
| | | }) |
| | | currentStaffRecord.value = row |
| | | form.value.staffOnJobId = row.staffOnJobId |
| | | form.value.reason = row.reason |
| | | form.value.remark = row.remark |
| | | personList.value = [ |
| | | { |
| | | staffName: row.staffName, |
| | | id: row.staffOnJobId, |
| | | } |
| | | ] |
| | | } else { |
| | | getList() |
| | | } |
| | | } |
| | | |
| | | const handleSelectDimissionReason = (val) => { |
| | | if (val === 'other') { |
| | | form.value.dimissionRemark = '' |
| | | form.value.remark = '' |
| | | } |
| | | } |
| | | // æäº¤äº§å表å |
| | | const submitForm = () => { |
| | | form.value.staffState = 0 |
| | | if (form.value.dimissionReason !== 'other') { |
| | | form.value.dimissionRemark = '' |
| | | } |
| | | if (!form.value.sysPostId) { |
| | | form.value.sysPostId = 0; |
| | | if (form.value.reason !== 'other') { |
| | | form.value.remark = '' |
| | | } |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | if (operationType.value === "add") { |
| | | staffJoinAdd(form.value).then(res => { |
| | | createStaffLeave(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }) |
| | | } else { |
| | | staffJoinUpdate(form.value).then(res => { |
| | | updateStaffLeave(currentStaffRecord.value.id, form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }) |
| | |
| | | const closeDia = () => { |
| | | // 表å已注éï¼æå¨éç½®è¡¨åæ°æ® |
| | | form.value = { |
| | | staffNo: "", |
| | | staffName: "", |
| | | sex: "", |
| | | nativePlace: "", |
| | | postName: "", |
| | | sysPostId: 0, |
| | | adress: "", |
| | | firstStudy: "", |
| | | profession: "", |
| | | age: 0, |
| | | phone: "", |
| | | emergencyContact: "", |
| | | emergencyContactPhone: "", |
| | | contractTerm: 0, |
| | | contractStartTime: "", |
| | | contractEndTime: "", |
| | | dimissionDate: "", |
| | | dimissionReason: "", |
| | | staffState: "", |
| | | staffOnJobId: undefined, |
| | | reason: "", |
| | | remark: "", |
| | | }; |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | |
| | | }; |
| | | |
| | | const handleSelect = (val) => { |
| | | let obj = personList.value.find(item => item.staffName === val) |
| | | let obj = personList.value.find(item => item.id === val) |
| | | currentStaffRecord.value = {} |
| | | if (obj) { |
| | | let { |
| | | sex, |
| | | phone, |
| | | staffNo, |
| | | nativePlace, |
| | | postName, |
| | | sysPostId, |
| | | adress, |
| | | firstStudy, |
| | | profession, |
| | | age, |
| | | emergencyContact, |
| | | emergencyContactPhone, |
| | | contractTerm, |
| | | contractStartTime, |
| | | contractEndTime, |
| | | staffName |
| | | } = obj |
| | | // ä¿çç¦»èæ¥æå离èåå ï¼åªæ´æ°åå·¥ä¿¡æ¯ |
| | | form.value = { |
| | | ...form.value, |
| | | sex, |
| | | phone, |
| | | staffNo, |
| | | nativePlace, |
| | | postName, |
| | | sysPostId, |
| | | adress, |
| | | firstStudy, |
| | | profession, |
| | | age, |
| | | emergencyContact, |
| | | emergencyContactPhone, |
| | | contractTerm, |
| | | contractStartTime, |
| | | contractEndTime, |
| | | staffName |
| | | } |
| | | currentStaffRecord.value = obj |
| | | } |
| | | } |
| | | defineExpose({ |
| | |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <span style="margin-left: 10px;" class="search_title">ååå¼å§æ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.entryDateStart" |
| | | type="date" |
| | | placeholder="è¯·éæ©ååå¼å§æ¥æ" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,1)" |
| | | /> |
| | | <span style="margin-left: 10px;" class="search_title">ååç»ææ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.entryDateEnd" |
| | | type="date" |
| | | placeholder="è¯·éæ©ååç»ææ¥æ" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,2)" |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import {onMounted, ref} from "vue"; |
| | | import FormDia from "@/views/personnelManagement/dimission/components/formDia.vue"; |
| | | import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js"; |
| | | import {findStaffLeaveListPage, batchDeleteStaffLeaves} from "@/api/personnelManagement/staffLeave.js"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | |
| | | prop: "nativePlace", |
| | | }, |
| | | { |
| | | label: "é¨é¨", |
| | | prop: "deptName", |
| | | }, |
| | | { |
| | | label: "å²ä½", |
| | | prop: "postName", |
| | | }, |
| | |
| | | prop: "emergencyContactPhone", |
| | | width:150 |
| | | }, |
| | | // { |
| | | // label: "ååå¹´é", |
| | | // prop: "contractTerm", |
| | | // }, |
| | | { |
| | | label: "ååå¼å§æ¥æ", |
| | | prop: "contractStartTime", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "ååç»ææ¥æ", |
| | | prop: "contractEndTime", |
| | | width: 120 |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | |
| | | const handleDateChange = (value,type) => { |
| | | searchForm.value.entryDateEnd = null |
| | | searchForm.value.entryDateStart = null |
| | | if(type === 1){ |
| | | if (value) { |
| | | searchForm.value.entryDateStart = dayjs(value).format("YYYY-MM-DD"); |
| | | } |
| | | }else{ |
| | | if (value) { |
| | | searchForm.value.entryDateEnd = dayjs(value).format("YYYY-MM-DD"); |
| | | } |
| | | } |
| | | getList(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | staffJoinListPage({...page, ...searchForm.value, staffState: 0}).then(res => { |
| | | findStaffLeaveListPage({...page, ...searchForm.value}).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | page.total = res.data.total; |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | staffJoinDel(ids).then((res) => { |
| | | batchDeleteStaffLeaves(ids).then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/staff/staffJoinLeaveRecord/export", {staffState: 0}, "人å离è.xlsx"); |
| | | proxy.download("/staff/staffLeave/export", {}, "人å离è.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¨é¨ï¼" prop="sysDeptId"> |
| | | <el-tree-select |
| | | v-model="form.sysDeptId" |
| | | :data="deptOptions" |
| | | :props="{ value: 'id', label: 'label', children: 'children' }" |
| | | value-key="id" |
| | | placeholder="è¯·éæ©é¨é¨" |
| | | check-strictly |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¹´é¾ï¼" prop="age"> |
| | | <el-input-number v-model="form.age" :precision="0" :step="1" style="width: 100%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="第ä¸å¦åï¼" prop="firstStudy"> |
| | | <el-input v-model="form.firstStudy" placeholder="请è¾å
¥" clearable/> |
| | | </el-form-item> |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸ä¸ï¼" prop="profession"> |
| | | <el-input v-model="form.profession" placeholder="请è¾å
¥" clearable/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¹´é¾ï¼" prop="age"> |
| | | <el-input-number v-model="form.age" :precision="0" :step="1" style="width: 100%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | |
| | | <script setup> |
| | | import {ref, onMounted} from "vue"; |
| | | import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | import {findPostOptions} from "@/api/system/post.js"; |
| | | import {listDept} from "@/api/system/dept.js"; |
| | | import {staffOnJobInfo, createStaffOnJob, updateStaffOnJob} from "@/api/personnelManagement/staffOnJob.js"; |
| | | import {deptTreeSelect} from "@/api/system/user.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | |
| | | contractEndTime: "", |
| | | staffState: "", |
| | | sysPostId: undefined, |
| | | sysDeptId: undefined, |
| | | }, |
| | | rules: { |
| | | staffNo: [{ required: true, message: "请è¾å
¥", trigger: "blur" },], |
| | |
| | | contractEndTime: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | }, |
| | | postOptions: [], // å²ä½é项 |
| | | deptOptions: [], // é¨é¨é项 |
| | | }); |
| | | const { form, rules, postOptions } = toRefs(data); |
| | | const { form, rules, postOptions, deptOptions } = toRefs(data); |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | |
| | | } |
| | | onMounted(() => { |
| | | fetchPostOptions() |
| | | fetchDeptOptions() |
| | | }) |
| | | |
| | | const fetchPostOptions = () => { |
| | |
| | | postOptions.value = res.data |
| | | }) |
| | | } |
| | | |
| | | // æ¥è¯¢é¨é¨å表 |
| | | const fetchDeptOptions = () => { |
| | | deptTreeSelect().then(response => { |
| | | deptOptions.value = filterDisabledDept(JSON.parse(JSON.stringify(response.data))) |
| | | }) |
| | | } |
| | | |
| | | /** è¿æ»¤ç¦ç¨çé¨é¨ */ |
| | | function filterDisabledDept(deptList) { |
| | | return deptList.filter(dept => { |
| | | if (dept.disabled) { |
| | | return false |
| | | } |
| | | if (dept.children && dept.children.length) { |
| | | dept.children = filterDisabledDept(dept.children) |
| | | } |
| | | return true |
| | | }) |
| | | } |
| | | |
| | | // æäº¤äº§å表å |
| | | const submitForm = () => { |
| | | if (!form.value.sysPostId) { |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="ç»ç¾åå" |
| | | width="800px" |
| | | @close="closeModal" |
| | | > |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-form-item label="ååå¼å§æ¥æï¼" prop="contractStartTime"> |
| | | <el-date-picker |
| | | v-model="form.contractStartTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="calculateContractTerm" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ååç»ææ¥æï¼" prop="contractEndTime"> |
| | | <el-date-picker |
| | | v-model="form.contractEndTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="calculateContractTerm" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ååå¹´éï¼" prop="contractTerm"> |
| | | <el-input-number v-model="form.contractTerm" :precision="0" :step="1" style="width: 100%" :disabled="true"/> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | // ç»ç¾åå |
| | | import { renewContract } from "@/api/personnelManagement/staffOnJob.js"; |
| | | import {computed, getCurrentInstance,} from "vue"; |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | contractTerm: 0, |
| | | contractStartTime: "", |
| | | contractEndTime: "", |
| | | }, |
| | | rules: { |
| | | contractTerm: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | contractStartTime: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | contractEndTime: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | } |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | let { proxy } = getCurrentInstance() |
| | | |
| | | const props = defineProps({ |
| | | id: { |
| | | type: Number, |
| | | default: 0, |
| | | }, |
| | | |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | }) |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | }, |
| | | }); |
| | | |
| | | // 计ç®ååå¹´é |
| | | const calculateContractTerm = () => { |
| | | if (form.value.contractStartTime && form.value.contractEndTime) { |
| | | const startDate = new Date(form.value.contractStartTime); |
| | | const endDate = new Date(form.value.contractEndTime); |
| | | |
| | | if (endDate > startDate) { |
| | | // 计ç®å¹´ä»½å·® |
| | | const yearDiff = endDate.getFullYear() - startDate.getFullYear(); |
| | | const monthDiff = endDate.getMonth() - startDate.getMonth(); |
| | | const dayDiff = endDate.getDate() - startDate.getDate(); |
| | | |
| | | let years = yearDiff; |
| | | |
| | | // å¦æç»ææ¥æçææ¥å°äºå¼å§æ¥æçææ¥ï¼ååå»1å¹´ |
| | | if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) { |
| | | years = yearDiff - 1; |
| | | } |
| | | |
| | | form.value.contractTerm = Math.max(0, years); |
| | | } else { |
| | | form.value.contractTerm = 0; |
| | | } |
| | | } else { |
| | | form.value.contractTerm = 0; |
| | | } |
| | | }; |
| | | |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | renewContract(props.id, form.value).then(res => { |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("ç»ç¾ååæå"); |
| | | emit('completed'); |
| | | closeModal(); |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeModal = () => { |
| | | // éç½®è¡¨åæ°æ® |
| | | form.value = { |
| | | contractTerm: 0, |
| | | contractStartTime: "", |
| | | contractEndTime: "", |
| | | }; |
| | | isShow.value = false; |
| | | }; |
| | | </script> |
| | |
| | | </div> |
| | | <show-form-dia ref="formDia" @close="handleQuery"></show-form-dia> |
| | | <new-or-edit-form-dia ref="formDiaNewOrEditFormDia" @close="handleQuery"></new-or-edit-form-dia> |
| | | <renew-contract |
| | | v-if="isShowRenewContractModal" |
| | | v-model:visible="isShowRenewContractModal" |
| | | :id="id" |
| | | @completed="handleQuery" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import {ElMessageBox} from "element-plus"; |
| | | import {batchDeleteStaffOnJobs, staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | const NewOrEditFormDia = defineAsyncComponent(() => import("@/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue")); |
| | | const ShowFormDia = defineAsyncComponent(() => import( "@/views/personnelManagement/employeeRecord/components/Show.vue")); |
| | | const RenewContract = defineAsyncComponent(() => import( "@/views/personnelManagement/employeeRecord/components/RenewContract.vue")); |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const isShowRenewContractModal = ref(false); |
| | | const id = ref(0); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ç¶æ", |
| | |
| | | { |
| | | label: "æ·ç±ä½å", |
| | | prop: "nativePlace", |
| | | }, |
| | | { |
| | | label: "é¨é¨", |
| | | prop: "deptName", |
| | | }, |
| | | { |
| | | label: "å²ä½", |
| | |
| | | openFormNewOrEditFormDia("edit", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "ç»ç¾åå", |
| | | type: "text", |
| | | showHide: row => row.staffState === 1, |
| | | clickFun: (row) => { |
| | | isShowRenewContractModal.value = true; |
| | | id.value = row.id; |
| | | }, |
| | | }, |
| | | // { |
| | | // name: "详æ
", |
| | | // type: "text", |
| | |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined |
| | | staffOnJobListPage({...params, staffState: 1}).then(res => { |
| | | staffOnJobListPage({...params}).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | page.total = res.data.total; |
| | |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {getStaffJoinInfo, getStaffOnJob, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | import {compensationAdd, compensationUpdate} from "@/api/personnelManagement/payrollManagement.js"; |
| | | import {staffOnJobInfo, staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | getStaffOnJob().then(res => { |
| | | personList.value = res.data |
| | | }) |
| | | staffOnJobListPage({ |
| | | current: -1, |
| | | size: -1, |
| | | staffState: 1 |
| | | }).then(res => { |
| | | personList.value = res.data.records || [] |
| | | }) |
| | | form.value = {} |
| | | if (operationType.value === 'edit') { |
| | | getStaffJoinInfo(row.id).then(res => { |
| | | staffOnJobInfo(row.staffId).then(res => { |
| | | form.value = {...row} |
| | | form.value.payDate = form.value.payDate + '-01' |
| | | }) |
| | |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue"; |
| | | import FormDia from "@/views/personnelManagement/payrollManagement/components/formDia.vue"; |
| | | import {staffJoinDel} from "@/api/personnelManagement/onboarding.js"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import {compensationDelete, compensationListPage} from "@/api/personnelManagement/payrollManagement.js"; |
| | |
| | | import {useDict} from "@/utils/dict.js" |
| | | import {Plus, Download, Search, Refresh} from '@element-plus/icons-vue' |
| | | import {save, del, delByIds, listPage} from "@/api/personnelManagement/scheduling.js" |
| | | import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; |
| | | import dayjs from "dayjs"; |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | |
| | | * è·åå½åå¨è人åå表 |
| | | */ |
| | | const getPersonList = () => { |
| | | getStaffOnJob().then(res => { |
| | | personList.value = res.data |
| | | staffOnJobListPage({ |
| | | current: -1, |
| | | size: -1, |
| | | staffState: 1 |
| | | }).then(res => { |
| | | personList.value = res.data.records || [] |
| | | }) |
| | | }; |
| | | const paginationChange = (obj) => { |
| | |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | import { getUserProfile } from '@/api/system/user.js' |
| | | import {staffJoinUpdate, staffJoinListPage} from "@/api/personnelManagement/onboarding.js"; |
| | | import { fa, id } from 'element-plus/es/locales.mjs' |
| | | import {staffOnJobListPage, updateStaffOnJob} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | const tableLoading = ref(false) |
| | | // å页忰 |
| | |
| | | currentUser.value = res.data |
| | | // console.log("----",currentUser.value) |
| | | //å¾å°äººåå表 |
| | | staffJoinListPage({staffState: 1}).then(res => { |
| | | staffOnJobListPage({staffState: 1}).then(res => { |
| | | //çéåºåcurrentUserååç人å |
| | | // let tableData = res.data.records |
| | | user.value = res.data.records.find(item => item.staffName === currentUser.value.userName) |
| | |
| | | const userRes = await getUserProfile(); |
| | | if (userRes.code === 200) { |
| | | currentUser.value = userRes.data; |
| | | const staffListRes = await staffJoinListPage({ staffState: 1 }); |
| | | const staffListRes = await staffOnJobListPage({ staffState: 1 }); |
| | | user.value = staffListRes.data.records.find(item => item.staffName === currentUser.value.userName); |
| | | // console.log("++++", user.value); |
| | | |
| | | Object.assign(joinForm, user.value); |
| | | joinForm.staffName = profileForm.name; |
| | | joinForm.phone = profileForm.phone; |
| | | joinForm.email = profileForm.email; |
| | | joinForm.adress = profileForm.adress; |
| | | console.log(joinForm) |
| | | // è°ç¨æ´æ°ä¸ªäººä¿¡æ¯çæ¥å£ |
| | | staffJoinUpdate(joinForm).then(res => { |
| | | updateStaffOnJob(user.value.id, joinForm).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success('个人信æ¯ä¿åæå'); |
| | | getProfile(); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog v-model="dialogVisible" title="éä»¶" width="40%" :before-close="handleClose"> |
| | | <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 { ElMessageBox, ElMessage } from 'element-plus' |
| | | import filePreview from '@/components/filePreview/index.vue' |
| | | 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(() => { |
| | | proxy.$modal.msg('已忶å é¤') |
| | | }) |
| | | } |
| | | defineExpose({ |
| | | open |
| | | }) |
| | | </script> |
| | | |
| | | <style></style> |
| | |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <el-form :model="searchForm" :inline="true"> |
| | | <el-form :model="searchForm" |
| | | :inline="true"> |
| | | <el-form-item label="ä¾åºååç§°ï¼"> |
| | | <el-input v-model="searchForm.supplierName" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | <el-input v-model="searchForm.supplierName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="éè´ååå·ï¼"> |
| | | <el-input |
| | | v-model="searchForm.purchaseContractNumber" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <el-input v-model="searchForm.purchaseContractNumber" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | </el-form-item> |
| | | <el-form-item label="éå®ååå·ï¼"> |
| | | <el-input v-model="searchForm.salesContractNo" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | <el-input v-model="searchForm.salesContractNo" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="项ç®åç§°ï¼"> |
| | | <el-input v-model="searchForm.projectName" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | <el-input v-model="searchForm.projectName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="å½å
¥æ¥æï¼"> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="è¯·éæ©" clearable @change="changeDaterange" /> |
| | | <el-date-picker v-model="searchForm.entryDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="daterange" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="changeDaterange" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery"> æç´¢ </el-button> |
| | | <el-button type="primary" |
| | | @click="handleQuery"> æç´¢ </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | </div> |
| | | <div class="table_list"> |
| | | <div style="display: flex;justify-content: flex-end;margin-bottom: 20px;"> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢å°è´¦</el-button> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">æ°å¢å°è´¦</el-button> |
| | | <el-button type="success" |
| | | @click="openScanAddDialog">æ«ç æ°å¢</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | <el-table |
| | | :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="(row) => row.id" |
| | | show-summary |
| | | :summary-method="summarizeMainTable" |
| | | @expand-change="expandChange" |
| | | height="calc(100vh - 22em)" |
| | | :row-class-name="tableRowClassName" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="(row) => row.id" |
| | | show-summary |
| | | :summary-method="summarizeMainTable" |
| | | @expand-change="expandChange" |
| | | height="calc(100vh - 19em)" |
| | | :row-class-name="tableRowClassName"> |
| | | <el-table-column align="center" |
| | | type="selection" |
| | | width="55" /> |
| | | <el-table-column type="expand"> |
| | | <template #default="props"> |
| | | <el-table |
| | | :data="props.row.children" |
| | | border |
| | | show-summary |
| | | :summary-method="summarizeChildrenTable" |
| | | > |
| | | <el-table-column |
| | | align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" /> |
| | | <el-table-column label="åä½" prop="unit" /> |
| | | <el-table-column label="æ°é" prop="quantity" /> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" /> |
| | | <el-table-column |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table :data="props.row.children" |
| | | border |
| | | show-summary |
| | | :summary-method="summarizeChildrenTable"> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" /> |
| | | <el-table-column label="产å大类" |
| | | prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" |
| | | prop="specificationModel" /> |
| | | <el-table-column label="åä½" |
| | | prop="unit" /> |
| | | <el-table-column label="æ°é" |
| | | prop="quantity" /> |
| | | <el-table-column label="ç¨ç(%)" |
| | | prop="taxRate" /> |
| | | <el-table-column label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" /> |
| | | <el-table-column label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" /> |
| | | <el-table-column label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" /> |
| | | </el-table> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column |
| | | label="éè´ååå·" |
| | | prop="purchaseContractNumber" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="éå®ååå·" |
| | | prop="salesContractNo" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="ä¾åºååç§°" |
| | | width="240" |
| | | prop="supplierName" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column label="订åç¶æ" width="100" align="center"> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" /> |
| | | <el-table-column label="éè´ååå·" |
| | | prop="purchaseContractNumber" |
| | | width="200" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="éå®ååå·" |
| | | prop="salesContractNo" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="ä¾åºååç§°" |
| | | prop="supplierName" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="订åç¶æ" |
| | | width="100" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-tag v-if="scope.row.isInvalid" type="danger" size="small">失æ</el-tag> |
| | | <el-tag v-else type="success" size="small">æ£å¸¸</el-tag> |
| | | <el-tag v-if="scope.row.isInvalid" |
| | | type="danger" |
| | | size="small">失æ</el-tag> |
| | | <el-tag v-else |
| | | type="success" |
| | | size="small">æ£å¸¸</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="项ç®åç§°" |
| | | prop="projectName" |
| | | width="420" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="审æ¹ç¶æ" |
| | | prop="approvalStatus" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | > |
| | | <el-table-column label="项ç®åç§°" |
| | | prop="projectName" |
| | | width="420" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="审æ¹ç¶æ" |
| | | prop="approvalStatus" |
| | | width="200" |
| | | show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | size="small" |
| | | > |
| | | <el-tag size="small"> |
| | | {{ approvalStatusText[scope.row.approvalStatus] || 'æªç¥ç¶æ' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="仿¬¾æ¹å¼" |
| | | width="100" |
| | | prop="paymentMethod" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="ååéé¢(å
)" |
| | | prop="contractAmount" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="å½å
¥äºº" |
| | | prop="recorderName" |
| | | width="100" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="å½å
¥æ¥æ" |
| | | prop="entryDate" |
| | | width="100" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | fixed="right" |
| | | label="æä½" |
| | | width="100" |
| | | align="center" |
| | | > |
| | | <el-table-column label="ç¾è®¢æ¥æ" |
| | | prop="executionDate" |
| | | width="100" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="仿¬¾æ¹å¼" |
| | | width="100" |
| | | prop="paymentMethod" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="ååéé¢(å
)" |
| | | prop="contractAmount" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | :formatter="formattedNumber" /> |
| | | <el-table-column label="å½å
¥äºº" |
| | | prop="recorderName" |
| | | width="120" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="å½å
¥æ¥æ" |
| | | prop="entryDate" |
| | | width="100" |
| | | show-overflow-tooltip /> |
| | | <el-table-column fixed="right" |
| | | label="æä½" |
| | | width="180" |
| | | 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="openForm('edit', scope.row)">ç¼è¾</el-button> |
| | | <el-button link |
| | | type="success" |
| | | size="small" |
| | | @click="showQRCode(scope.row)">çæäºç»´ç </el-button> |
| | | <el-button link |
| | | type="primary" |
| | | size="small" |
| | | @click="downLoadFile(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" |
| | | /> |
| | | <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="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-dialog v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? 'æ°å¢éè´å°è´¦é¡µé¢' : 'ç¼è¾éè´å°è´¦é¡µé¢'" |
| | | width="70%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éè´ååå·ï¼" prop="purchaseContractNumber"> |
| | | <el-input |
| | | v-model="form.purchaseContractNumber" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="éè´ååå·ï¼" |
| | | prop="purchaseContractNumber"> |
| | | <el-input v-model="form.purchaseContractNumber" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éå®ååå·ï¼" prop="salesLedgerId"> |
| | | <el-select |
| | | v-model="form.salesLedgerId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="salesLedgerChange" |
| | | > |
| | | <el-option |
| | | v-for="item in salesContractList" |
| | | :key="item.id" |
| | | :label="item.salesContractNo" |
| | | :value="item.id" |
| | | /> |
| | | <el-form-item label="éå®ååå·ï¼" |
| | | prop="salesLedgerId"> |
| | | <el-select v-model="form.salesLedgerId" |
| | | placeholder="è¯·éæ©" |
| | | filterable |
| | | clearable |
| | | @change="salesLedgerChange"> |
| | | <el-option v-for="item in salesContractList" |
| | | :key="item.id" |
| | | :label="item.salesContractNo" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¾åºååç§°ï¼" prop="supplierId"> |
| | | <el-select |
| | | v-model="form.supplierId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | filterable |
| | | allow-create |
| | | > |
| | | <el-option |
| | | v-for="item in supplierList" |
| | | :key="item.id" |
| | | :label="item.supplierName" |
| | | :value="item.id" |
| | | /> |
| | | <el-form-item label="ä¾åºååç§°ï¼" |
| | | prop="supplierId"> |
| | | <el-select v-model="form.supplierId" |
| | | placeholder="è¯·éæ©" |
| | | filterable |
| | | clearable> |
| | | <el-option v-for="item in supplierList" |
| | | :key="item.id" |
| | | :label="item.supplierName" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项ç®åç§°ï¼" prop="projectName"> |
| | | <el-input |
| | | v-model="form.projectName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="项ç®åç§°" |
| | | prop="projectName"> |
| | | <el-input v-model="form.projectName" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仿¬¾æ¹å¼"> |
| | | <el-input |
| | | v-model="form.paymentMethod" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-input v-model="form.paymentMethod" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¾è®¢æ¥æï¼" prop="executionDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.executionDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | <el-form-item label="ç¾è®¢æ¥æï¼" |
| | | prop="executionDate"> |
| | | <el-date-picker style="width: 100%" |
| | | v-model="form.executionDate" |
| | | 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="approverId"> |
| | | <el-select |
| | | v-model="form.approverId" |
| | | placeholder="è¯·éæ©å®¡æ¹äºº" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | /> |
| | | <el-form-item label="审æ¹äººï¼" |
| | | prop="approverId"> |
| | | <el-select v-model="form.approverId" |
| | | placeholder="è¯·éæ©å®¡æ¹äºº" |
| | | clearable> |
| | | <el-option v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å½å
¥äººï¼" prop="recorderId" v-show="false"> |
| | | <el-select |
| | | v-model="form.recorderId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | disabled |
| | | > |
| | | <el-option |
| | | v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | /> |
| | | <el-form-item label="å½å
¥äººï¼" |
| | | prop="recorderId" |
| | | v-show="false"> |
| | | <el-select v-model="form.recorderId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | disabled> |
| | | <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="entryDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.entryDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | <el-form-item label="å½å
¥æ¥æï¼" |
| | | prop="entryDate"> |
| | | <el-date-picker style="width: 100%" |
| | | v-model="form.entryDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-form-item label="产åä¿¡æ¯ï¼" prop="entryDate"> |
| | | <el-button type="primary" @click="openProductForm('add')" |
| | | >æ·»å </el-button |
| | | > |
| | | <el-button plain type="danger" @click="deleteProduct" |
| | | >å é¤</el-button |
| | | > |
| | | <el-form-item label="产åä¿¡æ¯ï¼" |
| | | prop="entryDate"> |
| | | <el-button type="primary" |
| | | @click="openProductForm('add')">æ·»å </el-button> |
| | | <el-button plain |
| | | type="danger" |
| | | @click="deleteProduct">å é¤</el-button> |
| | | </el-form-item> |
| | | <div class="select-button-group" style="width: 220px; margin: 20px 0;" v-if="operationType === 'add'"> |
| | | <el-select |
| | | filterable |
| | | allow-create |
| | | :reserve-keyword="true" |
| | | :default-first-option="false" |
| | | v-model="templateName" |
| | | :input-value="filterInputValue" |
| | | @filter-change="onTemplateFilterChange" |
| | | @change="onTemplateChange" |
| | | style="width: 180px; border-right: none; border-radius: 4px 0 0 4px;" |
| | | placeholder="è¯·éæ©" |
| | | class="no-arrow-select" |
| | | > |
| | | <el-option |
| | | v-for="item in templateList" |
| | | :key="item.value" |
| | | :label="item.templateName" |
| | | :value="item.templateName" |
| | | ></el-option> |
| | | <div class="select-button-group" |
| | | style="width: 220px; margin: 20px 0;" |
| | | v-if="operationType === 'add'"> |
| | | <el-select filterable |
| | | allow-create |
| | | :reserve-keyword="true" |
| | | :default-first-option="false" |
| | | v-model="templateName" |
| | | :input-value="filterInputValue" |
| | | @filter-change="onTemplateFilterChange" |
| | | @change="onTemplateChange" |
| | | style="width: 180px; border-right: none; border-radius: 4px 0 0 4px;" |
| | | placeholder="è¯·éæ©" |
| | | class="no-arrow-select"> |
| | | <el-option v-for="item in templateList" |
| | | :key="item.value" |
| | | :label="item.templateName" |
| | | :value="item.templateName"></el-option> |
| | | </el-select> |
| | | <!-- æé®ï¼ä¸ Select é«åº¦å¹é
ï¼å»æå·¦ä¾§è¾¹æ¡ï¼æ ç¼è¡æ¥ --> |
| | | <el-button |
| | | size="small" |
| | | style="height: 32px; border-radius: 0 4px 4px 0; margin-left: -1px;" |
| | | @click="handleButtonClick" |
| | | :disabled="!templateName || templateName.trim() === '' || isTemplateNameDuplicate" |
| | | > |
| | | <el-button size="small" |
| | | style="height: 32px; border-radius: 0 4px 4px 0; margin-left: -1px;" |
| | | @click="handleButtonClick" |
| | | :disabled="!templateName || templateName.trim() === '' || isTemplateNameDuplicate"> |
| | | ä¿å |
| | | </el-button> |
| | | </div> |
| | | </el-row> |
| | | <el-table |
| | | :data="productData" |
| | | border |
| | | @selection-change="productSelected" |
| | | show-summary |
| | | :summary-method="summarizeProTable" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column |
| | | align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" /> |
| | | <el-table-column label="åä½" prop="unit" width="70" /> |
| | | <el-table-column label="æ°é" prop="quantity" width="70" /> |
| | | <el-table-column label="åºåé¢è¦æ°é" prop="warnNum" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="80" /> |
| | | <el-table-column |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | fixed="right" |
| | | label="æä½" |
| | | min-width="60" |
| | | align="center" |
| | | > |
| | | <el-table :data="productData" |
| | | border |
| | | @selection-change="productSelected" |
| | | show-summary |
| | | :summary-method="summarizeProTable"> |
| | | <el-table-column align="center" |
| | | type="selection" |
| | | width="55" /> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" /> |
| | | <el-table-column label="产å大类" |
| | | prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" |
| | | prop="specificationModel" /> |
| | | <el-table-column label="åä½" |
| | | prop="unit" |
| | | width="70" /> |
| | | <el-table-column label="æ°é" |
| | | prop="quantity" |
| | | width="70" /> |
| | | <el-table-column label="åºåé¢è¦æ°é" |
| | | prop="warnNum" |
| | | width="120" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="ç¨ç(%)" |
| | | prop="taxRate" |
| | | width="80" /> |
| | | <el-table-column label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | <el-table-column label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | <el-table-column label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | <el-table-column label="æ¯å¦è´¨æ£" |
| | | prop="isChecked" |
| | | width="150"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | @click="openProductForm('edit', scope.row, scope.$index)" |
| | | >ç¼è¾</el-button |
| | | > |
| | | <el-tag :type="scope.row.isChecked ? 'success' : 'info'"> |
| | | {{ scope.row.isChecked ? 'æ¯' : 'å¦' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column fixed="right" |
| | | label="æä½" |
| | | min-width="60" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button link |
| | | type="primary" |
| | | size="small" |
| | | @click="openProductForm('edit', scope.row, scope.$index)">ç¼è¾</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="夿³¨Â·ï¼" prop="remark"> |
| | | <el-input |
| | | v-model="form.remark" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | type="textarea" |
| | | :rows="2" |
| | | /> |
| | | <el-form-item label="夿³¨Â·ï¼" |
| | | prop="remark"> |
| | | <el-input v-model="form.remark" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | type="textarea" |
| | | :rows="2" /> |
| | | </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-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">ä¸ä¼ </el-button> |
| | | <template #tip> |
| | | <div class="el-upload__tip"> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </FormDialog> |
| | | <FormDialog |
| | | v-model="productFormVisible" |
| | | :title="productOperationType === 'add' ? 'æ°å¢äº§å' : 'ç¼è¾äº§å'" |
| | | :width="'40%'" |
| | | :operation-type="productOperationType" |
| | | @close="closeProductDia" |
| | | @confirm="submitProduct" |
| | | @cancel="closeProductDia" |
| | | > |
| | | <el-form |
| | | :model="productForm" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="productRules" |
| | | ref="productFormRef" |
| | | > |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <el-dialog v-model="productFormVisible" |
| | | :title="productOperationType === 'add' ? 'æ°å¢äº§å' : 'ç¼è¾äº§å'" |
| | | width="40%" |
| | | @close="closeProductDia"> |
| | | <el-form :model="productForm" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="productRules" |
| | | ref="productFormRef"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="产å大类ï¼" prop="productId"> |
| | | <el-tree-select |
| | | v-model="productForm.productId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | check-strictly |
| | | @change="getModels" |
| | | :data="productOptions" |
| | | :render-after-expand="false" |
| | | style="width: 100%" |
| | | /> |
| | | <el-form-item label="产å大类ï¼" |
| | | prop="productId"> |
| | | <el-tree-select v-model="productForm.productId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | check-strictly |
| | | @change="getModels" |
| | | :data="productOptions" |
| | | :render-after-expand="false" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="productModelId"> |
| | | <el-select |
| | | v-model="productForm.productModelId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="getProductModel" |
| | | > |
| | | <el-option |
| | | v-for="item in modelOptions" |
| | | :key="item.id" |
| | | :label="item.model" |
| | | :value="item.id" |
| | | /> |
| | | <el-form-item label="è§æ ¼åå·ï¼" |
| | | prop="productModelId"> |
| | | <el-select v-model="productForm.productModelId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="getProductModel"> |
| | | <el-option v-for="item in modelOptions" |
| | | :key="item.id" |
| | | :label="item.model" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åä½ï¼" prop="unit"> |
| | | <el-input |
| | | v-model="productForm.unit" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="åä½ï¼" |
| | | prop="unit"> |
| | | <el-input v-model="productForm.unit" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¨ç(%)ï¼" prop="taxRate"> |
| | | <el-select |
| | | v-model="productForm.taxRate" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="mathNum" |
| | | > |
| | | <el-option label="1" value="1" /> |
| | | <el-option label="6" value="6" /> |
| | | <el-option label="13" value="13" /> |
| | | <el-form-item label="ç¨ç(%)ï¼" |
| | | prop="taxRate"> |
| | | <el-select v-model="productForm.taxRate" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="mathNum"> |
| | | <el-option label="1" |
| | | value="1" /> |
| | | <el-option label="6" |
| | | value="6" /> |
| | | <el-option label="13" |
| | | value="13" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å«ç¨åä»·(å
)ï¼" prop="taxInclusiveUnitPrice"> |
| | | <el-input-number |
| | | v-model="productForm.taxInclusiveUnitPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="mathNum" |
| | | /> |
| | | <el-form-item label="å«ç¨åä»·(å
)ï¼" |
| | | prop="taxInclusiveUnitPrice"> |
| | | <el-input-number v-model="productForm.taxInclusiveUnitPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | | :min="0" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="mathNum" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ°éï¼" prop="quantity"> |
| | | <el-input-number |
| | | :step="0.1" |
| | | clearable |
| | | :precision="2" |
| | | style="width: 100%" |
| | | v-model="productForm.quantity" |
| | | placeholder="请è¾å
¥" |
| | | @change="mathNum" |
| | | /> |
| | | <el-form-item label="æ°éï¼" |
| | | prop="quantity"> |
| | | <el-input-number :step="0.1" |
| | | clearable |
| | | :precision="2" |
| | | :min="0" |
| | | style="width: 100%" |
| | | v-model="productForm.quantity" |
| | | placeholder="请è¾å
¥" |
| | | @change="mathNum" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å«ç¨æ»ä»·(å
)ï¼" prop="taxInclusiveTotalPrice"> |
| | | <el-input-number |
| | | v-model="productForm.taxInclusiveTotalPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="reverseMathNum('taxInclusiveTotalPrice')" |
| | | /> |
| | | <el-form-item label="å«ç¨æ»ä»·(å
)ï¼" |
| | | prop="taxInclusiveTotalPrice"> |
| | | <el-input-number v-model="productForm.taxInclusiveTotalPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | | :min="0" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="reverseMathNum('taxInclusiveTotalPrice')" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item |
| | | label="ä¸å«ç¨æ»ä»·(å
)ï¼" |
| | | prop="taxExclusiveTotalPrice" |
| | | > |
| | | <el-input |
| | | v-model="productForm.taxExclusiveTotalPrice" |
| | | @change="reverseMathNum('taxExclusiveTotalPrice')" |
| | | /> |
| | | <el-form-item label="ä¸å«ç¨æ»ä»·(å
)ï¼" |
| | | prop="taxExclusiveTotalPrice"> |
| | | <el-input-number v-model="productForm.taxExclusiveTotalPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | | :min="0" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="reverseMathNum('taxExclusiveTotalPrice')" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票类åï¼" prop="invoiceType"> |
| | | <el-select |
| | | v-model="productForm.invoiceType" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option label="墿®ç¥¨" value="墿®ç¥¨" /> |
| | | <el-option label="å¢ä¸ç¥¨" value="å¢ä¸ç¥¨" /> |
| | | <el-form-item label="å票类åï¼" |
| | | prop="invoiceType"> |
| | | <el-select v-model="productForm.invoiceType" |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option label="墿®ç¥¨" |
| | | value="墿®ç¥¨" /> |
| | | <el-option label="å¢ä¸ç¥¨" |
| | | value="å¢ä¸ç¥¨" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºåé¢è¦æ°éï¼" prop="warnNum"> |
| | | <el-input-number |
| | | v-model="productForm.warnNum" |
| | | :precision="2" |
| | | :step="0.1" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | <el-form-item label="åºåé¢è¦æ°éï¼" |
| | | prop="warnNum"> |
| | | <el-input-number v-model="productForm.warnNum" |
| | | :precision="2" |
| | | :step="0.1" |
| | | :min="0" |
| | | clearable |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¯å¦è´¨æ£ï¼" |
| | | prop="isChecked"> |
| | | <el-radio-group v-model="productForm.isChecked"> |
| | | <el-radio label="æ¯" |
| | | :value="true" /> |
| | | <el-radio label="å¦" |
| | | :value="false" /> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </FormDialog> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitProduct">确认</el-button> |
| | | <el-button @click="closeProductDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- äºç»´ç æ¾ç¤ºå¯¹è¯æ¡ --> |
| | | <el-dialog v-model="qrCodeDialogVisible" |
| | | title="éè´ååå·äºç»´ç " |
| | | width="400px" |
| | | center> |
| | | <div style="text-align: center;"> |
| | | <img :src="qrCodeUrl" |
| | | alt="äºç»´ç " |
| | | style="width:200px;height:200px;" /> |
| | | <div style="margin: 20px;"> |
| | | <el-button type="primary" |
| | | @click="downloadQRCode">ä¸è½½äºç»´ç å¾ç</el-button> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | <!-- æ«ç æ°å¢å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="scanAddDialogVisible" |
| | | title="æ«ç æ°å¢éè´å°è´¦" |
| | | width="70%" |
| | | @close="closeScanAddDialog"> |
| | | <el-form :model="scanAddForm" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="scanAddRules" |
| | | ref="scanAddFormRef"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="æ«ç å
容ï¼"> |
| | | <el-input v-model="scanAddForm.scanContent" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="è¯·æ«æäºç»´ç ææå¨è¾å
¥éè´ååä¿¡æ¯" |
| | | @input="parseScanContent" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éè´ååå·ï¼" |
| | | prop="purchaseContractNumber"> |
| | | <el-input v-model="scanAddForm.purchaseContractNumber" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¾åºååç§°ï¼" |
| | | prop="supplierName"> |
| | | <el-input v-model="scanAddForm.supplierName" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项ç®åç§°ï¼" |
| | | prop="projectName"> |
| | | <el-input v-model="scanAddForm.projectName" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ååéé¢(å
)ï¼" |
| | | prop="contractAmount"> |
| | | <el-input-number v-model="scanAddForm.contractAmount" |
| | | :precision="2" |
| | | :step="0.1" |
| | | clearable |
| | | style="width: 100%" |
| | | placeholder="请è¾å
¥" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仿¬¾æ¹å¼ï¼"> |
| | | <el-input v-model="scanAddForm.paymentMethod" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥äººï¼"> |
| | | <el-input v-model="scanAddForm.recorderName" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="夿³¨ï¼"> |
| | | <el-input v-model="scanAddForm.remark" |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitScanAdd">确认æ°å¢</el-button> |
| | | <el-button @click="closeScanAddDialog">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- æ«ç ç»è®°å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="scanDialogVisible" |
| | | title="æ«ç ç»è®°" |
| | | width="60%" |
| | | @close="closeScanDialog"> |
| | | <el-form :model="scanForm" |
| | | label-width="120px" |
| | | label-position="left" |
| | | :rules="scanRules" |
| | | ref="scanFormRef"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éè´ååå·ï¼"> |
| | | <el-input v-model="scanForm.purchaseContractNumber" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¾åºååç§°ï¼"> |
| | | <el-input v-model="scanForm.supplierName" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项ç®åç§°ï¼"> |
| | | <el-input v-model="scanForm.projectName" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ«ç æ¶é´ï¼"> |
| | | <el-input v-model="scanForm.scanTime" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ«ç 人ï¼"> |
| | | <el-input v-model="scanForm.scannerName" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ«ç ç¶æï¼"> |
| | | <el-tag :type="scanForm.scanStatus === 'å·²æ«ç ' ? 'success' : 'warning'"> |
| | | {{ scanForm.scanStatus }} |
| | | </el-tag> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="æ«ç 夿³¨ï¼"> |
| | | <el-input v-model="scanForm.scanRemark" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥æ«ç 夿³¨ä¿¡æ¯" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="æ«ç è®°å½ï¼"> |
| | | <el-table :data="scanRecords" |
| | | border |
| | | style="width: 100%"> |
| | | <el-table-column label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | align="center" /> |
| | | <el-table-column label="æ«ç æ¶é´" |
| | | prop="scanTime" |
| | | width="180" /> |
| | | <el-table-column label="æ«ç 人" |
| | | prop="scannerName" |
| | | width="120" /> |
| | | <el-table-column label="æ«ç ç¶æ" |
| | | prop="scanStatus" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="scope.row.scanStatus === 'å·²æ«ç ' ? 'success' : 'warning'"> |
| | | {{ scope.row.scanStatus }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="夿³¨" |
| | | prop="scanRemark" /> |
| | | </el-table> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitScan">确认æ«ç </el-button> |
| | | <el-button @click="closeScanDialog">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <FileList ref="fileListRef" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {getToken} from "@/utils/auth"; |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import FormDialog from '@/components/Dialog/FormDialog.vue'; |
| | | import {getCurrentInstance, nextTick, onMounted, reactive, ref, toRefs} from "vue"; |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import {ElMessage, ElMessageBox} from "element-plus"; |
| | | import {userListNoPage} from "@/api/system/user.js"; |
| | | import { |
| | | addOrUpdateSalesLedgerProduct, |
| | | delLedgerFile, |
| | | delProduct, |
| | | getProductInfoByContractNo, |
| | | getSalesLedgerWithProducts, |
| | | } from "@/api/salesManagement/salesLedger.js"; |
| | | import { |
| | | addOrEditPurchase, |
| | | addPurchaseTemplate, |
| | | createPurchaseNo, |
| | | delPurchase, |
| | | getOptions, |
| | | getPurchaseById, |
| | | getPurchaseTemplateList, |
| | | getSalesNo, |
| | | productList, |
| | | purchaseListPage |
| | | } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import useFormData from "@/hooks/useFormData.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import {modelList, productTreeList} from "@/api/basicData/product.js"; |
| | | import dayjs from "dayjs"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import { |
| | | ref, |
| | | onMounted, |
| | | reactive, |
| | | toRefs, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | } from "vue"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import FileList from "./fileList.vue"; |
| | | import { |
| | | getSalesLedgerWithProducts, |
| | | addOrUpdateSalesLedgerProduct, |
| | | delProduct, |
| | | delLedgerFile, |
| | | getProductInfoByContractNo, |
| | | } from "@/api/salesManagement/salesLedger.js"; |
| | | import { |
| | | addOrEditPurchase, |
| | | addPurchaseTemplate, |
| | | createPurchaseNo, |
| | | delPurchase, |
| | | getSalesNo, |
| | | purchaseListPage, |
| | | productList, |
| | | getPurchaseById, |
| | | getOptions, |
| | | getPurchaseTemplateList, |
| | | } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import useFormData from "@/hooks/useFormData.js"; |
| | | import QRCode from "qrcode"; |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | const tableData = ref([]); |
| | | const productData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const productSelectedRows = ref([]); |
| | | const modelOptions = ref([]); |
| | | const userList = ref([]); |
| | | const productOptions = ref([]); |
| | | const salesContractList = ref([]); |
| | | const supplierList = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | }); |
| | | const total = ref(0); |
| | | const fileList = ref([]); |
| | | const { proxy } = getCurrentInstance(); |
| | | const tableData = ref([]); |
| | | const productData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const productSelectedRows = ref([]); |
| | | const modelOptions = ref([]); |
| | | const userList = ref([]); |
| | | const productOptions = ref([]); |
| | | const salesContractList = ref([]); |
| | | const supplierList = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | }); |
| | | const total = ref(0); |
| | | const fileList = ref([]); |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { modelList, productTreeList } from "@/api/basicData/product.js"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | const userStore = useUserStore(); |
| | | const userStore = useUserStore(); |
| | | |
| | | // 订å审æ¹ç¶ææ¾ç¤ºææ¬ |
| | | const approvalStatusText = { |
| | | 0: '审æ¹ä¸', |
| | | 1: '审æ¹éè¿', |
| | | 2: '审æ¹å¤±è´¥' |
| | | }; |
| | | // äºç»´ç ç¸å
³åé |
| | | const qrCodeDialogVisible = ref(false); |
| | | const qrCodeUrl = ref(""); |
| | | |
| | | // 订å审æ¹ç¶ææ¾ç¤ºææ¬ |
| | | const approvalStatusText = { |
| | | 0: "审æ¹ä¸", |
| | | 1: "审æ¹éè¿", |
| | | 2: "审æ¹å¤±è´¥", |
| | | }; |
| | | |
| | | const templateName = ref(''); |
| | | const filterInputValue = ref(''); |
| | | const templateList = ref([]); |
| | | const isTemplateNameDuplicate = ref(false); // æ 记模æ¿åç§°æ¯å¦éå¤ |
| | | |
| | | // æ£æ¥æ¨¡æ¿åç§°æ¯å¦éå¤ |
| | | const checkTemplateNameDuplicate = (name) => { |
| | | if (!name || name.trim() === '') { |
| | | isTemplateNameDuplicate.value = false; |
| | | return false; |
| | | } |
| | | const isDuplicate = templateList.value.some(item => item.templateName === name.trim()); |
| | | isTemplateNameDuplicate.value = isDuplicate; |
| | | return isDuplicate; |
| | | }; |
| | | |
| | | // 鲿宿¶å¨ |
| | | let duplicateCheckTimer = null; |
| | | const onTemplateFilterChange = (val) => { |
| | | filterInputValue.value = val ?? ''; |
| | | // æ¸
é¤ä¹åç宿¶å¨ |
| | | if (duplicateCheckTimer) { |
| | | clearTimeout(duplicateCheckTimer); |
| | | } |
| | | // 宿¶æ£æ¥æ¨¡æ¿åç§°æ¯å¦éå¤ï¼é²æå¤çï¼é¿å
é¢ç¹æç¤ºï¼ |
| | | if (val && val.trim()) { |
| | | duplicateCheckTimer = setTimeout(() => { |
| | | const isDuplicate = checkTemplateNameDuplicate(val); |
| | | if (isDuplicate) { |
| | | ElMessage({ |
| | | message: '模æ¿åç§°å·²åå¨ï¼è¯·æ´æ¢æ¨¡æ¿åç§°', |
| | | type: 'warning', |
| | | duration: 2000 |
| | | }); |
| | | } |
| | | }, 300); // 300ms 鲿 |
| | | } else { |
| | | isTemplateNameDuplicate.value = false; |
| | | } |
| | | }; |
| | | |
| | | // allow-create æ¶ï¼è¾å
¥ä¸åå¨çå
容ä¼ä½ä¸º string å¼è¿åï¼è¿é忥åè¾å
¥æ¡ä»¥ç¡®ä¿æåä¸ä¸¢ |
| | | const onTemplateChange = async (val) => { |
| | | if (typeof val === 'string') { |
| | | filterInputValue.value = val; |
| | | // éæ©æè¾å
¥æ¶æ£æ¥éå¤ |
| | | checkTemplateNameDuplicate(val); |
| | | } |
| | | |
| | | // è¿æ»¤æ°æ®ï¼æ¥æ¾å¹é
çæ¨¡æ¿ |
| | | const matchedTemplate = templateList.value.find(item => item.templateName === val); |
| | | |
| | | if (matchedTemplate?.id) { |
| | | // 妿æ¾å°æ¨¡æ¿ï¼å è½½æ¨¡æ¿æ°æ® |
| | | form.value = { |
| | | ...form.value, |
| | | ...matchedTemplate, |
| | | }; |
| | | productData.value = matchedTemplate.productData || []; |
| | | // çææ°çéè´ååå· |
| | | try { |
| | | const res = await createPurchaseNo(); |
| | | if (res?.data) { |
| | | form.value.purchaseContractNumber = res.data; |
| | | } |
| | | } catch (error) { |
| | | console.error('çæéè´ååå·å¤±è´¥:', error); |
| | | } |
| | | } else { |
| | | // å¦ææ²¡ææ¾å°æ¨¡æ¿ï¼é置表åï¼ä¿æå½å表åç¶æï¼ |
| | | const currentFormData = { ...form.value }; |
| | | const currentProductData = [...productData.value]; |
| | | |
| | | // å¦æå¯¹è¯æ¡æªæå¼ï¼å
æå¼ |
| | | if (!dialogFormVisible.value) { |
| | | operationType.value = 'add'; |
| | | dialogFormVisible.value = true; |
| | | } |
| | | |
| | | // çå¾
ä¸ä¸ä¸ª tick 忢夿°æ® |
| | | await nextTick(); |
| | | form.value = { |
| | | ...form.value, |
| | | ...currentFormData, |
| | | }; |
| | | productData.value = currentProductData; |
| | | } |
| | | }; |
| | | |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const operationType = ref(""); |
| | | const dialogFormVisible = ref(false); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplierName: "", // ä¾åºååç§° |
| | | purchaseContractNumber: "", // éè´ååç¼å· |
| | | salesContractNo: "", // éå®ååç¼å· |
| | | projectName: "", // 项ç®åç§° |
| | | entryDate: null, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | form: { |
| | | purchaseContractNumber: "", |
| | | salesLedgerId: "", |
| | | projectName: "", |
| | | recorderId: "", |
| | | entryDate: "", |
| | | productData: [], |
| | | supplierName: "", |
| | | supplierId: "", |
| | | paymentMethod: "", |
| | | executionDate: "", |
| | | }, |
| | | rules: { |
| | | purchaseContractNumber: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | projectName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | supplierId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | entryDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | approverId:[{ required: true, message: "è¯·éæ©å®¡æ¹äºº", trigger: "change" }], |
| | | executionDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const { form: searchForm } = useFormData(data.searchForm); |
| | | |
| | | // 产å表åå¼¹æ¡æ°æ® |
| | | const productFormVisible = ref(false); |
| | | const productOperationType = ref(""); |
| | | const productOperationIndex = ref(""); |
| | | const currentId = ref(""); |
| | | const productFormData = reactive({ |
| | | productForm: { |
| | | productId: "", |
| | | productCategory: "", |
| | | productModelId: "", |
| | | specificationModel: "", |
| | | unit: "", |
| | | quantity: "", |
| | | taxInclusiveUnitPrice: "", |
| | | taxRate: "", |
| | | taxInclusiveTotalPrice: "", |
| | | taxExclusiveTotalPrice: "", |
| | | invoiceType: "", |
| | | warnNum: "", |
| | | }, |
| | | productRules: { |
| | | productId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | productModelId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | unit: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | quantity: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | taxInclusiveUnitPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | taxRate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | warnNum: [{ required: false, message: "è¯·éæ©", trigger: "change" }], |
| | | taxInclusiveTotalPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | taxExclusiveTotalPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | invoiceType: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const { productForm, productRules } = toRefs(productFormData); |
| | | const upload = reactive({ |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/file/upload", |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | }); |
| | | |
| | | const changeDaterange = (value) => { |
| | | if (value) { |
| | | searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } else { |
| | | searchForm.entryDateStart = undefined; |
| | | searchForm.entryDateEnd = undefined; |
| | | } |
| | | handleQuery(); |
| | | }; |
| | | |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | if (cellValue === null || cellValue === undefined || cellValue === '') { |
| | | return '0.00'; |
| | | } |
| | | const num = parseFloat(cellValue); |
| | | if (isNaN(num)) { |
| | | return '0.00'; |
| | | } |
| | | return num.toFixed(2); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // ä¿åæ¨¡æ¿ |
| | | const handleButtonClick = async () => { |
| | | // æ£æ¥æ¨¡æ¿åç§°æ¯å¦ä¸ºç©º |
| | | if (!templateName.value || templateName.value.trim() === '') { |
| | | ElMessage({ |
| | | message: '请è¾å
¥æ¨¡æ¿åç§°', |
| | | type: 'warning', |
| | | }); |
| | | return; |
| | | } |
| | | const templateName = ref(""); |
| | | const filterInputValue = ref(""); |
| | | const templateList = ref([]); |
| | | const isTemplateNameDuplicate = ref(false); // æ 记模æ¿åç§°æ¯å¦éå¤ |
| | | |
| | | // æ£æ¥æ¨¡æ¿åç§°æ¯å¦éå¤ |
| | | const isDuplicate = checkTemplateNameDuplicate(templateName.value); |
| | | if (isDuplicate) { |
| | | ElMessage({ |
| | | message: '模æ¿åç§°å·²åå¨ï¼è¯·æ´æ¢æ¨¡æ¿åç§°', |
| | | type: 'warning', |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥ä¾åºåæ¯å¦éæ© |
| | | if (!form.value.supplierId) { |
| | | ElMessage({ |
| | | message: '请å
éæ©ä¾åºå', |
| | | type: 'warning', |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦æäº§åæ°æ® |
| | | // if (!productData.value || productData.value.length === 0) { |
| | | // ElMessage({ |
| | | // message: '请å
æ·»å 产åä¿¡æ¯', |
| | | // type: 'warning', |
| | | // }); |
| | | // return; |
| | | // } |
| | | |
| | | try { |
| | | let params = { |
| | | productData: proxy.HaveJson(productData.value), |
| | | supplierId: form.value.supplierId, |
| | | paymentMethod: form.value.paymentMethod, |
| | | recorderId: form.value.recorderId, |
| | | approverId: form.value.approverId, |
| | | templateName: templateName.value.trim() |
| | | }; |
| | | console.log(params); |
| | | let res = await addPurchaseTemplate(params); |
| | | |
| | | if (res && res.code === 200) { |
| | | ElMessage({ |
| | | message: '模æ¿ä¿åæå', |
| | | type: 'success', |
| | | }); |
| | | // ä¿åæååéæ°è·å模æ¿å表 |
| | | await getTemplateList(); |
| | | // æ¸
空模æ¿åç§°è¾å
¥ |
| | | templateName.value = ''; |
| | | filterInputValue.value = ''; |
| | | const checkTemplateNameDuplicate = name => { |
| | | if (!name || name.trim() === "") { |
| | | isTemplateNameDuplicate.value = false; |
| | | return false; |
| | | } |
| | | const isDuplicate = templateList.value.some( |
| | | item => item.templateName === name.trim() |
| | | ); |
| | | isTemplateNameDuplicate.value = isDuplicate; |
| | | return isDuplicate; |
| | | }; |
| | | |
| | | // 鲿宿¶å¨ |
| | | let duplicateCheckTimer = null; |
| | | const onTemplateFilterChange = val => { |
| | | filterInputValue.value = val ?? ""; |
| | | // æ¸
é¤ä¹åç宿¶å¨ |
| | | if (duplicateCheckTimer) { |
| | | clearTimeout(duplicateCheckTimer); |
| | | } |
| | | // 宿¶æ£æ¥æ¨¡æ¿åç§°æ¯å¦éå¤ï¼é²æå¤çï¼é¿å
é¢ç¹æç¤ºï¼ |
| | | if (val && val.trim()) { |
| | | duplicateCheckTimer = setTimeout(() => { |
| | | const isDuplicate = checkTemplateNameDuplicate(val); |
| | | if (isDuplicate) { |
| | | ElMessage({ |
| | | message: "模æ¿åç§°å·²åå¨ï¼è¯·æ´æ¢æ¨¡æ¿åç§°", |
| | | type: "warning", |
| | | duration: 2000, |
| | | }); |
| | | } |
| | | }, 300); // 300ms 鲿 |
| | | } else { |
| | | isTemplateNameDuplicate.value = false; |
| | | } |
| | | }; |
| | | |
| | | // allow-create æ¶ï¼è¾å
¥ä¸åå¨çå
容ä¼ä½ä¸º string å¼è¿åï¼è¿é忥åè¾å
¥æ¡ä»¥ç¡®ä¿æåä¸ä¸¢ |
| | | const onTemplateChange = async val => { |
| | | if (typeof val === "string") { |
| | | filterInputValue.value = val; |
| | | // éæ©æè¾å
¥æ¶æ£æ¥éå¤ |
| | | checkTemplateNameDuplicate(val); |
| | | } |
| | | |
| | | // è¿æ»¤æ°æ®ï¼æ¥æ¾å¹é
çæ¨¡æ¿ |
| | | const matchedTemplate = templateList.value.find( |
| | | item => item.templateName === val |
| | | ); |
| | | |
| | | if (matchedTemplate?.id) { |
| | | // 妿æ¾å°æ¨¡æ¿ï¼å è½½æ¨¡æ¿æ°æ® |
| | | form.value = { |
| | | ...form.value, |
| | | ...matchedTemplate, |
| | | }; |
| | | productData.value = matchedTemplate.productData || []; |
| | | // çææ°çéè´ååå· |
| | | try { |
| | | const res = await createPurchaseNo(); |
| | | if (res?.data) { |
| | | form.value.purchaseContractNumber = res.data; |
| | | } |
| | | } catch (error) { |
| | | console.error("çæéè´ååå·å¤±è´¥:", error); |
| | | } |
| | | } else { |
| | | // å¦ææ²¡ææ¾å°æ¨¡æ¿ï¼é置表åï¼ä¿æå½å表åç¶æï¼ |
| | | const currentFormData = { ...form.value }; |
| | | const currentProductData = [...productData.value]; |
| | | |
| | | // å¦æå¯¹è¯æ¡æªæå¼ï¼å
æå¼ |
| | | if (!dialogFormVisible.value) { |
| | | operationType.value = "add"; |
| | | dialogFormVisible.value = true; |
| | | } |
| | | |
| | | // çå¾
ä¸ä¸ä¸ª tick 忢夿°æ® |
| | | await nextTick(); |
| | | form.value = { |
| | | ...form.value, |
| | | ...currentFormData, |
| | | }; |
| | | productData.value = currentProductData; |
| | | } |
| | | }; |
| | | |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const operationType = ref(""); |
| | | const dialogFormVisible = ref(false); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplierName: "", // ä¾åºååç§° |
| | | purchaseContractNumber: "", // éè´ååç¼å· |
| | | salesContractNo: "", // éå®ååç¼å· |
| | | projectName: "", // 项ç®åç§° |
| | | entryDate: null, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | form: { |
| | | purchaseContractNumber: "", |
| | | salesLedgerId: "", |
| | | projectName: "", |
| | | recorderId: "", |
| | | entryDate: "", |
| | | productData: [], |
| | | supplierName: "", |
| | | supplierId: "", |
| | | paymentMethod: "", |
| | | executionDate: "", |
| | | isChecked: true, |
| | | }, |
| | | rules: { |
| | | purchaseContractNumber: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | approverId: [ |
| | | { required: true, message: "è¯·éæ©å®¡æ¹äºº", trigger: "change" }, |
| | | ], |
| | | projectName: [ |
| | | { required: true, message: "请è¾å
¥é¡¹ç®åç§°", trigger: "blur" }, |
| | | ], |
| | | supplierId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | entryDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | executionDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const { form: searchForm } = useFormData({ |
| | | ...data.searchForm, |
| | | // 设置å½å
¥æ¥æèå´ä¸ºå½å¤© |
| | | entryDate: [ |
| | | dayjs().startOf("day").format("YYYY-MM-DD"), |
| | | dayjs().endOf("day").format("YYYY-MM-DD"), |
| | | ], |
| | | entryDateStart: dayjs().startOf("day").format("YYYY-MM-DD"), |
| | | entryDateEnd: dayjs().endOf("day").format("YYYY-MM-DD"), |
| | | }); |
| | | |
| | | // 产å表åå¼¹æ¡æ°æ® |
| | | const productFormVisible = ref(false); |
| | | const productOperationType = ref(""); |
| | | const productOperationIndex = ref(""); |
| | | const currentId = ref(""); |
| | | const productFormData = reactive({ |
| | | productForm: { |
| | | productId: "", |
| | | productCategory: "", |
| | | productModelId: "", |
| | | specificationModel: "", |
| | | unit: "", |
| | | quantity: "", |
| | | taxInclusiveUnitPrice: "", |
| | | taxRate: "", |
| | | taxInclusiveTotalPrice: "", |
| | | taxExclusiveTotalPrice: "", |
| | | invoiceType: "", |
| | | warnNum: "", |
| | | isChecked: true, |
| | | }, |
| | | productRules: { |
| | | productId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | productModelId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | unit: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | quantity: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | taxInclusiveUnitPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | taxRate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | warnNum: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | taxInclusiveTotalPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | taxExclusiveTotalPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | invoiceType: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | isChecked: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const { productForm, productRules } = toRefs(productFormData); |
| | | const upload = reactive({ |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/file/upload", |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | }); |
| | | |
| | | const changeDaterange = value => { |
| | | if (value) { |
| | | searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } else { |
| | | searchForm.entryDateStart = undefined; |
| | | searchForm.entryDateEnd = undefined; |
| | | } |
| | | handleQuery(); |
| | | }; |
| | | |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // ä¿åæ¨¡æ¿ |
| | | const handleButtonClick = async () => { |
| | | // æ£æ¥æ¨¡æ¿åç§°æ¯å¦ä¸ºç©º |
| | | if (!templateName.value || templateName.value.trim() === "") { |
| | | ElMessage({ |
| | | message: res?.msg || '模æ¿ä¿å失败', |
| | | type: 'error', |
| | | message: "请è¾å
¥æ¨¡æ¿åç§°", |
| | | type: "warning", |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥æ¨¡æ¿åç§°æ¯å¦éå¤ |
| | | const isDuplicate = checkTemplateNameDuplicate(templateName.value); |
| | | if (isDuplicate) { |
| | | ElMessage({ |
| | | message: "模æ¿åç§°å·²åå¨ï¼è¯·æ´æ¢æ¨¡æ¿åç§°", |
| | | type: "warning", |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥ä¾åºåæ¯å¦éæ© |
| | | if (!form.value.supplierId) { |
| | | ElMessage({ |
| | | message: "请å
éæ©ä¾åºå", |
| | | type: "warning", |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦æäº§åæ°æ® |
| | | // if (!productData.value || productData.value.length === 0) { |
| | | // ElMessage({ |
| | | // message: '请å
æ·»å 产åä¿¡æ¯', |
| | | // type: 'warning', |
| | | // }); |
| | | // return; |
| | | // } |
| | | |
| | | try { |
| | | let params = { |
| | | productData: proxy.HaveJson(productData.value), |
| | | supplierId: form.value.supplierId, |
| | | paymentMethod: form.value.paymentMethod, |
| | | recorderId: form.value.recorderId, |
| | | approverId: form.value.approverId, |
| | | templateName: templateName.value.trim(), |
| | | }; |
| | | console.log(params); |
| | | let res = await addPurchaseTemplate(params); |
| | | |
| | | if (res && res.code === 200) { |
| | | ElMessage({ |
| | | message: "模æ¿ä¿åæå", |
| | | type: "success", |
| | | }); |
| | | // ä¿åæååéæ°è·å模æ¿å表 |
| | | await getTemplateList(); |
| | | // æ¸
空模æ¿åç§°è¾å
¥ |
| | | templateName.value = ""; |
| | | filterInputValue.value = ""; |
| | | isTemplateNameDuplicate.value = false; |
| | | } else { |
| | | ElMessage({ |
| | | message: res?.msg || "模æ¿ä¿å失败", |
| | | type: "error", |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error("ä¿å模æ¿å¤±è´¥:", error); |
| | | ElMessage({ |
| | | message: "模æ¿ä¿å失败ï¼è¯·ç¨åéè¯", |
| | | type: "error", |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error('ä¿å模æ¿å¤±è´¥:', error); |
| | | ElMessage({ |
| | | message: '模æ¿ä¿å失败ï¼è¯·ç¨åéè¯', |
| | | type: 'error', |
| | | }); |
| | | } |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeChildrenTable = (param) => { |
| | | return proxy.summarizeTable( |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeChildrenTable = param => { |
| | | return proxy.summarizeTable( |
| | | param, |
| | | [ |
| | | "taxInclusiveUnitPrice", |
| | |
| | | ticketsNum: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | futureTickets: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | } |
| | | ); |
| | | }; |
| | | const paginationChange = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const { entryDate, ...rest } = searchForm; |
| | | purchaseListPage({ ...rest, ...page }) |
| | | .then((res) => { |
| | | ); |
| | | }; |
| | | const paginationChange = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const { entryDate, ...rest } = searchForm; |
| | | purchaseListPage({ ...rest, ...page }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | // tableData.value = res.data.records; |
| | | // å¤çæ°æ®ï¼æ·»å 失æç¶ææ è®° |
| | | tableData.value = res.data.records.map(record => ({ |
| | | ...record, |
| | | isInvalid: record.isWhite === 1 |
| | | isInvalid: record.isWhite === 1, |
| | | })); |
| | | // åå§ååæ°æ®æ°ç» |
| | | tableData.value.forEach((item) => { |
| | | tableData.value.forEach(item => { |
| | | item.children = []; |
| | | }); |
| | | total.value = res.data.total; |
| | |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const productSelected = (selectedRows) => { |
| | | productSelectedRows.value = selectedRows; |
| | | }; |
| | | const expandedRowKeys = ref([]); |
| | | // å±å¼è¡ |
| | | const expandChange = async (row, expandedRows) => { |
| | | if (expandedRows.length > 0) { |
| | | expandedRowKeys.value = []; |
| | | try { |
| | | const res = await productList({ salesLedgerId: row.id, type: 2 }); |
| | | const index = tableData.value.findIndex((item) => item.id === row.id); |
| | | if (index > -1) { |
| | | tableData.value[index].children = res.data || []; |
| | | expandedRowKeys.value.push(row.id); |
| | | } |
| | | } catch (error) { |
| | | console.error('å 载产åå表失败:', error); |
| | | proxy.$modal.msgError('å 载产åå表失败'); |
| | | // å±å¼å¤±è´¥æ¶ï¼ç§»é¤å±å¼ç¶æ |
| | | const index = expandedRows.findIndex(item => item.id === row.id); |
| | | if (index > -1) { |
| | | expandedRows.splice(index, 1); |
| | | } |
| | | } |
| | | } else { |
| | | expandedRowKeys.value = []; |
| | | } |
| | | }; |
| | | // 主表åè®¡æ¹æ³ |
| | | const summarizeMainTable = (param) => { |
| | | return proxy.summarizeTable(param, ["contractAmount"]); |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeProTable = (param) => { |
| | | return proxy.summarizeTable(param, [ |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | ]); |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = async (type, row) => { |
| | | await getTemplateList() |
| | | operationType.value = type; |
| | | form.value = {}; |
| | | productData.value = []; |
| | | fileList.value = []; |
| | | templateName.value = ''; |
| | | filterInputValue.value = ''; |
| | | isTemplateNameDuplicate.value = false; |
| | | try { |
| | | // å¹¶è¡å è½½åºç¡æ°æ® |
| | | const [userRes, salesRes, supplierRes] = await Promise.all([ |
| | | userListNoPage(), |
| | | getSalesNo(), |
| | | getOptions() |
| | | ]); |
| | | |
| | | userList.value = userRes.data || []; |
| | | salesContractList.value = salesRes || []; |
| | | // ä¾åºåè¿æ»¤åºisWhite=0 çæ°æ® |
| | | supplierList.value = (supplierRes.data || []).filter((item) => item.isWhite === 0); |
| | | |
| | | // 设置é»è®¤å¼ |
| | | form.value.recorderId = userStore.id; |
| | | form.value.entryDate = getCurrentDate(); |
| | | |
| | | if (type === "add") { |
| | | // æ°å¢æ¶çæéè´ååå· |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const productSelected = selectedRows => { |
| | | productSelectedRows.value = selectedRows; |
| | | }; |
| | | const expandedRowKeys = ref([]); |
| | | // å±å¼è¡ |
| | | const expandChange = async (row, expandedRows) => { |
| | | if (expandedRows.length > 0) { |
| | | expandedRowKeys.value = []; |
| | | try { |
| | | const purchaseNoRes = await createPurchaseNo(); |
| | | if (purchaseNoRes?.data) { |
| | | form.value.purchaseContractNumber = purchaseNoRes.data; |
| | | const res = await productList({ salesLedgerId: row.id, type: 2 }); |
| | | const index = tableData.value.findIndex(item => item.id === row.id); |
| | | if (index > -1) { |
| | | tableData.value[index].children = res.data || []; |
| | | expandedRowKeys.value.push(row.id); |
| | | } |
| | | } catch (error) { |
| | | console.error('çæéè´ååå·å¤±è´¥:', error); |
| | | proxy.$modal.msgWarning('çæéè´ååå·å¤±è´¥'); |
| | | console.error("å 载产åå表失败:", error); |
| | | proxy.$modal.msgError("å 载产åå表失败"); |
| | | // å±å¼å¤±è´¥æ¶ï¼ç§»é¤å±å¼ç¶æ |
| | | const index = expandedRows.findIndex(item => item.id === row.id); |
| | | if (index > -1) { |
| | | expandedRows.splice(index, 1); |
| | | } |
| | | } |
| | | } else if (type === "edit" && row?.id) { |
| | | // ç¼è¾æ¶å è½½æ°æ® |
| | | currentId.value = row.id; |
| | | try { |
| | | const purchaseRes = await getPurchaseById({ id: row.id, type: 2 }); |
| | | form.value = { ...purchaseRes }; |
| | | productData.value = purchaseRes.productData || []; |
| | | fileList.value = purchaseRes.salesLedgerFiles || []; |
| | | } catch (error) { |
| | | console.error('å è½½éè´å°è´¦æ°æ®å¤±è´¥:', error); |
| | | proxy.$modal.msgError('å è½½æ°æ®å¤±è´¥'); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | dialogFormVisible.value = true; |
| | | } catch (error) { |
| | | console.error('æå¼è¡¨å失败:', error); |
| | | proxy.$modal.msgError('å è½½åºç¡æ°æ®å¤±è´¥'); |
| | | } |
| | | }; |
| | | // ä¸ä¼ åæ ¡æ£ |
| | | 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) { |
| | | file.tempId = res.data.tempId; |
| | | proxy.$modal.msgSuccess("ä¸ä¼ æå"); |
| | | } else { |
| | | proxy.$modal.msgError(res.msg); |
| | | proxy.$refs.fileUpload.handleRemove(file); |
| | | } |
| | | } |
| | | // ç§»é¤æä»¶ |
| | | async function handleRemove(file) { |
| | | if (!file?.id) { |
| | | return; |
| | | } |
| | | |
| | | if (file.size > 1024 * 1024 * 10) { |
| | | // ä»
å端æ¸
çï¼ä¸è°ç¨å 餿¥å£åæç¤º |
| | | return; |
| | | } |
| | | |
| | | if (operationType.value === "edit" && file.id) { |
| | | try { |
| | | await delLedgerFile([file.id]); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | } catch (error) { |
| | | console.error('å é¤æä»¶å¤±è´¥:', error); |
| | | proxy.$modal.msgError("å é¤æä»¶å¤±è´¥"); |
| | | } |
| | | } |
| | | } |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | const valid = await proxy.$refs["formRef"].validate().catch(() => false); |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | |
| | | if (!productData.value || productData.value.length === 0) { |
| | | proxy.$modal.msgWarning("请添å 产åä¿¡æ¯"); |
| | | return; |
| | | } |
| | | |
| | | form.value.productData = proxy.HaveJson(productData.value); |
| | | form.value.tempFileIds = fileList.value |
| | | .filter(item => item.tempId) |
| | | .map((item) => item.tempId); |
| | | form.value.type = 2; |
| | | |
| | | try { |
| | | await addOrEditPurchase(form.value); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | } catch (error) { |
| | | console.error('æäº¤è¡¨å失败:', error); |
| | | proxy.$modal.msgError("æäº¤å¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | } catch (error) { |
| | | console.error('表åéªè¯å¤±è´¥:', error); |
| | | } |
| | | }; |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | // æå¼äº§åå¼¹æ¡ |
| | | const openProductForm = (type, row, index) => { |
| | | productOperationType.value = type; |
| | | productOperationIndex.value = index; |
| | | productForm.value = {}; |
| | | proxy.resetForm("productFormRef"); |
| | | if (type === "edit") { |
| | | productForm.value = { ...row }; |
| | | } |
| | | productFormVisible.value = true; |
| | | getProductOptions(); |
| | | }; |
| | | const getProductOptions = async () => { |
| | | try { |
| | | const res = await productTreeList(); |
| | | productOptions.value = convertIdToValue(res); |
| | | } catch (error) { |
| | | console.error('å 载产åé项失败:', error); |
| | | proxy.$modal.msgError('å 载产åé项失败'); |
| | | } |
| | | }; |
| | | const getModels = async (value) => { |
| | | if (value) { |
| | | productForm.value.productCategory = findNodeById(productOptions.value, value) || ""; |
| | | try { |
| | | const res = await modelList({ id: value }); |
| | | modelOptions.value = res || []; |
| | | } catch (error) { |
| | | console.error('å è½½è§æ ¼åå·å¤±è´¥:', error); |
| | | proxy.$modal.msgError('å è½½è§æ ¼åå·å¤±è´¥'); |
| | | modelOptions.value = []; |
| | | } |
| | | } else { |
| | | productForm.value.productCategory = ""; |
| | | modelOptions.value = []; |
| | | } |
| | | }; |
| | | const getProductModel = (value) => { |
| | | const index = modelOptions.value.findIndex((item) => item.id === value); |
| | | if (index !== -1) { |
| | | productForm.value.specificationModel = modelOptions.value[index].model; |
| | | productForm.value.unit = modelOptions.value[index].unit; |
| | | } else { |
| | | productForm.value.specificationModel = null; |
| | | productForm.value.unit = null; |
| | | } |
| | | }; |
| | | const findNodeById = (nodes, productId) => { |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | if (nodes[i].value === productId) { |
| | | return nodes[i].label; // æ¾å°èç¹ï¼è¿å该èç¹çlabel |
| | | } |
| | | if (nodes[i].children && nodes[i].children.length > 0) { |
| | | const foundNode = findNodeById(nodes[i].children, productId); |
| | | if (foundNode) { |
| | | return foundNode; // å¨åèç¹ä¸æ¾å°ï¼ç´æ¥è¿åï¼å·²ç»æ¯labelåç¬¦ä¸²ï¼ |
| | | } |
| | | } |
| | | } |
| | | return null; // æ²¡ææ¾å°èç¹ï¼è¿ånull |
| | | }; |
| | | 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 submitProduct = async () => { |
| | | try { |
| | | const valid = await proxy.$refs["productFormRef"].validate().catch(() => false); |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | |
| | | if (operationType.value === "edit") { |
| | | await submitProductEdit(); |
| | | } else { |
| | | if (productOperationType.value === "add") { |
| | | productData.value.push({ ...productForm.value }); |
| | | } else { |
| | | productData.value[productOperationIndex.value] = { |
| | | ...productForm.value, |
| | | }; |
| | | } |
| | | closeProductDia(); |
| | | expandedRowKeys.value = []; |
| | | } |
| | | } catch (error) { |
| | | console.error('æäº¤äº§å表å失败:', error); |
| | | } |
| | | }; |
| | | |
| | | const submitProductEdit = async () => { |
| | | try { |
| | | productForm.value.salesLedgerId = currentId.value; |
| | | productForm.value.type = 2; |
| | | await addOrUpdateSalesLedgerProduct(productForm.value); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeProductDia(); |
| | | |
| | | // éæ°å è½½äº§åæ°æ® |
| | | }; |
| | | // 主表åè®¡æ¹æ³ |
| | | const summarizeMainTable = param => { |
| | | return proxy.summarizeTable(param, ["contractAmount"]); |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeProTable = param => { |
| | | return proxy.summarizeTable(param, [ |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | ]); |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = async (type, row) => { |
| | | await getTemplateList(); |
| | | operationType.value = type; |
| | | form.value = {}; |
| | | productData.value = []; |
| | | fileList.value = []; |
| | | templateName.value = ""; |
| | | filterInputValue.value = ""; |
| | | isTemplateNameDuplicate.value = false; |
| | | try { |
| | | const res = await getPurchaseById({ id: currentId.value, type: 2 }); |
| | | productData.value = res.productData || []; |
| | | } catch (error) { |
| | | console.error('éæ°å è½½äº§åæ°æ®å¤±è´¥:', error); |
| | | } |
| | | } catch (error) { |
| | | console.error('æäº¤äº§åç¼è¾å¤±è´¥:', error); |
| | | proxy.$modal.msgError("æäº¤å¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | }; |
| | | // å é¤äº§å |
| | | const deleteProduct = async () => { |
| | | if (productSelectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | if (operationType.value === "add") { |
| | | // æ°å¢æ¨¡å¼ä¸ï¼ç´æ¥ä»åç«¯æ°æ®ä¸å é¤ |
| | | productSelectedRows.value.forEach((selectedRow) => { |
| | | const index = productData.value.findIndex( |
| | | (product) => product.id === selectedRow.id |
| | | // å¹¶è¡å è½½åºç¡æ°æ® |
| | | const [userRes, salesRes, supplierRes] = await Promise.all([ |
| | | userListNoPage(), |
| | | getSalesNo(), |
| | | getOptions(), |
| | | ]); |
| | | |
| | | userList.value = userRes.data || []; |
| | | salesContractList.value = salesRes || []; |
| | | // ä¾åºåè¿æ»¤åºisWhite=0 çæ°æ® |
| | | supplierList.value = (supplierRes.data || []).filter( |
| | | item => item.isWhite === 0 |
| | | ); |
| | | if (index !== -1) { |
| | | productData.value.splice(index, 1); |
| | | |
| | | // 设置é»è®¤å¼ |
| | | form.value.recorderId = userStore.id; |
| | | form.value.entryDate = getCurrentDate(); |
| | | |
| | | if (type === "add") { |
| | | // æ°å¢æ¶çæéè´ååå· |
| | | try { |
| | | const purchaseNoRes = await createPurchaseNo(); |
| | | if (purchaseNoRes?.data) { |
| | | form.value.purchaseContractNumber = purchaseNoRes.data; |
| | | } |
| | | } catch (error) { |
| | | console.error("çæéè´ååå·å¤±è´¥:", error); |
| | | proxy.$modal.msgWarning("çæéè´ååå·å¤±è´¥"); |
| | | } |
| | | } else if (type === "edit" && row?.id) { |
| | | // ç¼è¾æ¶å è½½æ°æ® |
| | | currentId.value = row.id; |
| | | try { |
| | | const purchaseRes = await getPurchaseById({ id: row.id, type: 2 }); |
| | | form.value = { ...purchaseRes }; |
| | | productData.value = purchaseRes.productData || []; |
| | | fileList.value = purchaseRes.salesLedgerFiles || []; |
| | | } catch (error) { |
| | | console.error("å è½½éè´å°è´¦æ°æ®å¤±è´¥:", error); |
| | | proxy.$modal.msgError("å è½½æ°æ®å¤±è´¥"); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | if (form.value.salesLedgerId == -1) { |
| | | form.value.salesLedgerId = null; |
| | | } |
| | | console.log(form.value, "form.value==========="); |
| | | dialogFormVisible.value = true; |
| | | } catch (error) { |
| | | console.error("æå¼è¡¨å失败:", error); |
| | | proxy.$modal.msgError("å è½½åºç¡æ°æ®å¤±è´¥"); |
| | | } |
| | | }; |
| | | // ä¸ä¼ åæ ¡æ£ |
| | | 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) { |
| | | file.tempId = res.data.tempId; |
| | | proxy.$modal.msgSuccess("ä¸ä¼ æå"); |
| | | } else { |
| | | proxy.$modal.msgError(res.msg); |
| | | proxy.$refs.fileUpload.handleRemove(file); |
| | | } |
| | | } |
| | | // ç§»é¤æä»¶ |
| | | async function handleRemove(file) { |
| | | if (!file?.id) { |
| | | return; |
| | | } |
| | | console.log("handleRemove", file.id); |
| | | if (file.size > 1024 * 1024 * 10) { |
| | | // ä»
å端æ¸
çï¼ä¸è°ç¨å 餿¥å£åæç¤º |
| | | return; |
| | | } |
| | | |
| | | if (operationType.value === "edit" && file.id) { |
| | | try { |
| | | await delLedgerFile([file.id]); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | } catch (error) { |
| | | console.error("å é¤æä»¶å¤±è´¥:", error); |
| | | proxy.$modal.msgError("å é¤æä»¶å¤±è´¥"); |
| | | } |
| | | } |
| | | } |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | if (productData.value.length > 0) { |
| | | form.value.productData = proxy.HaveJson(productData.value); |
| | | } else { |
| | | proxy.$modal.msgWarning("请添å 产åä¿¡æ¯"); |
| | | return; |
| | | } |
| | | let tempFileIds = []; |
| | | if (fileList.value.length > 0) { |
| | | tempFileIds = fileList.value.map(item => item.tempId); |
| | | } |
| | | form.value.tempFileIds = tempFileIds; |
| | | form.value.type = 2; |
| | | |
| | | // 妿salesLedgerId为空ï¼åä¸ä¼ ésalesContractNo |
| | | if (!form.value.salesLedgerId) { |
| | | form.value.salesContractNo = ""; |
| | | } |
| | | |
| | | addOrEditPurchase(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | } |
| | | }); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | } else { |
| | | // ç¼è¾æ¨¡å¼ä¸ï¼éè¦è°ç¨æ¥å£å é¤ |
| | | const ids = productSelectedRows.value |
| | | .filter(item => item.id) |
| | | .map((item) => item.id); |
| | | |
| | | if (ids.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©ææçæ°æ®"); |
| | | }; |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | // æå¼äº§åå¼¹æ¡ |
| | | const openProductForm = (type, row, index) => { |
| | | productOperationType.value = type; |
| | | productOperationIndex.value = index; |
| | | productForm.value = {}; |
| | | proxy.resetForm("productFormRef"); |
| | | if (type === "edit") { |
| | | productForm.value = { ...row }; |
| | | } |
| | | productFormVisible.value = true; |
| | | getProductOptions(); |
| | | }; |
| | | const getProductOptions = () => { |
| | | productTreeList().then(res => { |
| | | productOptions.value = convertIdToValue(res); |
| | | }); |
| | | }; |
| | | const getModels = value => { |
| | | if (value) { |
| | | productForm.value.productCategory = |
| | | findNodeById(productOptions.value, value) || ""; |
| | | modelList({ id: value }).then(res => { |
| | | modelOptions.value = res; |
| | | }); |
| | | } else { |
| | | productForm.value.productCategory = ""; |
| | | modelOptions.value = []; |
| | | } |
| | | }; |
| | | const getProductModel = value => { |
| | | const index = modelOptions.value.findIndex(item => item.id === value); |
| | | if (index !== -1) { |
| | | productForm.value.specificationModel = modelOptions.value[index].model; |
| | | productForm.value.unit = modelOptions.value[index].unit; |
| | | } else { |
| | | productForm.value.specificationModel = null; |
| | | productForm.value.unit = null; |
| | | } |
| | | }; |
| | | const findNodeById = (nodes, productId) => { |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | if (nodes[i].value === productId) { |
| | | return nodes[i].label; // æ¾å°èç¹ï¼è¿å该èç¹çlabel |
| | | } |
| | | if (nodes[i].children && nodes[i].children.length > 0) { |
| | | const foundNode = findNodeById(nodes[i].children, productId); |
| | | if (foundNode) { |
| | | return foundNode; // å¨åèç¹ä¸æ¾å°ï¼ç´æ¥è¿åï¼å·²ç»æ¯labelåç¬¦ä¸²ï¼ |
| | | } |
| | | } |
| | | } |
| | | return null; // æ²¡ææ¾å°èç¹ï¼è¿ånull |
| | | }; |
| | | 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 submitProduct = () => { |
| | | proxy.$refs["productFormRef"].validate(valid => { |
| | | if (valid) { |
| | | if (operationType.value === "edit") { |
| | | submitProductEdit(); |
| | | } else { |
| | | if (productOperationType.value === "add") { |
| | | productData.value.push({ ...productForm.value }); |
| | | console.log("productData.value---", productData.value); |
| | | } else { |
| | | productData.value[productOperationIndex.value] = { |
| | | ...productForm.value, |
| | | }; |
| | | } |
| | | closeProductDia(); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | const submitProductEdit = () => { |
| | | productForm.value.salesLedgerId = currentId.value; |
| | | productForm.value.type = 2; |
| | | addOrUpdateSalesLedgerProduct(productForm.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeProductDia(); |
| | | getPurchaseById({ id: currentId.value, type: 2 }).then(res => { |
| | | productData.value = res.productData; |
| | | }); |
| | | }); |
| | | }; |
| | | // å é¤äº§å |
| | | const deleteProduct = () => { |
| | | if (productSelectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | await ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤ç¡®è®¤", { |
| | | if (operationType.value === "add") { |
| | | productSelectedRows.value.forEach(selectedRow => { |
| | | const index = productData.value.findIndex( |
| | | product => product.id === selectedRow.id |
| | | ); |
| | | if (index !== -1) { |
| | | productData.value.splice(index, 1); |
| | | } |
| | | }); |
| | | } else { |
| | | let ids = []; |
| | | if (productSelectedRows.value.length > 0) { |
| | | ids = productSelectedRows.value.map(item => item.id); |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | delProduct(ids).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | closeProductDia(); |
| | | getSalesLedgerWithProducts({ id: currentId.value, type: 2 }).then( |
| | | res => { |
| | | productData.value = res.productData; |
| | | } |
| | | ); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | } |
| | | }; |
| | | // å
³é产åå¼¹æ¡ |
| | | const closeProductDia = () => { |
| | | proxy.resetForm("productFormRef"); |
| | | productFormVisible.value = false; |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/purchase/ledger/export", {}, "éè´å°è´¦.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | |
| | | await delProduct(ids); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | closeProductDia(); |
| | | |
| | | // éæ°å è½½äº§åæ°æ® |
| | | try { |
| | | const res = await getSalesLedgerWithProducts({ id: currentId.value, type: 2 }); |
| | | productData.value = res.productData || []; |
| | | } catch (error) { |
| | | console.error('éæ°å è½½äº§åæ°æ®å¤±è´¥:', error); |
| | | } |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | console.error('å é¤äº§å失败:', error); |
| | | proxy.$modal.msgError("å é¤å¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | // å
³é产åå¼¹æ¡ |
| | | const closeProductDia = () => { |
| | | proxy.resetForm("productFormRef"); |
| | | productFormVisible.value = false; |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = async () => { |
| | | try { |
| | | await ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åºç¡®è®¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }); |
| | | proxy.download("/purchase/ledger/export", {}, "éè´å°è´¦.xlsx"); |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | console.error('导åºå¤±è´¥:', error); |
| | | proxy.$modal.msgError("导åºå¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // å é¤ |
| | | const handleDelete = async () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® |
| | | const unauthorizedData = selectedRows.value.filter(item => item.recorderName !== userStore.nickName); |
| | | if (unauthorizedData.length > 0) { |
| | | proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | const ids = selectedRows.value |
| | | .filter(item => item.id) |
| | | .map((item) => item.id); |
| | | |
| | | if (ids.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©ææçæ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | await ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤ç¡®è®¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }); |
| | | |
| | | await delPurchase(ids); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | console.error('å é¤å¤±è´¥:', error); |
| | | proxy.$modal.msgError("å é¤å¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | } |
| | | }; |
| | | const mathNum = () => { |
| | | if (!productForm.value.taxRate) { |
| | | proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | return; |
| | | } |
| | | if (!productForm.value.taxInclusiveUnitPrice) { |
| | | return; |
| | | } |
| | | if (!productForm.value.quantity) { |
| | | return; |
| | | } |
| | | // å«ç¨æ»ä»·è®¡ç® |
| | | productForm.value.taxInclusiveTotalPrice = |
| | | proxy.calculateTaxIncludeTotalPrice( |
| | | productForm.value.taxInclusiveUnitPrice, |
| | | productForm.value.quantity |
| | | }; |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® |
| | | const unauthorizedData = selectedRows.value.filter( |
| | | item => item.recorderName !== userStore.nickName |
| | | ); |
| | | if (productForm.value.taxRate) { |
| | | // ä¸å«ç¨æ»ä»·è®¡ç® |
| | | productForm.value.taxExclusiveTotalPrice = |
| | | proxy.calculateTaxExclusiveTotalPrice( |
| | | productForm.value.taxInclusiveTotalPrice, |
| | | productForm.value.taxRate |
| | | ); |
| | | } |
| | | }; |
| | | const reverseMathNum = (field) => { |
| | | if (!productForm.value.taxRate) { |
| | | proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | return; |
| | | } |
| | | const taxRate = Number(productForm.value.taxRate); |
| | | if (!taxRate) return; |
| | | if (field === 'taxInclusiveTotalPrice') { |
| | | // å·²ç¥å«ç¨æ»ä»·åæ°éï¼åç®å«ç¨åä»· |
| | | if (productForm.value.quantity) { |
| | | productForm.value.taxInclusiveUnitPrice = |
| | | (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.quantity)).toFixed(2); |
| | | if (unauthorizedData.length > 0) { |
| | | proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); |
| | | return; |
| | | } |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | // å·²ç¥å«ç¨æ»ä»·åå«ç¨åä»·ï¼åç®æ°é |
| | | else if (productForm.value.taxInclusiveUnitPrice) { |
| | | productForm.value.quantity = |
| | | (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.taxInclusiveUnitPrice)).toFixed(2); |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | delPurchase(ids).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | | const year = today.getFullYear(); |
| | | const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ |
| | | const day = String(today.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | const mathNum = () => { |
| | | if (!productForm.value.taxRate) { |
| | | proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | return; |
| | | } |
| | | // åç®ä¸å«ç¨æ»ä»· |
| | | productForm.value.taxExclusiveTotalPrice = |
| | | (Number(productForm.value.taxInclusiveTotalPrice) / (1 + taxRate / 100)).toFixed(2); |
| | | } else if (field === 'taxExclusiveTotalPrice') { |
| | | // åç®å«ç¨æ»ä»· |
| | | if (!productForm.value.taxInclusiveUnitPrice) { |
| | | return; |
| | | } |
| | | if (!productForm.value.quantity) { |
| | | return; |
| | | } |
| | | // å«ç¨æ»ä»·è®¡ç® |
| | | productForm.value.taxInclusiveTotalPrice = |
| | | (Number(productForm.value.taxExclusiveTotalPrice) * (1 + taxRate / 100)).toFixed(2); |
| | | // å·²ç¥æ°éï¼åç®å«ç¨åä»· |
| | | if (productForm.value.quantity) { |
| | | productForm.value.taxInclusiveUnitPrice = |
| | | (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.quantity)).toFixed(2); |
| | | proxy.calculateTaxIncludeTotalPrice( |
| | | productForm.value.taxInclusiveUnitPrice, |
| | | productForm.value.quantity |
| | | ); |
| | | if (productForm.value.taxRate) { |
| | | // ä¸å«ç¨æ»ä»·è®¡ç® |
| | | productForm.value.taxExclusiveTotalPrice = |
| | | proxy.calculateTaxExclusiveTotalPrice( |
| | | productForm.value.taxInclusiveTotalPrice, |
| | | productForm.value.taxRate |
| | | ); |
| | | } |
| | | // å·²ç¥å«ç¨åä»·ï¼åç®æ°é |
| | | else if (productForm.value.taxInclusiveUnitPrice) { |
| | | productForm.value.quantity = |
| | | (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.taxInclusiveUnitPrice)).toFixed(2); |
| | | }; |
| | | const reverseMathNum = field => { |
| | | if (!productForm.value.taxRate) { |
| | | proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | return; |
| | | } |
| | | } |
| | | }; |
| | | // éå®ååéæ©æ¹åæ¹æ³ |
| | | const salesLedgerChange = async (row) => { |
| | | const index = salesContractList.value.findIndex((item) => item.id === row); |
| | | if (index > -1) { |
| | | form.value.projectName = salesContractList.value[index].projectName; |
| | | await querygProductInfoByContractNo(); |
| | | } |
| | | }; |
| | | const taxRate = Number(productForm.value.taxRate); |
| | | if (!taxRate) return; |
| | | |
| | | const querygProductInfoByContractNo = async () => { |
| | | const { code, data } = await getProductInfoByContractNo({ |
| | | contractNo: form.value.salesLedgerId, |
| | | // ç¡®ä¿è¾å
¥å¼ä¸ä¸ºè´æ° |
| | | if ( |
| | | field === "taxInclusiveTotalPrice" || |
| | | field === "taxExclusiveTotalPrice" |
| | | ) { |
| | | const value = Number(productForm.value[field]); |
| | | if (value < 0) { |
| | | productForm.value[field] = "0"; |
| | | proxy.$modal.msgWarning("å¼ä¸è½å°äº0"); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | if (field === "taxInclusiveTotalPrice") { |
| | | // å·²ç¥å«ç¨æ»ä»·åæ°éï¼åç®å«ç¨åä»· |
| | | if (productForm.value.quantity) { |
| | | productForm.value.taxInclusiveUnitPrice = ( |
| | | Number(productForm.value.taxInclusiveTotalPrice) / |
| | | Number(productForm.value.quantity) |
| | | ).toFixed(2); |
| | | // ç¡®ä¿ç»æä¸ä¸ºè´æ° |
| | | if (Number(productForm.value.taxInclusiveUnitPrice) < 0) { |
| | | productForm.value.taxInclusiveUnitPrice = "0"; |
| | | } |
| | | } |
| | | // å·²ç¥å«ç¨æ»ä»·åå«ç¨åä»·ï¼åç®æ°é |
| | | else if (productForm.value.taxInclusiveUnitPrice) { |
| | | productForm.value.quantity = ( |
| | | Number(productForm.value.taxInclusiveTotalPrice) / |
| | | Number(productForm.value.taxInclusiveUnitPrice) |
| | | ).toFixed(2); |
| | | // ç¡®ä¿ç»æä¸ä¸ºè´æ° |
| | | if (Number(productForm.value.quantity) < 0) { |
| | | productForm.value.quantity = "0"; |
| | | } |
| | | } |
| | | // åç®ä¸å«ç¨æ»ä»· |
| | | productForm.value.taxExclusiveTotalPrice = ( |
| | | Number(productForm.value.taxInclusiveTotalPrice) / |
| | | (1 + taxRate / 100) |
| | | ).toFixed(2); |
| | | // ç¡®ä¿ç»æä¸ä¸ºè´æ° |
| | | if (Number(productForm.value.taxExclusiveTotalPrice) < 0) { |
| | | productForm.value.taxExclusiveTotalPrice = "0"; |
| | | } |
| | | } else if (field === "taxExclusiveTotalPrice") { |
| | | // åç®å«ç¨æ»ä»· |
| | | productForm.value.taxInclusiveTotalPrice = ( |
| | | Number(productForm.value.taxExclusiveTotalPrice) * |
| | | (1 + taxRate / 100) |
| | | ).toFixed(2); |
| | | // ç¡®ä¿ç»æä¸ä¸ºè´æ° |
| | | if (Number(productForm.value.taxInclusiveTotalPrice) < 0) { |
| | | productForm.value.taxInclusiveTotalPrice = "0"; |
| | | } |
| | | // å·²ç¥æ°éï¼åç®å«ç¨åä»· |
| | | if (productForm.value.quantity) { |
| | | productForm.value.taxInclusiveUnitPrice = ( |
| | | Number(productForm.value.taxInclusiveTotalPrice) / |
| | | Number(productForm.value.quantity) |
| | | ).toFixed(2); |
| | | // ç¡®ä¿ç»æä¸ä¸ºè´æ° |
| | | if (Number(productForm.value.taxInclusiveUnitPrice) < 0) { |
| | | productForm.value.taxInclusiveUnitPrice = "0"; |
| | | } |
| | | } |
| | | // å·²ç¥å«ç¨åä»·ï¼åç®æ°é |
| | | else if (productForm.value.taxInclusiveUnitPrice) { |
| | | productForm.value.quantity = ( |
| | | Number(productForm.value.taxInclusiveTotalPrice) / |
| | | Number(productForm.value.taxInclusiveUnitPrice) |
| | | ).toFixed(2); |
| | | // ç¡®ä¿ç»æä¸ä¸ºè´æ° |
| | | if (Number(productForm.value.quantity) < 0) { |
| | | productForm.value.quantity = "0"; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | // éå®ååéæ©æ¹åæ¹æ³ |
| | | const salesLedgerChange = async row => { |
| | | console.log("row", row); |
| | | var index = salesContractList.value.findIndex(item => item.id == row); |
| | | console.log("index", index); |
| | | if (index > -1) { |
| | | await querygProductInfoByContractNo(); |
| | | } |
| | | }; |
| | | |
| | | const querygProductInfoByContractNo = async () => { |
| | | const { code, data } = await getProductInfoByContractNo({ |
| | | contractNo: form.value.salesLedgerId, |
| | | }); |
| | | if (code == 200) { |
| | | productData.value = data; |
| | | } |
| | | }; |
| | | |
| | | const fileListRef = ref(null); |
| | | const downLoadFile = row => { |
| | | fileListRef.value.open(row.salesLedgerFiles); |
| | | }; |
| | | |
| | | // æ¾ç¤ºäºç»´ç |
| | | const showQRCode = async row => { |
| | | try { |
| | | // æå»ºäºç»´ç å
容ï¼åªå
å«éè´ååå·ï¼çº¯ææ¬ï¼ |
| | | const qrContent = row.purchaseContractNumber || ""; |
| | | // æ£æ¥å
容æ¯å¦ä¸ºç©º |
| | | if (!qrContent || qrContent.trim() === "") { |
| | | proxy.$modal.msgWarning("è¯¥è¡æ²¡æéè´ååå·ï¼æ æ³çæäºç»´ç "); |
| | | return; |
| | | } |
| | | qrCodeUrl.value = await QRCode.toDataURL(qrContent, { |
| | | width: 200, |
| | | margin: 2, |
| | | color: { |
| | | dark: "#000000", |
| | | light: "#FFFFFF", |
| | | }, |
| | | }); |
| | | qrCodeDialogVisible.value = true; |
| | | } catch (error) { |
| | | console.error("çæäºç»´ç 失败:", error); |
| | | proxy.$modal.msgError("çæäºç»´ç 失败ï¼" + error.message); |
| | | } |
| | | }; |
| | | |
| | | // ä¸è½½äºç»´ç |
| | | const downloadQRCode = () => { |
| | | if (!qrCodeUrl.value) { |
| | | proxy.$modal.msgWarning("äºç»´ç æªçæ"); |
| | | return; |
| | | } |
| | | |
| | | const a = document.createElement("a"); |
| | | a.href = qrCodeUrl.value; |
| | | a.download = `éè´ååå·äºç»´ç _${new Date().getTime()}.png`; |
| | | document.body.appendChild(a); |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | proxy.$modal.msgSuccess("ä¸è½½æå"); |
| | | }; |
| | | |
| | | // æ«ç æ°å¢å¯¹è¯æ¡ç¸å
³åé |
| | | const scanAddDialogVisible = ref(false); |
| | | const scanAddForm = reactive({ |
| | | scanContent: "", |
| | | purchaseContractNumber: "", |
| | | supplierName: "", |
| | | projectName: "", |
| | | contractAmount: "", |
| | | paymentMethod: "", |
| | | recorderName: "", |
| | | scanRemark: "", |
| | | }); |
| | | if (code == 200) { |
| | | productData.value = data; |
| | | const scanAddRules = { |
| | | purchaseContractNumber: [ |
| | | { required: true, message: "请è¾å
¥éè´ååå·", trigger: "blur" }, |
| | | ], |
| | | supplierName: [ |
| | | { required: true, message: "请è¾å
¥ä¾åºååç§°", trigger: "blur" }, |
| | | ], |
| | | projectName: [{ required: true, message: "请è¾å
¥é¡¹ç®åç§°", trigger: "blur" }], |
| | | }; |
| | | |
| | | // æ«ç ç»è®°å¯¹è¯æ¡ç¸å
³åé |
| | | const scanDialogVisible = ref(false); |
| | | const scanForm = reactive({ |
| | | purchaseContractNumber: "", |
| | | supplierName: "", |
| | | projectName: "", |
| | | scanTime: "", |
| | | scannerName: "", |
| | | scanStatus: "æªæ«ç ", |
| | | scanRemark: "", |
| | | }); |
| | | const scanRules = { |
| | | scanRemark: [{ required: true, message: "请è¾å
¥æ«ç 夿³¨", trigger: "blur" }], |
| | | }; |
| | | const scanRecords = ref([]); |
| | | |
| | | // æå¼æ«ç æ°å¢å¯¹è¯æ¡ |
| | | const openScanAddDialog = () => { |
| | | scanAddForm.scanContent = ""; |
| | | scanAddForm.purchaseContractNumber = ""; |
| | | scanAddForm.supplierName = ""; |
| | | scanAddForm.projectName = ""; |
| | | scanAddForm.contractAmount = ""; |
| | | scanAddForm.paymentMethod = ""; |
| | | scanAddForm.recorderName = userStore.nickName; |
| | | scanAddForm.scanRemark = ""; |
| | | scanAddDialogVisible.value = true; |
| | | }; |
| | | |
| | | // è§£ææ«ç å
å®¹ï¼æ¨¡æè§£æäºç»´ç æ°æ®ï¼ |
| | | const parseScanContent = content => { |
| | | if (!content) return; |
| | | |
| | | // 模æè§£æäºç»´ç å
容ï¼è¿éå¯ä»¥æ ¹æ®å®é
éæ±è°æ´è§£æé»è¾ |
| | | // å设æ«ç å
å®¹æ ¼å¼ä¸ºï¼ååå·|ä¾åºå|éé¢|仿¬¾æ¹å¼ |
| | | const parts = content.split("|"); |
| | | if (parts.length >= 2) { |
| | | scanAddForm.purchaseContractNumber = parts[0] || ""; |
| | | scanAddForm.supplierName = parts[1] || ""; |
| | | scanAddForm.contractAmount = parts[2] || ""; |
| | | scanAddForm.paymentMethod = parts[3] || ""; |
| | | scanAddForm.projectName = parts[4] || ""; |
| | | // scanAddForm.contractAmount = parts[3] || ""; |
| | | // scanAddForm.paymentMethod = parts[4] || ""; |
| | | } |
| | | }; |
| | | |
| | | // å
³éæ«ç æ°å¢å¯¹è¯æ¡ |
| | | const closeScanAddDialog = () => { |
| | | scanAddDialogVisible.value = false; |
| | | proxy.resetForm("scanAddFormRef"); |
| | | }; |
| | | |
| | | // æäº¤æ«ç æ°å¢ |
| | | const submitScanAdd = () => { |
| | | proxy.$refs["scanAddFormRef"].validate(valid => { |
| | | if (valid) { |
| | | // æå»ºæ°å¢æ°æ® |
| | | const newData = { |
| | | purchaseContractNumber: scanAddForm.purchaseContractNumber, |
| | | supplierName: scanAddForm.supplierName, |
| | | projectName: scanAddForm.projectName, |
| | | contractAmount: scanAddForm.contractAmount, |
| | | paymentMethod: scanAddForm.paymentMethod, |
| | | recorderName: scanAddForm.recorderName, |
| | | entryDate: getCurrentDate(), |
| | | remark: scanAddForm.scanRemark, |
| | | type: 2, |
| | | }; |
| | | |
| | | // æ¨¡ææ°å¢æå |
| | | proxy.$modal.msgSuccess("æ«ç æ°å¢æåï¼"); |
| | | closeScanAddDialog(); |
| | | |
| | | // å¯ä»¥éæ©æ¯å¦å·æ°å表 |
| | | // getList(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // æå¼æ«ç ç»è®°å¯¹è¯æ¡ |
| | | const openScanDialog = row => { |
| | | scanForm.purchaseContractNumber = row.purchaseContractNumber; |
| | | scanForm.supplierName = row.supplierName; |
| | | scanForm.projectName = row.projectName; |
| | | scanForm.scanTime = getCurrentDateTime(); |
| | | scanForm.scannerName = userStore.nickName; |
| | | scanForm.scanStatus = "æªæ«ç "; |
| | | scanForm.scanRemark = ""; |
| | | scanRecords.value = []; |
| | | scanDialogVisible.value = true; |
| | | }; |
| | | |
| | | // å
³éæ«ç ç»è®°å¯¹è¯æ¡ |
| | | const closeScanDialog = () => { |
| | | scanDialogVisible.value = false; |
| | | proxy.resetForm("scanFormRef"); |
| | | }; |
| | | |
| | | // æäº¤æ«ç ç»è®° |
| | | const submitScan = () => { |
| | | proxy.$refs["scanFormRef"].validate(valid => { |
| | | if (valid) { |
| | | // æ·»å æ«ç è®°å½ |
| | | scanRecords.value.push({ |
| | | ...scanForm, |
| | | id: Date.now(), // 模æID |
| | | scanTime: getCurrentDateTime(), |
| | | }); |
| | | scanForm.scanStatus = "å·²æ«ç "; |
| | | scanForm.scanRemark = scanForm.scanRemark || "æ "; |
| | | proxy.$modal.msgSuccess("æ«ç ç»è®°æåï¼"); |
| | | closeScanDialog(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // è·åå½åæ¥ææ¶é´ |
| | | function getCurrentDateTime() { |
| | | const now = new Date(); |
| | | const year = now.getFullYear(); |
| | | const month = String(now.getMonth() + 1).padStart(2, "0"); |
| | | const day = String(now.getDate()).padStart(2, "0"); |
| | | const hours = String(now.getHours()).padStart(2, "0"); |
| | | const minutes = String(now.getMinutes()).padStart(2, "0"); |
| | | const seconds = String(now.getSeconds()).padStart(2, "0"); |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | } |
| | | }; |
| | | |
| | | // æ·»å è¡ç±»åæ¹æ³ |
| | | const tableRowClassName = ({ row }) => { |
| | | return row.isInvalid ? 'invalid-row' : ''; |
| | | }; |
| | | // æ·»å è¡ç±»åæ¹æ³ |
| | | const tableRowClassName = ({ row }) => { |
| | | return row.isInvalid ? "invalid-row" : ""; |
| | | }; |
| | | |
| | | // è·å模æ¿ä¿¡æ¯ |
| | | const getTemplateList =async ()=>{ |
| | | let res = await getPurchaseTemplateList() |
| | | if(res && res.code===200 && Array.isArray(res.data)){ |
| | | templateList.value = res.data |
| | | } |
| | | } |
| | | // è·å模æ¿ä¿¡æ¯ |
| | | const getTemplateList = async () => { |
| | | let res = await getPurchaseTemplateList(); |
| | | if (res && res.code === 200 && Array.isArray(res.data)) { |
| | | templateList.value = res.data; |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | getTemplateList(); |
| | | |
| | | }); |
| | | onMounted(() => { |
| | | getList(); |
| | | getTemplateList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .invalid-row { |
| | | opacity: 0.6; |
| | | background-color: #f5f7fa; |
| | | } |
| | | .el-row{ |
| | | justify-content: space-between; |
| | | align-items: center |
| | | } |
| | | .no-arrow-select { |
| | | --el-select-suffix-icon-color: transparent; /* éèé»è®¤ä¸æç®å¤´ */ |
| | | } |
| | | .select-button-group { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .invalid-row { |
| | | opacity: 0.6; |
| | | background-color: #f5f7fa; |
| | | } |
| | | .el-row { |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .no-arrow-select { |
| | | --el-select-suffix-icon-color: transparent; /* éèé»è®¤ä¸æç®å¤´ */ |
| | | } |
| | | .select-button-group { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | </style> |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/basic/customer/export", {}, "çäº§æ ¸ç®.xlsx"); |
| | | proxy.download("/salesLedger/productionAccounting/export", {}, "çäº§æ ¸ç®.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | 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"; |
| | |
| | | { |
| | | label: "å·¥èºè·¯çº¿ç¼å·", |
| | | prop: "processRouteCode", |
| | | width: '140px', |
| | | width: '200px', |
| | | }, |
| | | { |
| | | label: "éæ±æ°é", |
| | |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import {productionReport, productionReportUpdate} from "@/api/productionManagement/productionReporting.js"; |
| | | const { proxy } = getCurrentInstance() |
| | |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥åç¶æ:"> |
| | | <el-select v-model="searchForm.workOrderStatus" |
| | | placeholder="è¯·éæ©å·¥åç¶æ" |
| | | style="width: 140px" |
| | | clearable> |
| | | <el-option label="å¾
确认" |
| | | :value="1"></el-option> |
| | | <el-option label="å¾
ç产" |
| | | :value="2"></el-option> |
| | | <el-option label="ç产ä¸" |
| | | :value="3"></el-option> |
| | | <el-option label="å·²ç产" |
| | | :value="4"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="handleQuery">æç´¢</el-button> |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/salesLedger/work/export", {}, "ç产æ¥å·¥.xlsx"); |
| | | proxy.download("/productionProductMain/export", {}, "ç产æ¥å·¥.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import { |
| | | qualityInspectParamDel, |
| | |
| | | <el-input v-model="form.model" placeholder="请è¾å
¥" clearable/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ææ éæ©ï¼" prop="testStandardId"> |
| | | <el-select |
| | | v-model="form.testStandardId" |
| | | placeholder="è¯·éæ©ææ " |
| | | clearable |
| | | @change="handleTestStandardChange" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="item in testStandardOptions" |
| | | :key="item.id" |
| | | :label="item.standardName || item.standardNo" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue"; |
| | | import {getOptions} from "@/api/procurementManagement/procurementLedger.js"; |
| | | import {productTreeList} from "@/api/basicData/product.js"; |
| | | import {qualityInspectAdd, qualityInspectUpdate} from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import {userListNoPage} from "@/api/system/user.js"; |
| | | import {qualityInspectDetailByProductId} from "@/api/qualityManagement/metricMaintenance.js"; |
| | | import {qualityInspectDetailByProductId, getQualityTestStandardParamByTestStandardId} from "@/api/qualityManagement/metricMaintenance.js"; |
| | | import {qualityInspectParamInfo} from "@/api/qualityManagement/qualityInspectParam.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | |
| | | productName: "", |
| | | productId: "", |
| | | model: "", |
| | | testStandardId: "", |
| | | unit: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | |
| | | checkName: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | productId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | model: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | testStandardId: [{required: true, message: "è¯·éæ©ææ ", trigger: "change"}], |
| | | unit: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | quantity: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkCompany: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | |
| | | const tableLoading = ref(false); |
| | | const userList = ref([]); |
| | | const currentProductId = ref(0); |
| | | const testStandardOptions = ref([]); // ææ éæ©ä¸ææ¡æ°æ® |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = async (type, row) => { |
| | |
| | | let userLists = await userListNoPage(); |
| | | userList.value = userLists.data; |
| | | form.value = {} |
| | | testStandardOptions.value = []; |
| | | tableData.value = []; |
| | | getProductOptions(); |
| | | if (operationType.value === 'edit') { |
| | | form.value = {...row} |
| | | // å
ä¿å testStandardIdï¼é¿å
被æ¸
空 |
| | | const savedTestStandardId = row.testStandardId; |
| | | // å
è®¾ç½®è¡¨åæ°æ®ï¼ä½ææ¶æ¸
空 testStandardIdï¼çé项å è½½å®æåå设置 |
| | | form.value = {...row, testStandardId: ''} |
| | | currentProductId.value = row.productId || 0 |
| | | getQualityInspectParamList(row.id) |
| | | // ç¼è¾æ¨¡å¼ä¸ï¼å
å è½½ææ é项ï¼ç¶åå è½½åæ°å表 |
| | | if (currentProductId.value) { |
| | | // å
å è½½ææ é项 |
| | | let params = { |
| | | productId: currentProductId.value, |
| | | inspectType: 2 |
| | | } |
| | | qualityInspectDetailByProductId(params).then(res => { |
| | | testStandardOptions.value = res.data || []; |
| | | // ä½¿ç¨ nextTick å setTimeout ç¡®ä¿éé¡¹å·²ç»æ¸²æå° DOM |
| | | nextTick(() => { |
| | | setTimeout(() => { |
| | | // 妿ç¼è¾æ°æ®ä¸æ testStandardIdï¼å设置并å 载对åºçåæ° |
| | | if (savedTestStandardId) { |
| | | // ç¡®ä¿ç±»åå¹é
ï¼item.id å¯è½æ¯æ°åæåç¬¦ä¸²ï¼ |
| | | const matchedOption = testStandardOptions.value.find(item => |
| | | item.id == savedTestStandardId || String(item.id) === String(savedTestStandardId) |
| | | ); |
| | | if (matchedOption) { |
| | | // ç¡®ä¿ä½¿ç¨å¹é
项ç idï¼ä¿æç±»åä¸è´ï¼ |
| | | form.value.testStandardId = matchedOption.id; |
| | | console.log(22222,form.value.testStandardId); |
| | | handleTestStandardChange(matchedOption.id); |
| | | } else { |
| | | // 妿æ¾ä¸å°å¹é
项ï¼å°è¯ç´æ¥ä½¿ç¨åå¼ |
| | | console.warn('æªæ¾å°å¹é
çææ é项ï¼testStandardId:', savedTestStandardId, 'å¯ç¨é项:', testStandardOptions.value); |
| | | form.value.testStandardId = savedTestStandardId; |
| | | handleTestStandardChange(savedTestStandardId); |
| | | } |
| | | } else { |
| | | // å¦åä½¿ç¨æ§çé»è¾ |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | }, 100); |
| | | }); |
| | | }); |
| | | } else { |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | } |
| | | } |
| | | const getProductOptions = () => { |
| | |
| | | const getModels = (value) => { |
| | | currentProductId.value = value |
| | | form.value.productName = findNodeById(productOptions.value, value); |
| | | if (currentProductId) { |
| | | if (currentProductId.value) { |
| | | getList(); |
| | | } |
| | | }; |
| | |
| | | }) |
| | | } |
| | | const getList = () => { |
| | | qualityInspectDetailByProductId(currentProductId.value).then(res => { |
| | | tableData.value = res.data; |
| | | if (!currentProductId.value) { |
| | | testStandardOptions.value = []; |
| | | tableData.value = []; |
| | | return; |
| | | } |
| | | let params = { |
| | | productId: currentProductId.value, |
| | | inspectType: 2 |
| | | } |
| | | qualityInspectDetailByProductId(params).then(res => { |
| | | // ä¿å䏿æ¡éé¡¹æ°æ® |
| | | testStandardOptions.value = res.data || []; |
| | | // æ¸
ç©ºè¡¨æ ¼æ°æ®ï¼çå¾
ç¨æ·éæ©ææ |
| | | tableData.value = []; |
| | | // æ¸
ç©ºææ éæ© |
| | | form.value.testStandardId = ''; |
| | | }) |
| | | } |
| | | |
| | | // ææ éæ©ååå¤ç |
| | | const handleTestStandardChange = (testStandardId) => { |
| | | if (!testStandardId) { |
| | | tableData.value = []; |
| | | return; |
| | | } |
| | | tableLoading.value = true; |
| | | getQualityTestStandardParamByTestStandardId(testStandardId).then(res => { |
| | | tableData.value = res.data || []; |
| | | }).catch(error => { |
| | | console.error('è·åæ ååæ°å¤±è´¥:', error); |
| | | tableData.value = []; |
| | | }).finally(() => { |
| | | tableLoading.value = false; |
| | | }) |
| | | } |
| | | const getQualityInspectParamList = (id) => { |
| | | qualityInspectParamInfo(id).then(res => { |
| | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | tableData.value = []; |
| | | testStandardOptions.value = []; |
| | | form.value.testStandardId = ''; |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | | }; |
| | |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import { |
| | | qualityInspectParamDel, |
| | |
| | | :isSelection="false" |
| | | :rowClassName="rowClassNameCenter" |
| | | :tableLoading="tableLoading" |
| | | :rowClick="handleTableRowClick" |
| | | @pagination="handlePagination" |
| | | :total="page.total" |
| | | > |
| | |
| | | } |
| | | |
| | | const standardColumns = ref([ |
| | | { label: 'æ åç¼å·', prop: 'standardNo', dataType: 'slot', slot: 'standardNoCell', minWidth: 160, headerSlot: 'standardNoHeader' }, |
| | | { label: 'æ ååç§°', prop: 'standardName', minWidth: 180, headerSlot: 'standardNameHeader' }, |
| | | { label: 'æ åç¼å·', prop: 'standardNo', dataType: 'slot', slot: 'standardNoCell', minWidth: 160, align: 'center', headerSlot: 'standardNoHeader' }, |
| | | { label: 'æ ååç§°', prop: 'standardName', minWidth: 180, align: 'center', headerSlot: 'standardNameHeader' }, |
| | | { |
| | | label: 'ç±»å«', |
| | | prop: 'inspectType', |
| | | headerSlot: 'inspectTypeHeader', |
| | | align: 'center', |
| | | dataType: 'tag', |
| | | formatData: (val) => { |
| | | const map = { 0: 'åæææ£éª', 1: 'è¿ç¨æ£éª', 2: 'åºåæ£éª' } |
| | |
| | | { |
| | | label: 'å·¥åº', |
| | | prop: 'processId', |
| | | align: 'center', |
| | | dataType: 'tag', |
| | | formatData: (val) => { |
| | | const target = processOptions.value.find( |
| | |
| | | { |
| | | label: '夿³¨', |
| | | prop: 'remark', |
| | | minWidth: 160 |
| | | minWidth: 160, |
| | | align: 'center' |
| | | } |
| | | // { |
| | | // label: 'ç¶æ', |
| | |
| | | }) |
| | | } |
| | | |
| | | // è¡¨æ ¼è¡ç¹å»ï¼å è½½å³ä¾§ç»å®å表 |
| | | const handleTableRowClick = (row) => { |
| | | currentStandard.value = row |
| | | loadBindingList() |
| | | } |
| | | |
| | | // 左侧è¡ç¹å»ï¼å è½½å³ä¾§ç»å®å表ï¼ä¿çç¨äºæ åç¼å·åçç¹å»ï¼ |
| | | const handleStandardRowClick = (row) => { |
| | | currentStandard.value = row |
| | | loadBindingList() |
| | |
| | | :deep(.center-table .el-table__body-wrapper td .cell) { |
| | | text-align: center !important; |
| | | } |
| | | |
| | | /* PIMTable 表头å±
ä¸ */ |
| | | :deep(.lims-table .pim-table-header-cell) { |
| | | text-align: center; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | :deep(.lims-table .pim-table-header-title) { |
| | | text-align: center; |
| | | width: 100%; |
| | | } |
| | | |
| | | :deep(.lims-table .pim-table-header-extra) { |
| | | width: 100%; |
| | | margin-top: 4px; |
| | | } |
| | | </style> |
| | |
| | | :isSelection="true" |
| | | :tableLoading="tableLoading" |
| | | :rowClassName="rowClassNameCenter" |
| | | :rowClick="handleTableRowClick" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="handlePagination" |
| | | :total="page.total" |
| | |
| | | standardNo: [{ required: true, message: '请è¾å
¥æ åç¼å·', trigger: 'blur' }], |
| | | standardName: [{ required: true, message: '请è¾å
¥æ ååç§°', trigger: 'blur' }], |
| | | inspectType: [{ required: true, message: 'è¯·éæ©æ£æµç±»å', trigger: 'change' }], |
| | | processId: [{ required: true, message: 'è¯·éæ©å·¥åº', trigger: 'change' }] |
| | | processId: [{ required: false, message: 'è¯·éæ©å·¥åº', trigger: 'change' }] |
| | | } |
| | | }) |
| | | |
| | |
| | | dataType: 'slot', |
| | | slot: 'standardNoCell', |
| | | minWidth: 160, |
| | | align: 'center', |
| | | headerSlot: 'standardNoHeader' |
| | | }, |
| | | { |
| | | label: 'æ ååç§°', |
| | | prop: 'standardName', |
| | | minWidth: 180, |
| | | align: 'center', |
| | | headerSlot: 'standardNameHeader' |
| | | }, |
| | | { |
| | | label: 'ç±»å«', |
| | | prop: 'inspectType', |
| | | headerSlot: 'inspectTypeHeader', |
| | | align: 'center', |
| | | dataType: 'tag', |
| | | formatData: (val) => { |
| | | const map = { |
| | |
| | | { |
| | | label: 'å·¥åº', |
| | | prop: 'processId', |
| | | align: 'center', |
| | | dataType: 'tag', |
| | | formatData: (val) => { |
| | | const target = processOptions.value.find( |
| | |
| | | label: 'ç¶æ', |
| | | prop: 'state', |
| | | headerSlot: 'stateHeader', |
| | | align: 'center', |
| | | dataType: 'tag', |
| | | formatData: (val) => { |
| | | const map = { |
| | |
| | | { |
| | | label: '夿³¨', |
| | | prop: 'remark', |
| | | minWidth: 160 |
| | | minWidth: 160, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | dataType: 'action', |
| | |
| | | getStandardList() |
| | | } |
| | | |
| | | // 左侧è¡ç¹å»ï¼å è½½å³ä¾§åæ° |
| | | // è¡¨æ ¼è¡ç¹å»ï¼å è½½å³ä¾§åæ° |
| | | const handleTableRowClick = (row) => { |
| | | currentStandard.value = row |
| | | loadDetail(row.id) |
| | | } |
| | | |
| | | // 左侧è¡ç¹å»ï¼å è½½å³ä¾§åæ°ï¼ä¿çç¨äºæ åç¼å·åçç¹å»ï¼ |
| | | const handleStandardRowClick = (row) => { |
| | | currentStandard.value = row |
| | | loadDetail(row.id) |
| | |
| | | processId: '' |
| | | }) |
| | | } else if (type === 'edit' && row) { |
| | | Object.assign(standardForm.value, row) |
| | | Object.assign(standardForm.value, { |
| | | ...row, |
| | | // ç¡®ä¿ inspectType å state 转æ¢ä¸ºå符串ï¼ä»¥å¹é
el-select ç value ç±»å |
| | | inspectType: row.inspectType !== null && row.inspectType !== undefined ? String(row.inspectType) : '', |
| | | state: row.state !== null && row.state !== undefined ? String(row.state) : '0', |
| | | // ç¡®ä¿ processId 转æ¢ä¸ºåç¬¦ä¸²ææ°åï¼æ ¹æ®å®é
éè¦ï¼ |
| | | processId: row.processId !== null && row.processId !== undefined ? row.processId : '' |
| | | }) |
| | | } else if (type === 'copy' && row) { |
| | | const { id, ...rest } = row |
| | | Object.assign(standardForm.value, { |
| | | ...rest, |
| | | id: undefined, |
| | | standardNo: '', |
| | | state: '0' |
| | | state: '0', |
| | | // ç¡®ä¿ inspectType 转æ¢ä¸ºå符串 |
| | | inspectType: rest.inspectType !== null && rest.inspectType !== undefined ? String(rest.inspectType) : '' |
| | | }) |
| | | } |
| | | standardDialogVisible.value = true |
| | |
| | | .metric-maintenance { |
| | | display: flex; |
| | | gap: 16px; |
| | | min-width: 0; /* å
许 flex åå
ç´ æ¶ç¼© */ |
| | | } |
| | | |
| | | .left-panel, |
| | | .right-panel { |
| | | flex: 1; |
| | | min-width: 0; /* å
许 flex åå
ç´ æ¶ç¼© */ |
| | | background: #ffffff; |
| | | padding: 16px; |
| | | box-sizing: border-box; |
| | | overflow: hidden; /* 鲿¢å
å®¹æº¢åº */ |
| | | } |
| | | |
| | | /* ä½å辨çéé
*/ |
| | | @media (max-width: 1400px) { |
| | | .metric-maintenance { |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .left-panel, |
| | | .right-panel { |
| | | width: 100%; |
| | | min-width: 0; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .metric-maintenance { |
| | | gap: 12px; |
| | | } |
| | | |
| | | .left-panel, |
| | | .right-panel { |
| | | padding: 12px; |
| | | } |
| | | } |
| | | |
| | | .toolbar { |
| | |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 12px; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .toolbar-left { |
| | |
| | | |
| | | .toolbar-right { |
| | | flex-shrink: 0; |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .search-label { |
| | |
| | | :deep(.center-table .el-table__body-wrapper td .cell) { |
| | | text-align: center !important; |
| | | } |
| | | |
| | | /* PIMTable 表头å±
ä¸ */ |
| | | :deep(.lims-table .pim-table-header-cell) { |
| | | text-align: center; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | :deep(.lims-table .pim-table-header-title) { |
| | | text-align: center; |
| | | width: 100%; |
| | | } |
| | | |
| | | :deep(.lims-table .pim-table-header-extra) { |
| | | width: 100%; |
| | | margin-top: 4px; |
| | | } |
| | | </style> |
| | |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å·¥åºï¼" prop="process"> |
| | | <el-input v-model="form.process" placeholder="请è¾å
¥" clearable/> |
| | | <el-form-item label="å·¥åºï¼" prop="processId"> |
| | | <el-select |
| | | v-model="form.processId" |
| | | placeholder="è¯·éæ©å·¥åº" |
| | | clearable |
| | | @change="handleProcessChange" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="item in processOptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="model"> |
| | | <el-input v-model="form.model" placeholder="请è¾å
¥" clearable/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ææ éæ©ï¼" prop="testStandardId"> |
| | | <el-select |
| | | v-model="form.testStandardId" |
| | | placeholder="è¯·éæ©ææ " |
| | | clearable |
| | | @change="handleTestStandardChange" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="item in testStandardOptions" |
| | | :key="item.id" |
| | | :label="item.standardName || item.standardNo" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue"; |
| | | import {getOptions} from "@/api/procurementManagement/procurementLedger.js"; |
| | | import {productTreeList} from "@/api/basicData/product.js"; |
| | | import {productProcessListPage} from "@/api/basicData/productProcess.js"; |
| | | import {qualityInspectAdd, qualityInspectUpdate} from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import {qualityInspectDetailByProductId} from "@/api/qualityManagement/metricMaintenance.js"; |
| | | import {qualityInspectDetailByProductId, getQualityTestStandardParamByTestStandardId} from "@/api/qualityManagement/metricMaintenance.js"; |
| | | import {userListNoPage} from "@/api/system/user.js"; |
| | | import {qualityInspectParamInfo} from "@/api/qualityManagement/qualityInspectParam.js"; |
| | | const { proxy } = getCurrentInstance() |
| | |
| | | const data = reactive({ |
| | | form: { |
| | | checkTime: "", |
| | | process: "", |
| | | processId: "", |
| | | checkName: "", |
| | | productName: "", |
| | | productId: "", |
| | | model: "", |
| | | testStandardId: "", |
| | | unit: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | |
| | | }, |
| | | rules: { |
| | | checkTime: [{ required: true, message: "请è¾å
¥", trigger: "blur" },], |
| | | process: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | processId: [{ required: true, message: "è¯·éæ©å·¥åº", trigger: "change" }], |
| | | checkName: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | productId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | model: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | testStandardId: [{required: true, message: "è¯·éæ©ææ ", trigger: "change"}], |
| | | unit: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | quantity: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkCompany: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const currentProductId = ref(0); |
| | | const processOptions = ref([]); // å·¥åºä¸ææ¡æ°æ® |
| | | const testStandardOptions = ref([]); // ææ éæ©ä¸ææ¡æ°æ® |
| | | |
| | | // è·åå·¥åºå表 |
| | | const getProcessList = async () => { |
| | | try { |
| | | const res = await productProcessListPage({ current: 1, size: 1000 }) |
| | | if (res?.code === 200) { |
| | | const records = res?.data?.records || [] |
| | | processOptions.value = records.map(item => ({ |
| | | label: item.processName || item.name || item.label, |
| | | value: item.id || item.processId || item.value |
| | | })) |
| | | } |
| | | } catch (error) { |
| | | console.error('è·åå·¥åºå表失败:', error) |
| | | } |
| | | } |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = async (type, row) => { |
| | |
| | | let userLists = await userListNoPage(); |
| | | userList.value = userLists.data; |
| | | form.value = {} |
| | | testStandardOptions.value = []; |
| | | tableData.value = []; |
| | | getProductOptions(); |
| | | // å
å 载工åºå表 |
| | | await getProcessList(); |
| | | if (operationType.value === 'edit') { |
| | | form.value = {...row} |
| | | // å
ä¿å testStandardIdï¼é¿å
被æ¸
空 |
| | | const savedTestStandardId = row.testStandardId; |
| | | // å
è®¾ç½®è¡¨åæ°æ®ï¼ä½ææ¶æ¸
空 testStandardIdï¼çé项å è½½å®æåå设置 |
| | | form.value = {...row, testStandardId: ''} |
| | | // å
¼å®¹æ§æ°æ®ï¼å¦æ row 䏿 process åæ®µï¼è½¬æ¢ä¸º processId |
| | | if (row.process && !row.processId) { |
| | | // å°è¯ä» processOptions 䏿¥æ¾å¹é
çå·¥åº |
| | | const processOption = processOptions.value.find(p => p.label === row.process); |
| | | if (processOption) { |
| | | form.value.processId = processOption.value; |
| | | } |
| | | } |
| | | currentProductId.value = row.productId || 0 |
| | | getQualityInspectParamList(row.id) |
| | | // ç¼è¾æ¨¡å¼ä¸ï¼å
å è½½ææ é项ï¼ç¶åå è½½åæ°å表 |
| | | if (currentProductId.value) { |
| | | // å
å è½½ææ é项 |
| | | let params = { |
| | | productId: currentProductId.value, |
| | | inspectType: 1, |
| | | process: form.value.processId ? processOptions.value.find(p => p.value === form.value.processId)?.label : '' |
| | | } |
| | | qualityInspectDetailByProductId(params).then(res => { |
| | | testStandardOptions.value = res.data || []; |
| | | // ä½¿ç¨ nextTick å setTimeout ç¡®ä¿éé¡¹å·²ç»æ¸²æå° DOM |
| | | nextTick(() => { |
| | | setTimeout(() => { |
| | | // 妿ç¼è¾æ°æ®ä¸æ testStandardIdï¼å设置并å 载对åºçåæ° |
| | | if (savedTestStandardId) { |
| | | // ç¡®ä¿ç±»åå¹é
ï¼item.id å¯è½æ¯æ°åæåç¬¦ä¸²ï¼ |
| | | const matchedOption = testStandardOptions.value.find(item => |
| | | item.id == savedTestStandardId || String(item.id) === String(savedTestStandardId) |
| | | ); |
| | | if (matchedOption) { |
| | | // ç¡®ä¿ä½¿ç¨å¹é
项ç idï¼ä¿æç±»åä¸è´ï¼ |
| | | form.value.testStandardId = matchedOption.id; |
| | | handleTestStandardChange(matchedOption.id); |
| | | } else { |
| | | // 妿æ¾ä¸å°å¹é
项ï¼å°è¯ç´æ¥ä½¿ç¨åå¼ |
| | | console.warn('æªæ¾å°å¹é
çææ é项ï¼testStandardId:', savedTestStandardId, 'å¯ç¨é项:', testStandardOptions.value); |
| | | form.value.testStandardId = savedTestStandardId; |
| | | handleTestStandardChange(savedTestStandardId); |
| | | } |
| | | } else { |
| | | // å¦åä½¿ç¨æ§çé»è¾ |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | }, 100); |
| | | }); |
| | | }); |
| | | } else { |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | } |
| | | } |
| | | const getProductOptions = () => { |
| | |
| | | const getModels = (value) => { |
| | | currentProductId.value = value |
| | | form.value.productName = findNodeById(productOptions.value, value); |
| | | if (currentProductId) { |
| | | if (currentProductId.value) { |
| | | getList(); |
| | | } |
| | | }; |
| | |
| | | return newItem; |
| | | }); |
| | | } |
| | | // å·¥åºååå¤ç |
| | | const handleProcessChange = () => { |
| | | // å·¥åºååæ¶ï¼å¦æå·²éæ©äº§åï¼éæ°å è½½ææ å表 |
| | | if (currentProductId.value) { |
| | | getList(); |
| | | } |
| | | } |
| | | |
| | | // æäº¤äº§å表å |
| | | const submitForm = () => { |
| | | proxy.$refs.formRef.validate(valid => { |
| | | if (valid) { |
| | | form.value.inspectType = 1 |
| | | // å° processId 转æ¢ä¸º process åç§°ï¼å¦æå端éè¦ process åæ®µï¼ |
| | | const processName = form.value.processId ? processOptions.value.find(p => p.value === form.value.processId)?.label : ''; |
| | | if (operationType.value === "add") { |
| | | tableData.value.forEach((item) => { |
| | | delete item.id |
| | | }) |
| | | } |
| | | const data = {...form.value, qualityInspectParams: tableData.value} |
| | | const data = { |
| | | ...form.value, |
| | | process: processName, // ä¿ç process åæ®µä»¥å
¼å®¹å端 |
| | | qualityInspectParams: tableData.value |
| | | } |
| | | if (operationType.value === "add") { |
| | | qualityInspectAdd(data).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | |
| | | }) |
| | | } |
| | | const getList = () => { |
| | | qualityInspectDetailByProductId(currentProductId.value).then(res => { |
| | | tableData.value = res.data; |
| | | if (!currentProductId.value) { |
| | | testStandardOptions.value = []; |
| | | tableData.value = []; |
| | | return; |
| | | } |
| | | // è·åå·¥åºåç§° |
| | | const processName = form.value.processId ? processOptions.value.find(p => p.value === form.value.processId)?.label : ''; |
| | | let params = { |
| | | productId: currentProductId.value, |
| | | inspectType: 1, |
| | | process: processName |
| | | } |
| | | qualityInspectDetailByProductId(params).then(res => { |
| | | // ä¿å䏿æ¡éé¡¹æ°æ® |
| | | testStandardOptions.value = res.data || []; |
| | | // æ¸
ç©ºè¡¨æ ¼æ°æ®ï¼çå¾
ç¨æ·éæ©ææ |
| | | tableData.value = []; |
| | | // æ¸
ç©ºææ éæ© |
| | | form.value.testStandardId = ''; |
| | | }) |
| | | } |
| | | |
| | | // ææ éæ©ååå¤ç |
| | | const handleTestStandardChange = (testStandardId) => { |
| | | if (!testStandardId) { |
| | | tableData.value = []; |
| | | return; |
| | | } |
| | | tableLoading.value = true; |
| | | getQualityTestStandardParamByTestStandardId(testStandardId).then(res => { |
| | | tableData.value = res.data || []; |
| | | }).catch(error => { |
| | | console.error('è·åæ ååæ°å¤±è´¥:', error); |
| | | tableData.value = []; |
| | | }).finally(() => { |
| | | tableLoading.value = false; |
| | | }) |
| | | } |
| | | const getQualityInspectParamList = (id) => { |
| | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | tableData.value = []; |
| | | testStandardOptions.value = []; |
| | | form.value.testStandardId = ''; |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | | }; |
| | |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import { |
| | | qualityInspectParamDel, |
| | |
| | | <el-input v-model="form.model" placeholder="请è¾å
¥" clearable/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ææ éæ©ï¼" prop="testStandardId"> |
| | | <el-select |
| | | v-model="form.testStandardId" |
| | | placeholder="è¯·éæ©ææ " |
| | | clearable |
| | | @change="handleTestStandardChange" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="item in testStandardOptions" |
| | | :key="item.id" |
| | | :label="item.standardName || item.standardNo" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue"; |
| | | import {getOptions} from "@/api/procurementManagement/procurementLedger.js"; |
| | | import {productTreeList} from "@/api/basicData/product.js"; |
| | | import {qualityInspectAdd, qualityInspectUpdate} from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import {qualityInspectParamDel, qualityInspectParamInfo} from "@/api/qualityManagement/qualityInspectParam.js"; |
| | | import {qualityInspectDetailByProductId} from "@/api/qualityManagement/metricMaintenance.js"; |
| | | import {qualityInspectDetailByProductId, getQualityTestStandardParamByTestStandardId} from "@/api/qualityManagement/metricMaintenance.js"; |
| | | |
| | | const {proxy} = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | |
| | | productName: "", |
| | | productId: "", |
| | | model: "", |
| | | testStandardId: "", |
| | | unit: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | |
| | | checkName: [{required: false, message: "请è¾å
¥", trigger: "blur"}], |
| | | productId: [{required: true, message: "请è¾å
¥", trigger: "blur"}], |
| | | model: [{required: false, message: "请è¾å
¥", trigger: "blur"}], |
| | | testStandardId: [{required: true, message: "è¯·éæ©ææ ", trigger: "change"}], |
| | | unit: [{required: false, message: "请è¾å
¥", trigger: "blur"}], |
| | | quantity: [{required: true, message: "请è¾å
¥", trigger: "blur"}], |
| | | checkCompany: [{required: false, message: "请è¾å
¥", trigger: "blur"}], |
| | |
| | | const supplierList = ref([]); |
| | | const productOptions = ref([]); |
| | | const currentProductId = ref(0); |
| | | const testStandardOptions = ref([]); // ææ éæ©ä¸ææ¡æ°æ® |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | |
| | | supplierList.value = res.data; |
| | | }); |
| | | form.value = {} |
| | | testStandardOptions.value = []; |
| | | tableData.value = []; |
| | | getProductOptions(); |
| | | if (operationType.value === 'edit') { |
| | | // å
ä¿å testStandardIdï¼é¿å
被æ¸
空 |
| | | const savedTestStandardId = row.testStandardId; |
| | | form.value = {...row} |
| | | currentProductId.value = row.productId || 0 |
| | | getQualityInspectParamList(row.id) |
| | | // ç¼è¾æ¨¡å¼ä¸ï¼å
å è½½ææ é项ï¼ç¶åå è½½åæ°å表 |
| | | if (currentProductId.value) { |
| | | // å
å è½½ææ é项 |
| | | let params = { |
| | | productId: currentProductId.value, |
| | | inspectType: 0 |
| | | } |
| | | qualityInspectDetailByProductId(params).then(res => { |
| | | testStandardOptions.value = res.data || []; |
| | | // ä½¿ç¨ nextTick å setTimeout ç¡®ä¿éé¡¹å·²ç»æ¸²æå° DOM |
| | | nextTick(() => { |
| | | setTimeout(() => { |
| | | // 妿ç¼è¾æ°æ®ä¸æ testStandardIdï¼å设置并å 载对åºçåæ° |
| | | if (savedTestStandardId) { |
| | | // ç¡®ä¿ç±»åå¹é
ï¼item.id å¯è½æ¯æ°åæåç¬¦ä¸²ï¼ |
| | | const matchedOption = testStandardOptions.value.find(item => |
| | | item.id == savedTestStandardId || String(item.id) === String(savedTestStandardId) |
| | | ); |
| | | if (matchedOption) { |
| | | // ç¡®ä¿ä½¿ç¨å¹é
项ç idï¼ä¿æç±»åä¸è´ï¼ |
| | | form.value.testStandardId = matchedOption.id; |
| | | handleTestStandardChange(matchedOption.id); |
| | | } else { |
| | | // 妿æ¾ä¸å°å¹é
项ï¼å°è¯ç´æ¥ä½¿ç¨åå¼ |
| | | console.warn('æªæ¾å°å¹é
çææ é项ï¼testStandardId:', savedTestStandardId, 'å¯ç¨é项:', testStandardOptions.value); |
| | | form.value.testStandardId = savedTestStandardId; |
| | | handleTestStandardChange(savedTestStandardId); |
| | | } |
| | | } else { |
| | | // å¦åä½¿ç¨æ§çé»è¾ |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | }, 100); |
| | | }); |
| | | }); |
| | | } else { |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | } |
| | | } |
| | | const getProductOptions = () => { |
| | |
| | | const getModels = (value) => { |
| | | currentProductId.value = value |
| | | form.value.productName = findNodeById(productOptions.value, value); |
| | | if (currentProductId) { |
| | | if (currentProductId.value) { |
| | | getList(); |
| | | } |
| | | }; |
| | |
| | | } |
| | | |
| | | const getList = () => { |
| | | qualityInspectDetailByProductId(currentProductId.value).then(res => { |
| | | tableData.value = res.data; |
| | | if (!currentProductId.value) { |
| | | testStandardOptions.value = []; |
| | | tableData.value = []; |
| | | return; |
| | | } |
| | | let params = { |
| | | productId: currentProductId.value, |
| | | inspectType: 0 |
| | | } |
| | | qualityInspectDetailByProductId(params).then(res => { |
| | | // ä¿å䏿æ¡éé¡¹æ°æ® |
| | | testStandardOptions.value = res.data || []; |
| | | // æ¸
ç©ºè¡¨æ ¼æ°æ®ï¼çå¾
ç¨æ·éæ©ææ |
| | | tableData.value = []; |
| | | // æ¸
ç©ºææ éæ© |
| | | form.value.testStandardId = ''; |
| | | }) |
| | | } |
| | | |
| | | // ææ éæ©ååå¤ç |
| | | const handleTestStandardChange = (testStandardId) => { |
| | | if (!testStandardId) { |
| | | tableData.value = []; |
| | | return; |
| | | } |
| | | tableLoading.value = true; |
| | | getQualityTestStandardParamByTestStandardId(testStandardId).then(res => { |
| | | tableData.value = res.data || []; |
| | | }).catch(error => { |
| | | console.error('è·åæ ååæ°å¤±è´¥:', error); |
| | | tableData.value = []; |
| | | }).finally(() => { |
| | | tableLoading.value = false; |
| | | }) |
| | | } |
| | | |
| | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | tableData.value = [] |
| | | tableData.value = []; |
| | | testStandardOptions.value = []; |
| | | form.value.testStandardId = ''; |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | | }; |
| | |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import { |
| | | qualityInspectParamDel, |
| | |
| | | <div class="left-panel"> |
| | | <!-- 客æ·ä¿¡æ¯ç»è®¡åæ --> |
| | | <div class="panel-header"> |
| | | <span class="panel-title">客æ·ä¿¡æ¯ç»è®¡åæ</span> |
| | | <span class="panel-title">å¨å¶åç»è®¡åæ</span> |
| | | </div> |
| | | <div class="panel-item-customers"> |
| | | <div class="panel-title-second"> |
| | | <div class="panel-title-icon"></div> |
| | | <div class="total-customers"> |
| | | <span class="label">æ»ååéé¢(å
)</span> |
| | | <span class="value">{{sum}}</span> |
| | | <div class="quality-cards"> |
| | | <div class="quality-cardSec"> |
| | | <div class="quality-card one"></div> |
| | | <div class="quality-cardTitle"> |
| | | <div>æ»å¨å¶æ°é</div> |
| | | <div>{{workInProcessStatistics.totalQuantity}}ä»¶</div> |
| | | </div> |
| | | </div> |
| | | <!-- <div class="jiantou"></div>--> |
| | | <div class="quality-cardSec"> |
| | | <div class="quality-card two"></div> |
| | | <div class="quality-cardTitle"> |
| | | <div>å¹³åå¨è½¬å¤©æ°</div> |
| | | <div>{{workInProcessStatistics.avgTurnoverDays}}天</div> |
| | | </div> |
| | | </div> |
| | | <div class="quality-cardSec"> |
| | | <div class="quality-card three"></div> |
| | | <div class="quality-cardTitle"> |
| | | <div>å¨è½¬æç</div> |
| | | <div>{{workInProcessStatistics.turnoverEfficiency}}%</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- 饼å¾åºå --> |
| | | <div style="display: flex;align-items: center;gap: 20px;justify-content: space-evenly;height: 82%;margin-top: 20px"> |
| | | <div style="width: 240px; height: 240px; background-image: url('/src/assets/BI/zonghetongbingtubiankuang@2x.png'); background-size: contain; background-position: center; background-repeat: no-repeat; display: flex; align-items: center; justify-content: center;"> |
| | | <Echarts ref="chart" :legend="pieLegend" :chartStyle="chartStylePie" |
| | | :series="materialPieSeries" |
| | | :tooltip="pieTooltip" |
| | | :options="{backgroundColor: 'transparent'}" |
| | | style="margin-left: 5px;"></Echarts> |
| | | </div> |
| | | <ul class="contract-list" style="margin: 0; padding: 0; display: flex; flex-direction: column;justify-content: space-around; height: 100%; overflow-y: auto; scroll-behavior: smooth;" ref="refContractList"> |
| | | <li v-for="item in materialPieSeries[0].data" :key="item.name" style="list-style: none; margin-bottom: 12px;"> |
| | | <div style="display: flex;align-items: center;justify-content: space-between;width: 100%"> |
| | | <div class="line" :style="{color: item.itemStyle.color}">â {{item.name}}</div> |
| | | <div style="font-weight: 700;font-size: 16px;color: #85B1E4;">ï¿¥{{item.value}}</div> |
| | | </div> |
| | | </li> |
| | | </ul> |
| | | <!-- å·¥åºå¨å¶åæ°éæ±ç¶å¾ --> |
| | | <div style="height: 82%;margin-top: 20px"> |
| | | <Echarts ref="chart" |
| | | :chartStyle="chartStyle" |
| | | :grid="grid" |
| | | :legend="workInProcessBarLegend" |
| | | :series="workInProcessBarSeries" |
| | | :tooltip="tooltip" |
| | | :xAxis="workInProcessXAxis" |
| | | :yAxis="workInProcessYAxis" |
| | | :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}" |
| | | style="height: 100%"></Echarts> |
| | | </div> |
| | | </div> |
| | | |
| | |
| | | <div class="quality-cardSec"> |
| | | <div class="quality-card one"></div> |
| | | <div class="quality-cardTitle"> |
| | | <div>åææå·²æ£æµæ°</div> |
| | | <div>åæææ£æ°</div> |
| | | <div>{{qualityStatisticsObject.supplierNum}}ä»¶</div> |
| | | </div> |
| | | </div> |
| | | <div class="quality-cardSec"> |
| | | <div class="quality-card two"></div> |
| | | <div class="quality-cardTitle"> |
| | | <div>è¿ç¨æ£éªæ°é</div> |
| | | <div>è¿ç¨æ£æ°</div> |
| | | <div>{{qualityStatisticsObject.processNum}}ä»¶</div> |
| | | </div> |
| | | </div> |
| | | <div class="quality-cardSec"> |
| | | <div class="quality-card three"></div> |
| | | <div class="quality-cardTitle"> |
| | | <div>åºåå·²æ£æ°é</div> |
| | | <div>åºåæ£æ°</div> |
| | | <div>{{qualityStatisticsObject.factoryNum}}ä»¶</div> |
| | | </div> |
| | | </div> |
| | |
| | | </div> |
| | | <div class="main-panel"> |
| | | <div class="panel-item-customers"> |
| | | <div class="event-header"> |
| | | <img src="@/assets/BI/shijianmingxiicon@2x.png" alt="徿 " class="event-icon" /> |
| | | <span class="event-title">ç»è¥åæ</span> |
| | | <div class="order-statistics-cards" style="margin-bottom: 0px;"> |
| | | <div class="quality-cardSec"> |
| | | <div class="quality-card four"></div> |
| | | <div class="quality-cardTitle"> |
| | | <div>æ»è®¢åæ°</div> |
| | | <div>{{orderStatisticsObject.totalOrderCount}}ä»¶</div> |
| | | </div> |
| | | </div> |
| | | <div class="quality-cardSec"> |
| | | <div class="quality-card five"></div> |
| | | <div class="quality-cardTitle"> |
| | | <div>æªå®æè®¢åæ°</div> |
| | | <div>{{orderStatisticsObject.uncompletedOrderCount}}ä»¶</div> |
| | | </div> |
| | | </div> |
| | | <div class="quality-cardSec"> |
| | | <div class="quality-card six"></div> |
| | | <div class="quality-cardTitle"> |
| | | <div>é¨åå®æè®¢åæ°</div> |
| | | <div>{{orderStatisticsObject.partialCompletedOrderCount}}ä»¶</div> |
| | | </div> |
| | | </div> |
| | | <div class="quality-cardSec"> |
| | | <div class="quality-card seven"></div> |
| | | <div class="quality-cardTitle"> |
| | | <div>å·²å®æè®¢åæ°</div> |
| | | <div>{{orderStatisticsObject.completedOrderCount}}ä»¶</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <Echarts ref="chart" |
| | | :chartStyle="chartStyle" |
| | | :grid="grid" |
| | | :legend="barLegend1" |
| | | :series="barSeries11" |
| | | :tooltip="tooltip" |
| | | :xAxis="xAxis3" |
| | | :yAxis="yAxis3" |
| | | :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}" |
| | | style="height: 170px"></Echarts> |
| | | <div class="progress-table-container" ref="progressTableRef" style="margin-top: 0px;" @scroll="handleTableScroll"> |
| | | <table class="progress-table"> |
| | | <thead> |
| | | <tr> |
| | | <th>ç产订åå·</th> |
| | | <th>产ååç§°</th> |
| | | <th>è§æ ¼</th> |
| | | <th>éæ±æ°é</th> |
| | | <th>宿æ°é</th> |
| | | <th>宿è¿åº¦</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr |
| | | v-for="(item, index) in progressTableData" |
| | | :key="index" |
| | | :ref="el => setRowRef(el, index)" |
| | | :class="{ 'row-under-header': isRowUnderHeader(index) }" |
| | | > |
| | | <td>{{ item.npsNo || '-' }}</td> |
| | | <td>{{ item.productCategory || '-' }}</td> |
| | | <td>{{ item.specificationModel || '-' }}</td> |
| | | <td>{{ item.quantity || 0 }}</td> |
| | | <td>{{ item.completeQuantity || 0 }}</td> |
| | | <td> |
| | | <el-progress |
| | | :percentage="calculateProgress(item)" |
| | | :color="progressColor(calculateProgress(item))" |
| | | :status="calculateProgress(item) >= 100 ? 'success' : ''" |
| | | :stroke-width="8" |
| | | /> |
| | | </td> |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | getProgressStatistics, |
| | | getWorkInProcessTurnover |
| | | } from "@/api/viewIndex.js"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/employeeRecord.js"; |
| | | import {listCustomer} from "@/api/basicData/customerFile.js"; |
| | | import {listSupplier} from "@/api/basicData/supplierManageFile.js"; |
| | | import {getLedgerPage} from "@/api/equipmentManagement/ledger.js"; |
| | |
| | | import {getUpkeepPage} from "@/api/equipmentManagement/upkeep.js"; |
| | | import {measuringInstrumentListPage} from "@/api/equipmentManagement/measurementEquipment.js"; |
| | | import {listPageAnalysis} from "@/api/financialManagement/expenseManagement.js"; |
| | | import {productOrderListPage} from "@/api/productionManagement/productionOrder.js"; |
| | | |
| | | // å
¨å±ç¸å
³ç¶æ |
| | | const isFullscreen = ref(false); |
| | |
| | | const realtimeLineChartRef = ref(null) |
| | | const refContractList = ref(null) |
| | | const refTodoList = ref(null) |
| | | const progressTableRef = ref(null) |
| | | const timerScroll = ref(null) |
| | | const progressTableScrollTimer = ref(null) |
| | | const isTableScrolling = ref(false) |
| | | const tableScrollTimeout = ref(null) |
| | | const tableRowRefs = ref([]) |
| | | const rowsUnderHeader = ref(new Set()) |
| | | |
| | | const chartStylePie = { |
| | | width: '140%', |
| | | height: '140%' // 设置å¾è¡¨å®¹å¨çé«åº¦ |
| | | width: '100%', |
| | | height: '100%' // 设置å¾è¡¨å®¹å¨çé«åº¦ |
| | | } |
| | | const materialPieSeries = ref([ |
| | | { |
| | |
| | | supplierNum: 0, |
| | | processNum: 0, |
| | | factoryNum: 0, |
| | | }) |
| | | |
| | | // 订åç»è®¡å¯¹è±¡ |
| | | const orderStatisticsObject = ref({ |
| | | totalOrderCount: 0, |
| | | uncompletedOrderCount: 0, |
| | | partialCompletedOrderCount: 0, |
| | | completedOrderCount: 0, |
| | | }) |
| | | |
| | | // å¨å¶åå¨è½¬ç»è®¡å¯¹è±¡ |
| | | const workInProcessStatistics = ref({ |
| | | totalQuantity: 0, |
| | | avgTurnoverDays: 0, |
| | | turnoverEfficiency: 0, |
| | | }) |
| | | const chartStyle = { |
| | | width: '100%', |
| | |
| | | axisLabel: { color: '#B8C8E0' } |
| | | }] |
| | | |
| | | // å¨å¶åå·¥åºæ±ç¶å¾é
ç½® |
| | | const workInProcessXAxis = ref([{ |
| | | type: 'category', |
| | | axisTick: { show: false }, |
| | | axisLabel: { color: '#B8C8E0' }, |
| | | data: [] |
| | | }]) |
| | | const workInProcessYAxis = [{ |
| | | type: 'value', |
| | | axisLabel: { color: '#B8C8E0' }, |
| | | name: '' |
| | | }] |
| | | const workInProcessBarLegend = { |
| | | show: false, |
| | | textStyle: { color: '#B8C8E0' }, |
| | | data: [] |
| | | } |
| | | const workInProcessBarSeries = ref([ |
| | | { |
| | | name: 'å¨å¶åæ°é', |
| | | type: 'bar', |
| | | barWidth: 25, // åºå®æ±ç¶å¾å®½åº¦ä¸º40px |
| | | barGap: 0, |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, |
| | | itemStyle: { |
| | | color: { |
| | | type: 'linear', |
| | | x: 0, |
| | | y: 0, |
| | | x2: 0, |
| | | y2: 1, |
| | | colorStops: [ |
| | | { offset: 0, color: '#4EE4FF' }, |
| | | { offset: 1, color: '#00A4ED' } |
| | | ] |
| | | } |
| | | }, |
| | | label: { |
| | | show: true, |
| | | position: 'top', |
| | | color: '#B8C8E0' |
| | | }, |
| | | data: [] |
| | | } |
| | | ]) |
| | | |
| | | // å¾
åäºé¡¹ |
| | | const todoList = ref([]) |
| | | |
| | | // ç产订å宿è¿åº¦è¡¨æ ¼æ°æ® |
| | | const progressTableData = ref([]) |
| | | |
| | | // 计ç®å®æè¿åº¦ç¾åæ¯ |
| | | const calculateProgress = (item) => { |
| | | if (!item) return 0 |
| | | // ä¼å
使ç¨completionStatusåæ®µ |
| | | if (item.completionStatus !== undefined && item.completionStatus !== null) { |
| | | const percentage = Number(item.completionStatus) |
| | | if (isNaN(percentage)) return 0 |
| | | return Math.min(Math.max(Math.round(percentage), 0), 100) |
| | | } |
| | | // å¦ææ²¡æcompletionStatusï¼åæ ¹æ®å®ææ°éåéæ±æ°éè®¡ç® |
| | | if (!item.quantity || item.quantity === 0) return 0 |
| | | const percentage = (item.completeQuantity || 0) / item.quantity * 100 |
| | | return Math.min(Math.max(Math.round(percentage), 0), 100) |
| | | } |
| | | |
| | | // æ ¹æ®è¿åº¦ç¾åæ¯è¿åé¢è² |
| | | const progressColor = (percentage) => { |
| | | const p = percentage || 0 |
| | | if (p < 30) return "#f56c6c" |
| | | if (p < 50) return "#e6a23c" |
| | | if (p < 80) return "#409eff" |
| | | return "#67c23a" |
| | | } |
| | | |
| | | // 计ç®ç¼©æ¾æ¯ä¾ |
| | | const calculateScale = () => { |
| | |
| | | })) |
| | | }) |
| | | } |
| | | // å¨å¶åå¨è½¬ç»è®¡ |
| | | const workInProcessTurnoverInfo = () => { |
| | | getWorkInProcessTurnover().then((res) => { |
| | | console.log("å¨å¶åå¨è½¬ç»è®¡æ°æ®:", res) |
| | | |
| | | if (!res || !res.data) { |
| | | console.warn('å¨å¶åå¨è½¬ç»è®¡æ°æ®ä¸ºç©º') |
| | | return |
| | | } |
| | | |
| | | // 仿¥å£è·åç»è®¡æ°æ® |
| | | workInProcessStatistics.value = { |
| | | totalQuantity: res.data.totalOrderCount || 0, |
| | | avgTurnoverDays: res.data.averageTurnoverDays || 0, |
| | | turnoverEfficiency: res.data.turnoverEfficiency || 0, |
| | | } |
| | | |
| | | // è®¾ç½®å·¥åºæ±ç¶å¾æ°æ® |
| | | // Xè½´ï¼processDetails (å·¥åºè¯¦æ
æ°ç») |
| | | // Yè½´ï¼processQuantityDetails (å·¥åºæ°é详æ
æ°ç») |
| | | if (res.data.processDetails && Array.isArray(res.data.processDetails)) { |
| | | // 设置Xè½´æ°æ®ï¼å·¥åºåç§°ï¼ |
| | | workInProcessXAxis.value[0].data = res.data.processDetails |
| | | } else { |
| | | workInProcessXAxis.value[0].data = [] |
| | | } |
| | | |
| | | if (res.data.processQuantityDetails && Array.isArray(res.data.processQuantityDetails)) { |
| | | // 设置Yè½´æ°æ®ï¼å¨å¶åæ°éï¼ |
| | | workInProcessBarSeries.value[0].data = res.data.processQuantityDetails |
| | | } else { |
| | | workInProcessBarSeries.value[0].data = [] |
| | | } |
| | | }).catch((error) => { |
| | | console.error('è·åå¨å¶åå¨è½¬ç»è®¡å¤±è´¥:', error) |
| | | }) |
| | | } |
| | | // è´¨æ£ç»è®¡ |
| | | const qualityStatisticsInfo = () => { |
| | | qualityStatistics().then((res) => { |
| | |
| | | } |
| | | // åç产订åç宿è¿åº¦ç»è®¡ |
| | | const progressStatisticsInfo = () => { |
| | | // ä»ç»è®¡æ¥å£è·åç»è®¡æ°æ® |
| | | getProgressStatistics().then((res) => { |
| | | console.log("ç产订å宿è¿åº¦ç»è®¡æ°æ®:", res) |
| | | |
| | |
| | | return |
| | | } |
| | | |
| | | // 设置Xè½´æ°æ® - 使ç¨åç±»åç§° |
| | | xAxis3.value[0].data = ['已宿è¿åº¦æ°', 'æ»è®¢åæ°', 'æªå®æè®¢åæ°', 'å·²å®æè®¢åæ°'] |
| | | |
| | | // 设置å个系åçæ°æ® - æ¯ä¸ªXè½´å类对åºä¸ä¸ªå¼ |
| | | if (barSeries11.value && barSeries11.value.length > 0) { |
| | | barSeries11.value[0].data = [ |
| | | res.data.completedProgressCount || 0, |
| | | res.data.totalOrderCount || 0, |
| | | res.data.uncompletedOrderCount || 0, |
| | | res.data.completedOrderCount || 0 |
| | | ] |
| | | // 仿¥å£è·åç»è®¡æ°æ® |
| | | orderStatisticsObject.value = { |
| | | totalOrderCount: res.data.totalOrderCount || 0, |
| | | uncompletedOrderCount: res.data.uncompletedOrderCount || 0, |
| | | partialCompletedOrderCount: res.data.partialCompletedOrderCount || 0, |
| | | completedOrderCount: res.data.completedOrderCount || 0 |
| | | } |
| | | progressTableData.value = res.data.completedOrderDetails || [] |
| | | // éç½®è¡å¼ç¨ |
| | | tableRowRefs.value = [] |
| | | rowsUnderHeader.value.clear() |
| | | |
| | | console.log('å¾è¡¨æ°æ®è®¾ç½®å®æ:', { |
| | | xAxis: xAxis3.value[0].data, |
| | | series: barSeries11.value[0]?.data |
| | | // å¨è·åå°æ°æ®åï¼åå§åæ»å¨åè½ |
| | | nextTick(() => { |
| | | initProgressTableScroll() |
| | | }) |
| | | |
| | | }).catch((error) => { |
| | | console.error('è·åç产订å宿è¿åº¦ç»è®¡å¤±è´¥:', error) |
| | | }) |
| | |
| | | |
| | | // èªå¨è½®æ¢å¨ãæãå£åº¦ç宿¶å¨ |
| | | const autoSwitchTimer = ref(null) |
| | | |
| | | // 设置è¡å¼ç¨ |
| | | const setRowRef = (el, index) => { |
| | | if (el) { |
| | | tableRowRefs.value[index] = el |
| | | } |
| | | } |
| | | |
| | | // å¤æè¡æ¯å¦å¨è¡¨å¤´ä¸æ¹ |
| | | const isRowUnderHeader = (index) => { |
| | | return rowsUnderHeader.value.has(index) |
| | | } |
| | | |
| | | // å¤çè¡¨æ ¼æ»å¨äºä»¶ |
| | | const handleTableScroll = () => { |
| | | const tableContainer = progressTableRef.value |
| | | if (!tableContainer) return |
| | | |
| | | const thead = tableContainer.querySelector('thead') |
| | | if (!thead) return |
| | | |
| | | const theadHeight = thead.offsetHeight |
| | | const containerRect = tableContainer.getBoundingClientRect() |
| | | const containerTop = containerRect.top |
| | | const theadBottom = containerTop + theadHeight |
| | | |
| | | // æ¸
空ä¹åçè®°å½ |
| | | rowsUnderHeader.value.clear() |
| | | |
| | | // æ£æ¥æ¯ä¸è¡æ¯å¦å¨è¡¨å¤´ä¸æ¹ï¼è¢«è¡¨å¤´é®æ¡ï¼ |
| | | tableRowRefs.value.forEach((row, index) => { |
| | | if (row) { |
| | | const rowRect = row.getBoundingClientRect() |
| | | const rowTop = rowRect.top |
| | | const rowBottom = rowRect.bottom |
| | | |
| | | // 妿è¡ä¸è¡¨å¤´æéå ï¼è¡å¨è¡¨å¤´ä¸æ¹è¢«é®æ¡ï¼ |
| | | // è¡çé¡¶é¨å¨è¡¨å¤´åºé¨ä¸æ¹ï¼ä½è¡çåºé¨å¨è¡¨å¤´åºé¨ä¸æ¹ï¼è¯´æè¢«é®æ¡ |
| | | if (rowTop < theadBottom && rowBottom > containerTop) { |
| | | rowsUnderHeader.value.add(index) |
| | | } |
| | | } |
| | | }) |
| | | |
| | | // æ¸
é¤ä¹åç宿¶å¨ |
| | | if (tableScrollTimeout.value) { |
| | | clearTimeout(tableScrollTimeout.value) |
| | | } |
| | | |
| | | // æ»å¨åæ¢åæ¸
ç©ºæ·¡åæ è®° |
| | | tableScrollTimeout.value = setTimeout(() => { |
| | | rowsUnderHeader.value.clear() |
| | | }, 150) |
| | | } |
| | | |
| | | // åå§åç产订åè¿åº¦è¡¨æ ¼æ»å¨åè½ |
| | | const initProgressTableScroll = () => { |
| | | const tableContainer = progressTableRef.value |
| | | if (!tableContainer) return |
| | | |
| | | // æ¸
çä¹åçæ»å¨å¨ç»å宿¶å¨ |
| | | if (progressTableScrollTimer.value) { |
| | | cancelAnimationFrame(progressTableScrollTimer.value) |
| | | progressTableScrollTimer.value = null |
| | | } |
| | | if (tableContainer._pauseTimer) { |
| | | clearInterval(tableContainer._pauseTimer) |
| | | tableContainer._pauseTimer = null |
| | | } |
| | | |
| | | const tbody = tableContainer.querySelector('tbody') |
| | | if (!tbody) return |
| | | |
| | | // æ¸
çä¹åå¯è½åå¨çå
éè¡ï¼ä¿çåå§æ°æ®è¡ï¼ |
| | | // åå§æ°æ®è¡çæ°éåºè¯¥çäº progressTableData.value.length |
| | | const originalCount = progressTableData.value.length |
| | | const allRows = Array.from(tbody.querySelectorAll('tr')) |
| | | if (allRows.length > originalCount) { |
| | | // ç§»é¤ææè¶
è¿åå§æ°éçè¡ï¼è¿äºæ¯å
éçè¡ï¼ |
| | | for (let i = originalCount; i < allRows.length; i++) { |
| | | allRows[i].remove() |
| | | } |
| | | } |
| | | |
| | | const scrollItems = Array.from(tbody.querySelectorAll('tr')) |
| | | if (scrollItems.length === 0) return |
| | | |
| | | // è·ååå§æ°æ®é¡¹æ°é |
| | | const originalItemCount = scrollItems.length |
| | | |
| | | // 计ç®å®¹å¨é«åº¦å表头é«åº¦ |
| | | const thead = tableContainer.querySelector('thead') |
| | | const theadHeight = thead ? thead.offsetHeight : 40 |
| | | const containerHeight = tableContainer.clientHeight |
| | | const visibleHeight = containerHeight - theadHeight |
| | | |
| | | // 计ç®åå§æ°æ®çæ»é«åº¦ |
| | | const itemHeight = scrollItems[0]?.offsetHeight || 40 |
| | | const totalContentHeight = itemHeight * originalItemCount |
| | | |
| | | // å¦ææ°æ®éä¸å¤ï¼å®¹å¨å¯ä»¥å®å
¨æ¾ç¤ºæææ°æ®ï¼å°±ä¸éè¦æ»å¨åå
é |
| | | if (totalContentHeight <= visibleHeight) { |
| | | // æ°æ®éå°ï¼ä¸éè¦æ»å¨ï¼ç´æ¥è¿å |
| | | return |
| | | } |
| | | |
| | | // æ°æ®éè¶³å¤ï¼éè¦æ»å¨ï¼è¿è¡å
é以å®ç°æ ç¼æ»å¨ |
| | | const cloneCount = Math.ceil(visibleHeight / itemHeight) + 2 |
| | | |
| | | // å
éåå 个项ç®å¹¶æ·»å å°å表æ«å°¾ï¼å®ç°æ ç¼æ»å¨ |
| | | for (let i = 0; i < cloneCount; i++) { |
| | | const clone = scrollItems[i % originalItemCount].cloneNode(true) |
| | | tbody.appendChild(clone) |
| | | } |
| | | |
| | | let scrollPosition = 0 |
| | | const scrollSpeed = 1.5 |
| | | const pauseTime = 3000 |
| | | let isPaused = false |
| | | let lastTimestamp = 0 |
| | | |
| | | // è¿ç»æ»å¨å¨ç»å½æ° |
| | | function scrollAnimation(timestamp) { |
| | | if (!lastTimestamp) lastTimestamp = timestamp |
| | | const deltaTime = timestamp - lastTimestamp |
| | | lastTimestamp = timestamp |
| | | |
| | | if (!isPaused) { |
| | | scrollPosition += scrollSpeed * (deltaTime / 16) |
| | | |
| | | // è®¡ç®æå¤§æ»å¨ä½ç½®ï¼åå§å
容çé«åº¦ï¼ |
| | | const maxScroll = itemHeight * originalItemCount |
| | | |
| | | // 彿»å¨è¶
è¿åå§å
容é¿åº¦æ¶ï¼éç½®ä½ç½®å®ç°æ ç¼æ»å¨ |
| | | if (scrollPosition >= maxScroll) { |
| | | scrollPosition = 0 |
| | | tableContainer.scrollTop = 0 |
| | | } else { |
| | | tableContainer.scrollTop = scrollPosition |
| | | } |
| | | } |
| | | |
| | | progressTableScrollTimer.value = requestAnimationFrame(scrollAnimation) |
| | | } |
| | | |
| | | // å¯å¨æ»å¨å¨ç» |
| | | progressTableScrollTimer.value = requestAnimationFrame(scrollAnimation) |
| | | |
| | | // 设置æ»å¨-æå-æ»å¨çå¾ªç¯ææ |
| | | const pauseTimer = setInterval(() => { |
| | | isPaused = !isPaused |
| | | }, pauseTime) |
| | | |
| | | // æ¸
ç宿¶å¨ |
| | | tableContainer._pauseTimer = pauseTimer |
| | | } |
| | | |
| | | // åå§åå¾
åäºé¡¹å表æ»å¨åè½ |
| | | const initTodoListScroll = () => { |
| | | const todoList = refTodoList.value |
| | |
| | | window.addEventListener('webkitfullscreenchange', handleFullscreenChange) |
| | | window.addEventListener('MSFullscreenChange', handleFullscreenChange) |
| | | analysisCustomer() |
| | | workInProcessTurnoverInfo() |
| | | qualityStatisticsInfo() |
| | | // accountStatisticsInfo() |
| | | progressStatisticsInfo() |
| | |
| | | clearInterval(todoList._pauseTimer) |
| | | todoList._pauseTimer = null |
| | | } |
| | | } |
| | | |
| | | // æ¸
çç产订åè¿åº¦è¡¨æ ¼çå¨ç»å宿¶å¨ |
| | | const progressTable = progressTableRef.value |
| | | if (progressTable) { |
| | | if (progressTableScrollTimer.value) { |
| | | cancelAnimationFrame(progressTableScrollTimer.value) |
| | | progressTableScrollTimer.value = null |
| | | } |
| | | if (progressTable._pauseTimer) { |
| | | clearInterval(progressTable._pauseTimer) |
| | | progressTable._pauseTimer = null |
| | | } |
| | | } |
| | | |
| | | // æ¸
çè¡¨æ ¼æ»å¨å®æ¶å¨ |
| | | if (tableScrollTimeout.value) { |
| | | clearTimeout(tableScrollTimeout.value) |
| | | tableScrollTimeout.value = null |
| | | } |
| | | |
| | | // æ¸
çèªå¨è½®æ¢å¨ãæãå£åº¦ç宿¶å¨ |
| | |
| | | } |
| | | .quality-card.three { |
| | | background-image: url("@/assets/BI/chuchangyijianicon@2x.png"); |
| | | |
| | | } |
| | | |
| | | /* 订åç»è®¡å¡çæ ·å¼ */ |
| | | .order-statistics-cards { |
| | | display: flex; |
| | | gap: 12px; |
| | | width: 100%; |
| | | height: 94px; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .quality-card.four { |
| | | background-image: url("@/assets/BI/yuancailiaoyijianicon@2x.png"); |
| | | } |
| | | |
| | | .quality-card.five { |
| | | background-image: url("@/assets/BI/guochengyijianicon@2x.png"); |
| | | } |
| | | |
| | | .quality-card.six { |
| | | background-image: url("@/assets/BI/chuchangyijianicon@2x.png"); |
| | | } |
| | | |
| | | .quality-card.seven { |
| | | background-image: url("@/assets/BI/yuancailiaoyijianicon@2x.png"); |
| | | } |
| | | .panel-title-icon { |
| | | width: 60px; |
| | |
| | | border-color: rgba(255, 255, 255, 0.5); |
| | | box-shadow: -1px 0 0 0 rgba(255, 255, 255, 0.5); |
| | | } |
| | | |
| | | /* ç产订åè¿åº¦è¡¨æ ¼æ ·å¼ */ |
| | | .progress-table-container { |
| | | height: 250px; |
| | | overflow-y: auto; |
| | | overflow-x: hidden; |
| | | margin-top: 10px; |
| | | scrollbar-width: none; /* Firefox */ |
| | | -ms-overflow-style: none; /* IEåEdge */ |
| | | } |
| | | |
| | | .progress-table-container::-webkit-scrollbar { |
| | | display: none; /* ChromeãSafariåOpera */ |
| | | } |
| | | |
| | | .progress-table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | color: #B8C8E0; |
| | | font-size: 12px; |
| | | table-layout: fixed; |
| | | } |
| | | |
| | | .progress-table thead { |
| | | position: sticky; |
| | | top: 0; |
| | | background-color: rgba(26, 88, 176, 0.9); |
| | | z-index: 10; |
| | | } |
| | | |
| | | .progress-table th { |
| | | padding: 8px 6px; |
| | | text-align: left; |
| | | font-weight: 500; |
| | | border-bottom: 1px solid rgba(184, 200, 224, 0.3); |
| | | color: #B8C8E0; |
| | | font-size: 12px; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | |
| | | .progress-table th:nth-child(1) { width: 15%; } /* ç产订åå· */ |
| | | .progress-table th:nth-child(2) { width: 15%; } /* 产ååç§° */ |
| | | .progress-table th:nth-child(3) { width: 15%; } /* è§æ ¼ */ |
| | | .progress-table th:nth-child(4) { width: 12%; } /* éæ±æ°é */ |
| | | .progress-table th:nth-child(5) { width: 12%; } /* 宿æ°é */ |
| | | .progress-table th:nth-child(6) { width: 31%; } /* 宿è¿åº¦ */ |
| | | |
| | | .progress-table td { |
| | | padding: 8px 6px; |
| | | border-bottom: 1px solid rgba(184, 200, 224, 0.1); |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | font-size: 12px; |
| | | transition: opacity 0.3s ease; |
| | | } |
| | | |
| | | .progress-table tbody tr:hover { |
| | | background-color: rgba(184, 200, 224, 0.1); |
| | | } |
| | | |
| | | .progress-table tbody tr.row-under-header { |
| | | opacity: 0.5; |
| | | } |
| | | |
| | | /* el-progress ç»ä»¶æ ·å¼è°æ´ */ |
| | | .progress-table :deep(.el-progress) { |
| | | width: 100%; |
| | | } |
| | | |
| | | .progress-table :deep(.el-progress-bar__outer) { |
| | | background-color: rgba(184, 200, 224, 0.2); |
| | | } |
| | | |
| | | .progress-table :deep(.el-progress__text) { |
| | | color: #B8C8E0; |
| | | font-size: 11px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-form :model="filters" :inline="true" label-width="80px"> |
| | | <el-form-item label="客æ·åç§°"> |
| | | <el-input v-model="filters.customerName" placeholder="请è¾å
¥å®¢æ·åç§°" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="getTableData"> æç´¢ </el-button> |
| | | <el-button @click="resetFilters"> éç½® </el-button> |
| | | <el-button @click="handleOut"> å¯¼åº </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="columns" |
| | | :tableLoading="loading" |
| | | :tableData="dataList" |
| | | :page="{ |
| | | <div class="app-container"> |
| | | <el-form :model="filters" :inline="true" label-width="80px"> |
| | | <el-form-item label="客æ·åç§°"> |
| | | <el-input v-model="filters.customerName" placeholder="请è¾å
¥å®¢æ·åç§°" clearable style="width: 240px"/> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="getTableData"> æç´¢ </el-button> |
| | | <el-button @click="resetFilters"> éç½® </el-button> |
| | | <el-button @click="handleOut"> å¯¼åº </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="columns" |
| | | :tableLoading="loading" |
| | | :tableData="dataList" |
| | | :page="{ |
| | | current: pagination.currentPage, |
| | | size: pagination.pageSize, |
| | | total: pagination.total, |
| | | total: pagination.total |
| | | }" |
| | | @pagination="changePage" |
| | | ></PIMTable> |
| | | </div> |
| | | </div> |
| | | :isShowSummary="true" |
| | | :summaryMethod="summarizeMainTable" |
| | | @pagination="changePage" |
| | | ></PIMTable> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | defineOptions({ |
| | | name: "项ç®å©æ¶¦", |
| | | name: "项ç®å©æ¶¦", |
| | | }); |
| | | |
| | | const { |
| | | loading, |
| | | filters, |
| | | columns, |
| | | dataList, |
| | | pagination, |
| | | getTableData, |
| | | resetFilters, |
| | | onCurrentChange, |
| | | loading, |
| | | filters, |
| | | columns, |
| | | dataList, |
| | | pagination, |
| | | getTableData, |
| | | resetFilters, |
| | | onCurrentChange, |
| | | } = usePaginationApi( |
| | | getPurchaseList, |
| | | { |
| | | customerName: undefined, |
| | | }, |
| | | [ |
| | | { |
| | | label: "éå®ååå·", |
| | | align: "center", |
| | | prop: "customerContractNo", |
| | | }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | align: "center", |
| | | prop: "customerName", |
| | | }, |
| | | { |
| | | label: "项ç®åç§°", |
| | | align: "center", |
| | | prop: "projectName", |
| | | }, |
| | | { |
| | | label: "ååéé¢", |
| | | align: "center", |
| | | prop: "contractAmount", |
| | | }, |
| | | { |
| | | label: "éè´éé¢", |
| | | align: "center", |
| | | prop: "purchaseAmount", |
| | | }, |
| | | { |
| | | label: "婿¶¦", |
| | | align: "center", |
| | | prop: "balance", |
| | | }, |
| | | { |
| | | label: "婿¶¦ç", |
| | | align: "center", |
| | | prop: "balanceRatio", |
| | | }, |
| | | { |
| | | label: "å¢å¼ç¨", |
| | | align: "center", |
| | | prop: "balanceAmount", |
| | | }, |
| | | ] |
| | | getPurchaseList, |
| | | { |
| | | customerName: undefined, |
| | | }, |
| | | [ |
| | | { |
| | | label: "éå®ååå·", |
| | | align: "center", |
| | | prop: "customerContractNo", |
| | | }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | align: "center", |
| | | prop: "customerName", |
| | | }, |
| | | { |
| | | label: "ååéé¢", |
| | | align: "center", |
| | | prop: "contractAmount", |
| | | }, |
| | | { |
| | | label: "éè´éé¢", |
| | | align: "center", |
| | | prop: "purchaseAmount", |
| | | }, |
| | | { |
| | | label: "婿¶¦", |
| | | align: "center", |
| | | prop: "balance", |
| | | }, |
| | | { |
| | | label: "婿¶¦ç", |
| | | align: "center", |
| | | prop: "balanceRatio", |
| | | }, |
| | | ] |
| | | ); |
| | | |
| | | const changePage = ({ page }) => { |
| | | pagination.currentPage = page; |
| | | onCurrentChange(page); |
| | | const changePage = ({ page, limit }) => { |
| | | pagination.currentPage = page; |
| | | pagination.pageSize = limit; |
| | | onCurrentChange(page); |
| | | }; |
| | | |
| | | // 主表åè®¡æ¹æ³ |
| | | const summarizeMainTable = (param) => { |
| | | return proxy.summarizeTable(param, ["contractAmount", "purchaseAmount", "balance"]); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/purchase/report/export", {}, "项ç®å©æ¶¦.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/purchase/report/export", {}, "项ç®å©æ¶¦.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getTableData(); |
| | | getTableData(); |
| | | }); |
| | | </script> |
| | | <style lang="scss" scoped> |
| | | .table_list { |
| | | margin-top: unset; |
| | | margin-top: unset; |
| | | } |
| | | </style> |
| | |
| | | <span class="value">{{ formatDate(item.createTime) }}</span> |
| | | </div> |
| | | <div> |
| | | |
| | | |
| | | <span class="label">客æ·åç§°ï¼</span> |
| | | <span class="value">{{ item.customerName || 'å¼ ç±æ' }}</span> |
| | | </div> |
| | |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <FileList ref="fileListRef" /> |
| | | <FileListDialog ref="fileListRef" v-model="fileListDialogVisible" /> |
| | | <!-- 导å
¥å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | :title="importUpload.title" |
| | | v-model="importUpload.open" |
| | | width="400px" |
| | | append-to-body |
| | | > |
| | | <el-upload |
| | | ref="importUploadRef" |
| | | :limit="1" |
| | | accept=".xlsx, .xls" |
| | | :headers="importUpload.headers" |
| | | :action="importUpload.url" |
| | | :disabled="importUpload.isUploading" |
| | | :before-upload="importUpload.beforeUpload" |
| | | :on-progress="importUpload.onProgress" |
| | | :on-success="importUpload.onSuccess" |
| | | :on-error="importUpload.onError" |
| | | :on-change="importUpload.onChange" |
| | | :auto-upload="false" |
| | | drag |
| | | > |
| | | <el-icon class="el-icon--upload"><UploadFilled /></el-icon> |
| | | <div class="el-upload__text">å°æä»¶æå°æ¤å¤ï¼æ<em>ç¹å»ä¸ä¼ </em></div> |
| | | <template #tip> |
| | | <div class="el-upload__tip text-center"> |
| | | <span>ä»
å
许导å
¥xlsãxlsxæ ¼å¼æä»¶ã</span> |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitImportFile" :loading="importUpload.isUploading">ç¡® å®</el-button> |
| | | <el-button @click="importUpload.open = false">å æ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getToken } from "@/utils/auth"; |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import {onMounted, ref} from "vue"; |
| | | import {onMounted, ref, getCurrentInstance} from "vue"; |
| | | import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js"; |
| | | import {ElMessage, ElMessageBox} from "element-plus"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import { UploadFilled } from "@element-plus/icons-vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import FileList from "./fileList.vue"; |
| | |
| | | }); |
| | | const { deliveryForm, deliveryRules } = toRefs(deliveryFormData); |
| | | |
| | | // 导å
¥ç¸å
³ |
| | | 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 changeDaterange = (value) => { |
| | | if (value) { |
| | | searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | |
| | | }); |
| | | }; |
| | | const getProductModel = (value) => { |
| | | console.log("value", value); |
| | | const index = modelOptions.value.findIndex((item) => item.id === value); |
| | | if (index !== -1) { |
| | | productForm.value.specificationModel = modelOptions.value[index].model; |
| | |
| | | return null; // æ²¡ææ¾å°èç¹ï¼è¿ånull |
| | | }; |
| | | function convertIdToValue(data) { |
| | | if (!data || !Array.isArray(data)) return []; |
| | | return data.map((item) => { |
| | | const { id, children, ...rest } = item; |
| | | const newItem = { |
| | |
| | | productOperationType.value = type; |
| | | productForm.value = {}; |
| | | proxy.resetForm("productFormRef"); |
| | | // æ°å¢ãç¼è¾é½éå
å è½½äº§åæ ï¼å¦å el-tree-select æ æ°æ® |
| | | try { |
| | | await getProductOptions(); |
| | | } catch (e) { |
| | | console.error("å è½½äº§åæ å¤±è´¥", e); |
| | | } |
| | | if (type === "edit") { |
| | | productForm.value = { ...row }; |
| | | productIndex.value = index; |
| | |
| | | proxy.resetForm("productFormRef"); |
| | | productFormVisible.value = false; |
| | | }; |
| | | // 导å
¥ |
| | | const handleImport = () => { |
| | | importUpload.title = "导å
¥éå®å°è´¦"; |
| | | importUpload.open = true; |
| | | if (importUploadRef.value) { |
| | | importUploadRef.value.clearFiles(); |
| | | } |
| | | }; |
| | | |
| | | // æäº¤å¯¼å
¥æä»¶ |
| | | const submitImportFile = () => { |
| | | importUpload.isUploading = true; |
| | | proxy.$refs["importUploadRef"].submit(); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |