diff --git a/src/api/repair/orderinfo/index.js b/src/api/repair/orderinfo/index.js index 35c6581..56f581e 100644 --- a/src/api/repair/orderinfo/index.js +++ b/src/api/repair/orderinfo/index.js @@ -79,3 +79,14 @@ export function exportData(params){ responseType: 'blob' }) } + + +// 根据ID修改发票信息 +export function updateBilled(data) { + return request({ + url: '/repair/order-info/updateBilled', + method: 'post', + data: data + }) +} + diff --git a/src/utils/createUniqueCode.js b/src/utils/createUniqueCode.js index 58de6a3..54bc505 100644 --- a/src/utils/createUniqueCode.js +++ b/src/utils/createUniqueCode.js @@ -1,4 +1,4 @@ -import {v4 as uuidv4} from 'uuid' +import { v4 as uuidv4 } from 'uuid' /** * 生成UUID @@ -33,5 +33,13 @@ export function createHashCodeByStr(str) { export function createUniqueCodeByHead(head = '') { const min = 100; // 最小值 const max = 999; // 最大值 - return head.toString() + Date.now().toString() + Math.floor(Math.random() * (max - min + 1)) + min; + + // 获取当前日期并格式化为年月日字符串(例如:20231225) + const now = new Date(); + const year = now.getFullYear(); + const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份从0开始,需要+1 + const day = String(now.getDate()).padStart(2, '0'); + const dateStr = `${year}${month}${day}`; + + return head.toString() + dateStr + Math.floor(Math.random() * (max - min + 1)) + min; } diff --git a/src/views/repair/statistics/index.vue b/src/views/repair/statistics/index.vue index f32d987..2419cbe 100644 --- a/src/views/repair/statistics/index.vue +++ b/src/views/repair/statistics/index.vue @@ -126,6 +126,22 @@ + + + + + @@ -133,10 +149,14 @@ import request from "@/utils/request"; import { formatCurrency, getDictByCode, getDateRange } from "@/utils/utils"; // import { checkPermi } from "@/utils/permission"; +import TicketManagerItem from "@/views/repair/tickets/Components/TicketManagerItem.vue"; export default { name: "DetailPagePC", dicts: ["repair_type"], + components: { + TicketManagerItem + }, data() { return { currentTab: "0", @@ -156,12 +176,18 @@ export default { }, dictData: {}, otherInfo: {}, + // 弹窗相关 + listDialogVisible: false, + dialogTitle: "", + dialogQueryParams: {}, + userRole: "all" // 默认角色,实际应用中可能需要动态获取 }; }, async mounted() { this.queryParams.dateRange = getDateRange("day"); // this.loadFinanceVisibility(); this.loadData(); + this.getDict(); }, methods: { // checkPermi, @@ -193,22 +219,53 @@ export default { }, goList(selectType, repairType) { console.log(selectType, repairType, 6666); + + // 设置弹窗标题 + this.dialogTitle = this.dictData[repairType] ? + `${this.dictData[repairType]}工单列表` : + `${this.getSelectTypeName(selectType)}工单列表`; - // 跳转路由 - this.$router.push({ - path: "/repair/tickets/ticket-manager", - query: { - selectType: selectType, - repairType: repairType, - }, - }); + // 设置查询参数 + this.dialogQueryParams = { + selectType: selectType, + repairType: repairType, + searchTimeArray: this.queryParams.dateRange + }; + + // 显示弹窗 + this.listDialogVisible = true; }, goListByPayStatus(payStatus) { - // 跳转路由 - this.$router.push({ - path: "/repair/tickets/ticket-manager", - query: { payStatus: payStatus }, - }); + // 设置弹窗标题 + this.dialogTitle = this.getPayStatusName(payStatus) + "工单列表"; + + // 设置查询参数 + this.dialogQueryParams = { + payStatus: payStatus, + searchTimeArray: this.queryParams.dateRange + }; + + // 显示弹窗 + this.listDialogVisible = true; + }, + getSelectTypeName(selectType) { + const typeMap = { + 'jinchang': '进厂', + 'weixiuzhong': '维修中', + 'yijungong': '已竣工', + 'yijiaoche': '已交车', + 'weijiesuan': '未结算', + 'zaichang': '在厂' + }; + return typeMap[selectType] || '工单'; + }, + getPayStatusName(payStatus) { + const statusMap = { + 'receivable': '应收款', + 'receivedAmount': '已收款', + 'pendingAmount': '待收款' + }; + return statusMap[payStatus] || '工单'; }, formatCurrency(amount) { return formatCurrency(amount); @@ -284,4 +341,4 @@ export default { font-size: 14px; color: #7f8fa4; } - + \ No newline at end of file diff --git a/src/views/repair/stockOperate/Components/SoIndex.vue b/src/views/repair/stockOperate/Components/SoIndex.vue index 4e94f96..17e6545 100644 --- a/src/views/repair/stockOperate/Components/SoIndex.vue +++ b/src/views/repair/stockOperate/Components/SoIndex.vue @@ -94,6 +94,7 @@ {{ scope.row._index + 1 }} + - + - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -240,62 +242,63 @@ + :label="item.label" :value="item.value" /> + :value="item.value" /> A单 B单 + + 选择A单 + 已绑定A单:{{ formData.parentTicketNo + }} + 清除 + 维修工时项目 + :coupon-list="couponList" @changeCoupon="changeCoupon" /> 更换配件清单 + :coupon-list="couponList" @changeCoupon="changeCoupon" ref="partTable" /> 其他 + :coupon-list="couponList" @changeCoupon="changeCoupon" ref="otherTable" /> - - - - - - + style="margin-bottom: 1rem"> + + + + + + - + - + - + {{ formData.count }} {{ formData.projectPrice }} {{ formData.partPrice }} @@ -305,8 +308,8 @@ 完成 - - + + @@ -316,22 +319,25 @@ - + 完成 - + - - - + + + + + + @@ -340,22 +346,23 @@ import UserChoose from "@/views/repair/Components/UserChoose.vue"; import StaffChoose from "@/views/repair/Components/StaffChoose.vue"; import TicketItem from "@/views/repair/tickets/Components/TicketItem.vue"; import CarChoose from "@/views/repair/Components/CarChoose.vue"; -import {createUniqueCodeByHead} from "@/utils/createUniqueCode"; -import {createTickets, getTicketsById} from "@/api/repair/tickets/Tickets"; +import { createUniqueCodeByHead } from "@/utils/createUniqueCode"; +import { createTickets, getTicketsById } from "@/api/repair/tickets/Tickets"; import RepairAdvice from "@/views/repair/tickets/form/RepairAdvice.vue"; import QualityExplain from "@/views/repair/tickets/form/QualityExplain.vue"; import TicketChoose from "@/views/repair/tickets/Components/TicketChoose.vue"; import request from "@/utils/request"; import * as CustomerMainApi from "@/api/base/customer"; import UserAndCarForm from "@/views/repair/tickets/form/UserAndCarForm.vue"; -import {getByNameAndMobile} from "@/api/base/customer"; -import {getByLicenseNumber} from "@/api/base/carmain"; +import { getByNameAndMobile } from "@/api/base/customer"; +import { getByLicenseNumber } from "@/api/base/carmain"; +import ParentTicketDialog from "@/views/repair/tickets/Components/ParentTicketDialog.vue"; export default { name: "UserInfo", components: { UserAndCarForm, - TicketChoose, QualityExplain, RepairAdvice, CarChoose, TicketItem, StaffChoose, UserChoose + ParentTicketDialog, TicketChoose, QualityExplain, RepairAdvice, CarChoose, TicketItem, StaffChoose, UserChoose }, props: { createTicketType: { @@ -444,7 +451,14 @@ export default { handleName: null, handleMobile: null, maintenanceDate: null, - maintenanceMileage: null + maintenanceMileage: null, + parentTicketId: null, // 绑定的A单ID + parentTicketNo: null, // 绑定的A单编号 + channelId: null, // 渠道ID + busiFrom: null, // 渠道名称 + sourceId: null, // 来源ID + cusFrom: null, // 来源名称 + busiCascader: [] // 业务渠道/来源级联选择值 }, selectUser: {}, selectCar: {}, @@ -457,8 +471,17 @@ export default { finaCouponList: [], userInData: null, carInData: null, + ticketChooseDialogVisible: false, // A单选择对话框显示状态 + busiAndCusList: [], // 业务渠道和来源列表 + channelList: [], // 渠道列表 + sourceList: [], // 来源列表 + busiCascaderOptions: [] // 业务渠道/来源级联选择器选项 } }, + mounted() { + // 组件挂载时获取业务渠道和来源数据 + this.queryBusiAndCus() + }, methods: { async getCouponList(id) { const res = await CustomerMainApi.getCustomerMain(id); @@ -530,10 +553,10 @@ export default { this.createItemInit() try { const count = this.handleValidate() - if (count > 0){ + if (count > 0) { return } - if (this.formData.image){ + if (this.formData.image) { const data = this.formData.image.split(",") this.formData.image = data.map(item => { return item.replace(process.env.VUE_APP_FILE_API, "") @@ -648,13 +671,13 @@ export default { this.formData.itemList = [...this.formData.itemList, ...this.formatItem("other", this.otherList)] }, // 非空验证 - handleValidate(){ + handleValidate() { let count = 0 this.formData.itemList.forEach(item => { if (count !== 0) return count - if (!item.repairIds || !item.saleId){ + if (!item.repairIds || !item.saleId) { let message = "" - switch (item.itemType){ + switch (item.itemType) { case "01": message += "项目:" break @@ -720,11 +743,11 @@ export default { cusName: data.userName, id: data.userId, phoneNumber: data.userMobile, - quality: {qualityMileage: data.qualityMileage, qualityDay: data.qualityDay} + quality: { qualityMileage: data.qualityMileage, qualityDay: data.qualityDay } } const itemList = this.formData.itemList - this.selectUser = {id: data.userId} - this.selectCar = {id: data.carId} + this.selectUser = { id: data.userId } + this.selectCar = { id: data.carId } this.projectList = [itemList.find(item => item.itemType === '01')] this.partList = [itemList.find(item => item.itemType === '02')] this.otherList = [itemList.find(item => item.itemType === '03')] @@ -801,12 +824,121 @@ export default { // handleSelectionChange(val){ // // } - updateBooking(){ + updateBooking() { const data = this.bookingList.filter(item => item.id === this.formData.bookingId) - if (data && data.length > 0){ + if (data && data.length > 0) { this.formData.repairType = data[0].repairType } }, + // 打开A单选择对话框 + openTicketChooseDialog() { + this.ticketChooseDialogVisible = true + }, + // 处理A单选择 + handleParentTicketSelected(ticket) { + if (ticket) { + this.formData.parentTicketId = ticket.id + this.formData.parentTicketNo = ticket.ticketNo + this.ticketChooseDialogVisible = false + this.$modal.msgSuccess(`已绑定A单:${ticket.ticketNo}`) + } + }, + // 清除绑定的A单 + clearParentTicket() { + this.formData.parentTicketId = null + this.formData.parentTicketNo = null + this.$modal.msgSuccess('已清除绑定的A单') + }, + /** + * 获取业务来源和渠道 + */ + queryBusiAndCus() { + request({ + url: `/business/list`, + method: 'GET', + params: { + systemCode: 'repair' + } + }).then(res => { + this.busiAndCusList = res.data + console.log('busiAndCusList', this.busiAndCusList); + // 处理渠道和来源数据 + this.processBusiAndCusData() + }) + }, + /** + * 处理业务渠道和来源数据 + */ + processBusiAndCusData() { + // 渠道列表:pid为0的是渠道 + this.channelList = this.busiAndCusList.filter(item => item.pid === 0) + // 来源列表:pid不为0的是来源 + this.sourceList = this.busiAndCusList.filter(item => item.pid !== 0) + + // 生成级联选择器选项 + this.generateCascaderOptions() + }, + /** + * 生成级联选择器选项 + */ + generateCascaderOptions() { + // 先获取所有渠道 + const channels = this.busiAndCusList.filter(item => item.pid === 0) + + // 构建级联选择器选项 + this.busiCascaderOptions = channels.map(channel => { + // 获取该渠道下的所有来源 + const sources = this.busiAndCusList.filter(item => item.pid === channel.id) + + return { + value: channel.id, + label: channel.name, + children: sources.map(source => ({ + value: source.id, + label: source.name + })) + } + }) + }, + /** + * 业务渠道/来源级联选择变化 + */ + handleBusiCascaderChange(value) { + if (value && value.length > 0) { + if (value.length === 1) { + // 只选择了渠道 + const channelId = value[0] + const selectedChannel = this.channelList.find(item => item.id === channelId) + if (selectedChannel) { + this.formData.channelId = selectedChannel.id + this.formData.busiFrom = selectedChannel.name + // 清空来源选择 + this.formData.sourceId = null + this.formData.cusFrom = null + } + } else if (value.length === 2) { + // 选择了渠道和来源 + const channelId = value[0] + const sourceId = value[1] + + const selectedChannel = this.channelList.find(item => item.id === channelId) + const selectedSource = this.sourceList.find(item => item.id === sourceId) + + if (selectedChannel && selectedSource) { + this.formData.channelId = selectedChannel.id + this.formData.busiFrom = selectedChannel.name + this.formData.sourceId = selectedSource.id + this.formData.cusFrom = selectedSource.name + } + } + } else { + // 清空选择 + this.formData.channelId = null + this.formData.busiFrom = null + this.formData.sourceId = null + this.formData.cusFrom = null + } + }, } }