diff --git a/src/api/admin/finance.ts b/src/api/admin/finance.ts new file mode 100644 index 0000000..334720d --- /dev/null +++ b/src/api/admin/finance.ts @@ -0,0 +1,74 @@ +import request from '@/utils/http' + +export class financeService { + // 收款记录-列表 + static getReceiptList(params: Api.Common.PaginatingParams) { + return request.get({ + url: '/admin/receipt/list', + params + }) + } + // 收款记录-详情 + static getReceiptDetail(params: any) { + return request.get({ + url: '/admin/receipt/show', + params + }) + } + // 收款记录-添加 + static addReceipt(params: any) { + return request.post({ + url: '/admin/receipt/store', + params + }) + } + // 收款记录-更新 + static updateReceipt(params: any) { + return request.post({ + url: '/admin/receipt/update', + params + }) + } + // 收款记录-删除 + static deleteReceipt(params: any) { + return request.post({ + url: '/admin/receipt/destroy', + params + }) + } + //付款申请-列表 + static getPaymentList(params: Api.Common.PaginatingParams) { + return request.get({ + url: '/admin/payment/list', + params + }) + } + //付款申请-详情 + static getPaymentDetail(params: any) { + return request.get({ + url: '/admin/payment/show', + params + }) + } + //付款申请-添加 + static addPayment(params: any) { + return request.post({ + url: '/admin/payment/store', + params + }) + } + //付款申请-更新 + static updatePayment(params: any) { + return request.post({ + url: '/admin/payment/update', + params + }) + } + //付款申请-删除 + static deletePayment(params: any) { + return request.post({ + url: '/admin/payment/destroy', + params + }) + } +} \ No newline at end of file diff --git a/src/api/admin/procurement.ts b/src/api/admin/procurement.ts new file mode 100644 index 0000000..5dbcd1f --- /dev/null +++ b/src/api/admin/procurement.ts @@ -0,0 +1,46 @@ +import request from '@/utils/http' + +export class purchaseService { + // 采购单预置 + static purchaseorderpredata(params: any) { + return request.get({ + url: '/admin/purchase/order/predata', + params + }) + } + // 采购单列表 + static purchaseorderlist(params: Api.Common.PaginatingParams) { + return request.get({ + url: '/admin/purchase/order/list', + params + }) + } + // 采购单添加 + static purchaseorderadd(params: any) { + return request.post({ + url: '/admin/purchase/order/store', + params + }) + } + // 采购单更新 + static purchaseorderupdate(params: any) { + return request.post({ + url: '/admin/purchase/order/update', + params + }) + } + // 采购单删除 + static purchaseorderdelete(params: any) { + return request.post({ + url: '/admin/purchase/order/destroy', + params + }) + } + // 采购单详情 + static purchaseorderdetail(params: any) { + return request.get({ + url: '/admin/purchase/order/show', + params + }) + } +} diff --git a/src/api/adminApi.ts b/src/api/adminApi.ts index fc18864..897a2c8 100644 --- a/src/api/adminApi.ts +++ b/src/api/adminApi.ts @@ -305,4 +305,25 @@ export class manageService { params }) } + //审核详情 + static stockapprovaldetailborder(params: any) { + return request.get({ + url: '/admin/approval/records/border', + params + }) + } + //审批转交 + static stockapprovaltransfer(params: any) { + return request.post({ + url: '/admin/approval/records/transfer', + params + }) + } + //审批时间轴 + static stockapprovaltimeline(params: any) { + return request.get({ + url: '/admin/approval/records/timeline', + params + }) + } } diff --git a/src/components/core/tables/ArtTable.vue b/src/components/core/tables/ArtTable.vue index b2c7f18..40f9a9d 100644 --- a/src/components/core/tables/ArtTable.vue +++ b/src/components/core/tables/ArtTable.vue @@ -184,12 +184,11 @@ const elTable = tableRef.value if (!elTable) return - // 递归处理树形数据 + // 支持普通与树形数据行展开 const processRows = (rows: any[]) => { rows.forEach((row) => { - const hasChildren = row.children?.length > 0 - if (hasChildren) { - elTable.toggleRowExpansion(row, true) + elTable.toggleRowExpansion(row, true) + if (row.children?.length > 0) { processRows(row.children) } }) @@ -203,12 +202,11 @@ const elTable = tableRef.value if (!elTable) return - // 递归处理树形数据 + // 支持普通与树形数据行收起 const processRows = (rows: any[]) => { rows.forEach((row) => { - const hasChildren = row.children?.length > 0 - if (hasChildren) { - elTable.toggleRowExpansion(row, false) + elTable.toggleRowExpansion(row, false) + if (row.children?.length > 0) { processRows(row.children) } }) diff --git a/src/components/custom/ApprovalTimeline.vue b/src/components/custom/ApprovalTimeline.vue new file mode 100644 index 0000000..95e5678 --- /dev/null +++ b/src/components/custom/ApprovalTimeline.vue @@ -0,0 +1,132 @@ + + + + + + + diff --git a/src/components/custom/OrderDetailContent.vue b/src/components/custom/OrderDetailContent.vue index 7ef4121..e685e91 100644 --- a/src/components/custom/OrderDetailContent.vue +++ b/src/components/custom/OrderDetailContent.vue @@ -8,7 +8,9 @@
业务员: - {{ orderData.salesperson_snapshot || orderData.salesperson || '—' }} + {{ + orderData.salesperson_snapshot || orderData.salesperson || '—' + }}
@@ -26,19 +28,27 @@ 清关目的国: - {{ orderData.clearance_country_snapshot || orderData.clearanceCountry || '—' }} + {{ + orderData.clearance_country_snapshot || orderData.clearanceCountry || '—' + }} 客户来源: - {{ orderData.customer_source_snapshot || orderData.customerSource || '—' }} + {{ + orderData.customer_source_snapshot || orderData.customerSource || '—' + }} 客户名称: - {{ orderData.customer_snapshot || orderData.customerName || '—' }} + {{ + orderData.customer_snapshot || orderData.customerName || '—' + }} 客户所在国: - {{ orderData.customer_country_snapshot || orderData.customerCountry || '—' }} + {{ + orderData.customer_country_snapshot || orderData.customerCountry || '—' + }} @@ -46,8 +56,16 @@
- +
合同汇率: - {{ orderData.contract_exchange_rate || orderData.contractRate || '—' }} + {{ + orderData.contract_exchange_rate || orderData.contractRate || '—' + }}
合计到岸价: - ${{ formatPrice(Number(orderData.cif_total_amount?.amount ?? orderData.totalCif ?? 0)) }} + ${{ + formatPrice(Number(orderData.cif_total_amount?.amount ?? orderData.totalCif ?? 0)) + }}
利润: - {{ orderData.profit_total?.currency_info || orderData.profit_total?.amount || '—' }} + {{ + orderData.profit_total?.currency_info || orderData.profit_total?.amount || '—' + }}
@@ -131,34 +246,54 @@ 清关人: - {{ orderData.declarant_name || orderData.declarant || '—' }} + {{ + orderData.declarant_name || orderData.declarant || '—' + }} 预计发运日期: - {{ orderData.eta_ship_date || orderData.etaShipDate || '—' }} + {{ + orderData.eta_ship_date || orderData.etaShipDate || '—' + }} 出运方式: - {{ orderData.shipping_method_snapshot || orderData.shippingMethod || '—' }} + {{ + orderData.shipping_method_snapshot || orderData.shippingMethod || '—' + }} 国内收货港: - {{ orderData.domestic_port_snapshot || orderData.domesticPort || '—' }} + {{ + orderData.domestic_port_snapshot || orderData.domesticPort || '—' + }} 贸易条款/清关目的港: - {{ orderData.trade_term_snapshot || orderData.tradeTerms || '—' }}/{{ orderData.clearance_port_snapshot || '—' }} + {{ orderData.trade_term_snapshot || orderData.tradeTerms || '—' }}/{{ + orderData.clearance_port_snapshot || '—' + }} 最迟到港时间: - {{ orderData.latest_arrival_date || orderData.latestArrival || '—' }} + {{ + orderData.latest_arrival_date || orderData.latestArrival || '—' + }} -
+
@@ -192,8 +327,7 @@ + + diff --git a/src/components/custom/ProcurementDetailView.vue b/src/components/custom/ProcurementDetailView.vue new file mode 100644 index 0000000..15ddfb5 --- /dev/null +++ b/src/components/custom/ProcurementDetailView.vue @@ -0,0 +1,169 @@ + + + + + diff --git a/src/components/custom/chat/WorkChatDrawer.vue b/src/components/custom/chat/WorkChatDrawer.vue new file mode 100644 index 0000000..9227e1a --- /dev/null +++ b/src/components/custom/chat/WorkChatDrawer.vue @@ -0,0 +1,213 @@ + + + + + + + diff --git a/src/composables/useOrderDetailDialog.ts b/src/composables/useOrderDetailDialog.ts index 1773613..3e8eef6 100644 --- a/src/composables/useOrderDetailDialog.ts +++ b/src/composables/useOrderDetailDialog.ts @@ -22,6 +22,7 @@ export interface PaymentItem { } export interface OrderData { + contract_file_url: { name: string; url: string }[] orderNo?: string salesperson?: string piNo?: string @@ -45,7 +46,11 @@ export interface OrderData { export function useOrderDetailDialog() { const visible = ref(false) const title = ref('订单详情') - const orderData = ref({}) + const orderData = ref({ + contract_file_url: [], + items: [], + payments: [] + }) const show = (data: OrderData, dialogTitle?: string) => { orderData.value = data diff --git a/src/composables/useStockingForm.ts b/src/composables/useStockingForm.ts index 89e512e..7b89a5a 100644 --- a/src/composables/useStockingForm.ts +++ b/src/composables/useStockingForm.ts @@ -1,5 +1,5 @@ import { ref, reactive, watch, onMounted } from 'vue' -import { ElMessage } from 'element-plus' +import { componentSizeMap, ElMessage } from 'element-plus' import { CrmService } from '@/api/crmApi' import { commonService } from '@/api/commonApi' import { vehicleService } from '@/api/vehicleApi' @@ -62,9 +62,19 @@ export interface ItemRow { handling_fee: string fob_transport_fee: number | undefined port_misc_fee: string + remark: string ocean_freight: string ocean_freight_currency: string ocean_freight_currency_snapshot: string + commission: string + commission_currency: string + commission_currency_snapshot: string + purchase_tax: string + purchase_tax_currency: string + purchase_tax_currency_snapshot: string + tax_refund: string + tax_refund_currency: string + tax_refund_currency_snapshot: string retrofit_fee: string total_price: number | undefined official_price: number | undefined @@ -195,9 +205,19 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { handling_fee: '', fob_transport_fee: undefined, port_misc_fee: '', + remark: '', ocean_freight: '', ocean_freight_currency: 'CNY', ocean_freight_currency_snapshot: '人民币', + commission: '', + commission_currency: 'CNY', + commission_currency_snapshot: '人民币', + purchase_tax: '', + purchase_tax_currency: 'CNY', + purchase_tax_currency_snapshot: '人民币', + tax_refund: '', + tax_refund_currency: 'CNY', + tax_refund_currency_snapshot: '人民币', retrofit_fee: '', total_price: undefined, official_price: undefined, @@ -434,6 +454,21 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { (it as any).ocean_freight_currency, targetCurrency ) + const commission = convertCurrency( + it.commission ?? (it as any).commission, + (it as any).commission_currency, + targetCurrency + ) + const purchaseTax = convertCurrency( + it.purchase_tax ?? (it as any).purchase_tax, + (it as any).purchase_tax_currency, + targetCurrency + ) + const taxRefund = convertCurrency( + it.tax_refund ?? (it as any).tax_refund, + (it as any).tax_refund_currency, + targetCurrency + ) const mileageVal = Number(it.mileage ?? 0) if (mileageVal > 0) { // 二手车:用挂牌价与二手减价替代官方指导价与优惠 @@ -447,7 +482,19 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { (it as any).reduction_price_currency, targetCurrency ) - return unit - (retrofit + fob + listing + reduction + handling + port + ocean) + return ( + unit - + (retrofit + + fob + + listing + + reduction + + handling + + port + + ocean + + commission + + purchaseTax) + + taxRefund + ) } // 新车/里程<=0:保持原有计算(官方指导价与优惠) @@ -461,7 +508,11 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { (it as any).discount_currency, targetCurrency ) - return unit - (retrofit + fob + guide + discount + handling + port + ocean) + return ( + unit - + (retrofit + fob + guide + discount + handling + port + ocean + commission + purchaseTax) + + taxRefund + ) } // 合同文件相关方法 @@ -678,9 +729,19 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { handling_fee: it.handling_fee?.amount ?? '', fob_transport_fee: it.fob_transport_fee?.amount ? Number(it.fob_transport_fee.amount) : undefined, port_misc_fee: it.port_misc_fee?.amount ?? '', + remark: it.remark || '', ocean_freight: it.ocean_freight?.amount ?? '', ocean_freight_currency: it.ocean_freight?.currency || 'CNY', ocean_freight_currency_snapshot: '', + commission: it.commission?.amount ?? '', + commission_currency: it.commission?.currency || 'CNY', + commission_currency_snapshot: '', + purchase_tax: it.purchase_tax?.amount ?? '', + purchase_tax_currency: it.purchase_tax?.currency || 'CNY', + purchase_tax_currency_snapshot: '', + tax_refund: it.tax_refund?.amount ?? '', + tax_refund_currency: it.tax_refund?.currency || 'CNY', + tax_refund_currency_snapshot: '', retrofit_fee: it.retrofit_fee?.amount ?? '', total_price: it.total_price?.amount ? Number(it.total_price.amount) : undefined, official_price: it.official_price?.amount ? Number(it.official_price.amount) : undefined, @@ -759,6 +820,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { color_interior_snapshot: it.color_interior_snapshot, color_exterior_code: it.color_exterior_code, color_exterior_snapshot: it.color_exterior_snapshot, + remark: it.remark, unit_price: wrapMoney(it.unit_price, (it as any).unit_price_currency, '单价'), handling_fee: wrapMoney(it.handling_fee, (it as any).helper_fee_currency, '手续费'), fob_transport_fee: wrapMoney( @@ -772,6 +834,9 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { '港杂费' ), ocean_freight: wrapMoney(it.ocean_freight, (it as any).ocean_freight_currency, '海运费'), + commission: wrapMoney(it.commission, (it as any).commission_currency, '佣金'), + purchase_tax: wrapMoney(it.purchase_tax, (it as any).purchase_tax_currency, '购置税'), + tax_refund: wrapMoney(it.tax_refund, (it as any).tax_refund_currency, '退税'), retrofit_fee: wrapMoney((it as any).retrofit_fee, (it as any).modify_fee_currency, '改装费'), modify_list: it.modify_list, // total_price: wrapMoney(it.total_price, (it as any).total_price_currency, '总价'), diff --git a/src/views/admin/approval/stocking_auth.vue b/src/views/admin/approval/stocking_auth.vue index c3f3161..97e6485 100644 --- a/src/views/admin/approval/stocking_auth.vue +++ b/src/views/admin/approval/stocking_auth.vue @@ -71,7 +71,7 @@
- +
+ +
+
+ +
+ v-model="approvalNotes" + type="textarea" + :rows="2" + placeholder="备注" + class="approval-notes" + />
@@ -98,15 +103,50 @@ + + + + + + + + + + + +
+ 取消 + 确定 +
+
+
@@ -117,9 +157,13 @@ import { commonService } from '@/api/commonApi' import OrderDetailContent from '@/components/custom/OrderDetailContent.vue' import type { OrderData } from '@/composables/useOrderDetailDialog' + import ProcurementDetailView from '@/components/custom/ProcurementDetailView.vue' defineOptions({ name: 'AdminStockingPage' }) + const zjDialogVisible = ref(false) const orderDialog = reactive({ - orderData: {} as OrderData + orderData: {} as OrderData, + title: '', + type: '' }) const { hasAuth } = useAuth() const loading = ref(false) @@ -127,7 +171,19 @@ const tableRef = ref() const tableData = ref([]) const pagination = reactive({ currentPage: 1, pageSize: 10, total: 0 }) - + const userOptions = ref() + const getuserList = async () => { + // 这里调用获取用户列表的接口 + const res = await manageService.presetusers() + userOptions.value = res || [] + // return res || [] + } + const zjForm = reactive({ + to_uid: '', + instance_id: '', + step_index: '', + reason: '' + }) // 审批弹出框相关 const approvalDialogVisible = ref(false) @@ -170,36 +226,58 @@ pagination.currentPage = page getList() } - - const handleCreate = () => { - // TODO: 跳转到创建备货单页面 - router.push('/crmpc/stocking_list/Add') - } const handleView = (row: any) => { router.push({ path: '/admin/approval/stocking_auth_detil', - query: { id: row.id, biz_id: row.biz_id, instance_id: row.instance_id, status: row.status } // 可带客户名等参数 + query: { + id: row.id, + biz_id: row.biz_id, + instance_id: row.instance_id, + status: row.status, + flow_type: row.flow_type, + step_index: row.step_index + } // 可带客户名等参数 }) } - const handleView1 = (row: any) => { - router.push('/crmpc/stocking_list/final_show') - // TODO: 跳转或弹窗查看备货单 - } - const toMoneyView = (m: any) => ({ - amount: m?.amount ?? '', - currency: m?.currency ?? '' - }) - const getDictItemSelectlist = ref([]) - const getDictItemSelect = async () => { - const res = await commonService.getDictItemSelect({ dict_id: '18' }) - getDictItemSelectlist.value = res - } const instance_id = ref('') + function extractFileName(pathOrUrl: string | undefined | null): string { + if (!pathOrUrl) return '合同文件' + try { + const clean = String(pathOrUrl) + const afterSlash = clean.split(/[\\/]/).pop() || '合同文件' + return decodeURIComponent(afterSlash) + } catch { + return '合同文件' + } + } + const activerow = ref() const handleCreateRepair = async (row: any) => { + activerow.value = row instance_id.value = row.instance_id - const res = await manageService.checkStock({ id: row.biz_id }) - const orderData: OrderData = res - orderDialog.orderData = orderData + const res = await manageService.stockapprovaldetailborder({ + id: row.id, + flow_type: row.flow_type + }) + if (row.flow_type == 'stock_orders') { + const orderData: OrderData = res + orderDialog.orderData = orderData + orderDialog.type = row.flow_type + orderDialog.title = '合塑实业-汽车事业部-备货单(客户下定)' + } else if (row.flow_type == 'purchase_orders') { + const orderData: OrderData = res + const urls = res.contract_file_url + const paths = res.contract_file + const list: Array<{ name: string; url: string }> = [] + const nameFromPath = (p: string) => extractFileName(p) + urls.forEach((u: string, i: number) => { + const p = paths[i] || '' + list.push({ name: p ? nameFromPath(p) : extractFileName(u), url: u }) + }) + orderData.contract_file_url = list + orderDialog.orderData = orderData + orderDialog.type = row.flow_type + orderDialog.title = '合塑实业-汽车事业部-采购单(采购)' + } approvalDialogVisible.value = true } @@ -224,6 +302,38 @@ ElMessage.error('审批失败') } } + // 转交操作 + const handleTransfer = async () => { + zjForm.instance_id = activerow.value.instance_id + zjForm.step_index = activerow.value.step_index + getuserList() + zjDialogVisible.value = true + } + const handlezjSubmit = async () => { + if (!zjForm.to_uid) { + ElMessage.warning('请选择转交人') + return + } + if (!zjForm.reason) { + ElMessage.warning('请输入转交原因') + return + } + try { + const { message } = await manageService.stockapprovaltransfer(zjForm) + ElMessage.success(message) + zjDialogVisible.value = false + approvalDialogVisible.value = false + approvalNotes.value = '' + zjForm.to_uid = '' + zjForm.reason = '' + instance_id.value = '' + // 刷新列表 + getList() + } catch (error) { + console.error('转交失败:', error) + // ElMessage.error('转交失败') + } + } diff --git a/src/views/admin/stock/final_list_admin.vue b/src/views/admin/stock/final_list_admin.vue index a833ef8..331cb86 100644 --- a/src/views/admin/stock/final_list_admin.vue +++ b/src/views/admin/stock/final_list_admin.vue @@ -66,6 +66,9 @@ 查看终版 + + 查看审批 + @@ -156,6 +159,19 @@ />
+ +
+ + +
+
@@ -165,8 +181,11 @@ import { manageService } from '@/api/adminApi' import { useAuth } from '@/composables/useAuth' import OrderDetailContent from '@/components/custom/OrderDetailContent.vue' + import ApprovalTimeline from '@/components/custom/ApprovalTimeline.vue' import type { OrderData } from '@/composables/useOrderDetailDialog' import { usePdfPreview } from '@/composables/usePdfPreview' + const timelineDialogVisible = ref(false) + const approvalRecords = ref([]) // PDF 预览/打印(公共) const { pdf, frameRef, openWithResponse, download, print, preparePreview, prepareImages } = usePdfPreview() defineOptions({ name: 'AdminFinalListPage' }) @@ -370,6 +389,28 @@ ElMessage.error('下载失败,请稍后重试') } } + //审批进度 + const showDialogtimeline = async (row: any) => { + // 审批记录(兼容多种字段) + const resstockapprovallogs = await manageService.stockapprovaltimeline({ + id: row.id, + flow_type: 'stock_orders' + }) + console.log(resstockapprovallogs) + const historyList = resstockapprovallogs + if (historyList.length > 0) { + approvalRecords.value = historyList.map((h: any) => ({ + name: h?.initiator_name ? h?.initiator_name : h?.name, + role: h?.status_desc, + time: h?.time || '', + approved: h?.status === 'approved' || h?.status === 'submitted', + rejected: h?.status === 'rejected', + pending: h?.status != 'approved' && h?.status != 'rejected' && h?.status != 'submitted', + comment: h?.comment || h?.remark || '' + })) + } + timelineDialogVisible.value = true + }