From da690dfa06b5b01216c6a5c2d53a725dd2fd865b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Thu, 11 Sep 2025 17:44:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20=E5=A4=87=E8=B4=A7?= =?UTF-8?q?=E5=8D=95=20=E8=AF=A6=E6=83=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/adminApi.ts | 7 + src/api/crmApi.ts | 7 + .../core/layouts/art-page-content/index.vue | 4 +- src/components/custom/OrderDetailContent.vue | 372 ++++++++++++++++ src/composables/useOrderDetailDialog.ts | 73 ++++ src/composables/useStockingForm.ts | 11 +- src/views/admin/approval/stocking_auth.vue | 315 +------------- .../admin/approval/stocking_auth_detil.vue | 396 +---------------- src/views/admin/stock/final_list_admin.vue | 210 ++++++++- src/views/admin/stock/final_show_admin.vue | 2 +- src/views/admin/stock/show_admin.vue | 2 +- src/views/admin/stock/stocking_list_admin.vue | 245 ++++++++++- src/views/crmpc/approval/auth_detil.vue | 408 ++---------------- src/views/crmpc/approval/stocking_auth.vue | 343 ++------------- src/views/crmpc/stocking/Add.vue | 8 +- src/views/crmpc/stocking/final_add.vue | 21 +- src/views/crmpc/stocking/final_list.vue | 214 ++++++++- src/views/crmpc/stocking/final_show.vue | 2 +- src/views/crmpc/stocking/show.vue | 2 +- src/views/crmpc/stocking/stocking_edit.vue | 21 +- src/views/crmpc/stocking/stocking_list.vue | 271 +++++++++++- 21 files changed, 1490 insertions(+), 1444 deletions(-) create mode 100644 src/components/custom/OrderDetailContent.vue create mode 100644 src/composables/useOrderDetailDialog.ts diff --git a/src/api/adminApi.ts b/src/api/adminApi.ts index 080d181..043d233 100644 --- a/src/api/adminApi.ts +++ b/src/api/adminApi.ts @@ -285,6 +285,13 @@ export class manageService { params }) } + //备货单查看 + static checkStock(params: any) { + return request.get({ + url: '/admin/stock/order/detail', + params + }) + } //打印 static printStock(params: any) { return request.get({ diff --git a/src/api/crmApi.ts b/src/api/crmApi.ts index 8ff6ef2..3bbabc4 100644 --- a/src/api/crmApi.ts +++ b/src/api/crmApi.ts @@ -236,6 +236,13 @@ export class CrmService { params }) } + //备货单查看 + static checkStock(params: any) { + return request.get({ + url: '/crm/stock/order/detail', + params + }) + } //提交备货单 static submitStock(params: any) { return request.post({ diff --git a/src/components/core/layouts/art-page-content/index.vue b/src/components/core/layouts/art-page-content/index.vue index f51e576..73c8bd1 100644 --- a/src/components/core/layouts/art-page-content/index.vue +++ b/src/components/core/layouts/art-page-content/index.vue @@ -6,7 +6,7 @@ @@ -17,7 +17,7 @@ - + diff --git a/src/components/custom/OrderDetailContent.vue b/src/components/custom/OrderDetailContent.vue new file mode 100644 index 0000000..e3e790f --- /dev/null +++ b/src/components/custom/OrderDetailContent.vue @@ -0,0 +1,372 @@ + + + + + diff --git a/src/composables/useOrderDetailDialog.ts b/src/composables/useOrderDetailDialog.ts new file mode 100644 index 0000000..1773613 --- /dev/null +++ b/src/composables/useOrderDetailDialog.ts @@ -0,0 +1,73 @@ +import { ref, reactive } from 'vue' + +export interface OrderItem { + model?: string + quantity?: number + exteriorColor?: string + interiorColor?: string + modification?: string + unitPrice?: number + totalPrice?: number + officialPrice?: number + discount?: string +} + +export interface PaymentItem { + country?: string + date?: string + currency?: string + account?: string + remitter?: string + amount?: number +} + +export interface OrderData { + orderNo?: string + salesperson?: string + piNo?: string + date?: string + clearanceCountry?: string + customerSource?: string + customerName?: string + customerCountry?: string + items?: OrderItem[] + contractRate?: string + totalCif?: number + declarant?: string + etaShipDate?: string + shippingMethod?: string + domesticPort?: string + tradeTerms?: string + latestArrival?: string + payments?: PaymentItem[] +} + +export function useOrderDetailDialog() { + const visible = ref(false) + const title = ref('订单详情') + const orderData = ref({}) + + const show = (data: OrderData, dialogTitle?: string) => { + orderData.value = data + title.value = dialogTitle || '订单详情' + visible.value = true + } + + const hide = () => { + visible.value = false + } + + const print = () => { + // 可以在这里添加打印逻辑 + window.print() + } + + return { + visible, + title, + orderData, + show, + hide, + print + } +} diff --git a/src/composables/useStockingForm.ts b/src/composables/useStockingForm.ts index 958e222..3d8786c 100644 --- a/src/composables/useStockingForm.ts +++ b/src/composables/useStockingForm.ts @@ -31,7 +31,7 @@ export interface BaseForm { pick_up_date: string collect_all_date: string contract_exchange_rate: string - contract_exchange_rate_currency: string + settlement_currency: string remark: string total_cif: number | undefined total_cif_currency: string @@ -161,7 +161,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { clearance_port_snapshot: '', latest_arrival_date: '', contract_exchange_rate: '', - contract_exchange_rate_currency: 'USD', + settlement_currency: 'USD', remark: '', total_cif: undefined, total_cif_currency: 'USD', @@ -359,7 +359,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { } const validateContractRate = () => { - const code = baseForm.contract_exchange_rate_currency || items.value[0]?.unit_price_currency || 'USD' + const code = baseForm.settlement_currency || items.value[0]?.unit_price_currency || 'USD' const { min, max } = getCurrencyBounds(code) const val = Number(baseForm.contract_exchange_rate) if (Number.isNaN(val)) return @@ -730,9 +730,8 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { reduction_price: wrapMoney(it.reduction_price, (it as any).reduction_price_currency, '二手减价') })) - // 从提交参数中移除 contract_exchange_rate_currency + // 从提交参数中移除 settlement_currency const baseFormWithoutCur = { ...(baseForm as any) } - delete (baseFormWithoutCur as any).contract_exchange_rate_currency delete (baseFormWithoutCur as any).total_cif delete (baseFormWithoutCur as any).total_cif_currency delete (baseFormWithoutCur as any).total_cif_currency_snapshot @@ -765,7 +764,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { // 监听器 watch( - () => baseForm.contract_exchange_rate_currency, + () => baseForm.settlement_currency, (newCurrency) => { if (newCurrency) { baseForm.contract_exchange_rate = getCurrencyRate(newCurrency) diff --git a/src/views/admin/approval/stocking_auth.vue b/src/views/admin/approval/stocking_auth.vue index 4b134a6..6ca5e9f 100644 --- a/src/views/admin/approval/stocking_auth.vue +++ b/src/views/admin/approval/stocking_auth.vue @@ -77,229 +77,18 @@ >
-
-
- 备货单编号:{{ header.order_no }} - 业务员:{{ header.salesman }} -
-
- - -
-
-
- 基础信息 -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
- 订单详情 -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - -
-
+
-
-
- 审批 -
- - - - - - - - - - + -
@@ -307,8 +96,12 @@ @@ -321,6 +114,11 @@ import { useAuth } from '@/composables/useAuth' import { CrmService } from '@/api/crmApi' import { commonService } from '@/api/commonApi' + import OrderDetailContent from '@/components/custom/OrderDetailContent.vue' + import type { OrderData } from '@/composables/useOrderDetailDialog' + const orderDialog = reactive({ + orderData: {} as OrderData + }) const { hasAuth } = useAuth() const loading = ref(false) const keyword = ref('') @@ -413,84 +211,20 @@ } const instance_id = ref('') const handleCreateRepair = async (row: any) => { - getDictItemSelect() instance_id.value = row.instance_id - const res = await CrmService.getStockDetail({ id: row.biz_id }) - stockingInfo.value = res - // 头部 - header.order_no = res?.order_no || res?.pi_no || '' - header.salesman = - res?.salesperson_snapshot || res?.salesman || res?.salesman_name || res?.user?.name || '' - // 基础信息 - base.pn_no = res?.pi_no || '' - base.date = res?.biz_date || '' - base.close_date = res?.clearance_country_snapshot || '' - base.channel = res?.customer_source_snapshot || res?.customer_source || '' - base.customer_name = res?.customer_snapshot || res?.customer_name || '' - base.client_country = res?.customer_country_snapshot || res?.customer_country || '' - // 订单明细 - const list = Array.isArray(res?.veh_list) ? res.veh_list : [] - items.value = list.map((it: any) => { - const unit = toMoneyView(it?.unit_price) - const total = toMoneyView(it?.total_price) - const guide = toMoneyView(it?.official_price) - const discount = toMoneyView(it?.discount_price) - const listing = toMoneyView(it?.listing_price) - const reduction = toMoneyView(it?.reduction_price) - const helper = toMoneyView(it?.handling_fee) - const fob = toMoneyView(it?.fob_transport_fee) - const port = toMoneyView(it?.port_misc_fee) - const profit = toMoneyView(it?.profit) - return { - model: it?.model_snapshot || '', - mileage: it?.mileage ?? 0, - vin: it?.vin || '', - color_out: it?.color_exterior_snapshot || '', - color_in: it?.color_interior_snapshot || '', - modify: (Array.isArray(it?.modify_list) ? it.modify_list : []) - .map((m: any) => m?.option_name_snapshot) - .filter(Boolean) - .join('、'), - modify_fee: it?.retrofit_fee?.amount ?? '', - modify_fee_currency: it?.retrofit_fee?.currency ?? '', - fob_fee: fob.amount, - fob_fee_currency: fob.currency, - unit_price: unit.amount, - unit_price_currency: unit.currency, - total_price: total.amount, - total_price_currency: total.currency, - guide_price: guide.amount, - guide_price_currency: guide.currency, - discount: discount.amount, - discount_currency: discount.currency, - listing_price: listing.amount, - listing_price_currency: listing.currency, - reduction_price: reduction.amount, - reduction_price_currency: reduction.currency, - helper_fee: helper.amount, - helper_fee_currency: helper.currency, - domestic_freight: it?.domestic_freight?.amount ?? '', - domestic_freight_currency: it?.domestic_freight?.currency ?? '', - port_fee: port.amount, - port_fee_currency: port.currency, - profit: profit.amount, - profit_currency: profit.currency - } - }) - // 合计与汇率 - base.total_cif = res?.cif_total_amount?.amount ?? '' - base.total_cif_currency = res?.cif_total_amount?.currency || '' - base.contract_rate = res?.contract_exchange_rate || res?.contract_rate || '' + const res = await manageService.checkStock({ id: row.biz_id }) + const orderData: OrderData = res + orderDialog.orderData = orderData approvalDialogVisible.value = true } // 审批操作 - const handleApprove = async () => { + const handleApprove = async (approvalAction: string) => { try { // 这里调用审批API const { message } = await manageService.stockapprovalpass({ instance_id: instance_id.value, - action: approvalAction.value, + action: approvalAction, comment: approvalNotes.value }) @@ -505,11 +239,6 @@ ElMessage.error('审批失败') } } - - const handleReject = async () => { - approvalDialogVisible.value = false - approvalNotes.value = '' - } diff --git a/src/views/admin/stock/final_show_admin.vue b/src/views/admin/stock/final_show_admin.vue index 6141e47..61b5c15 100644 --- a/src/views/admin/stock/final_show_admin.vue +++ b/src/views/admin/stock/final_show_admin.vue @@ -16,7 +16,7 @@
基础信息
- + diff --git a/src/views/admin/stock/show_admin.vue b/src/views/admin/stock/show_admin.vue index 8b2fa32..8e1fbb3 100644 --- a/src/views/admin/stock/show_admin.vue +++ b/src/views/admin/stock/show_admin.vue @@ -16,7 +16,7 @@
基础信息
- + diff --git a/src/views/admin/stock/stocking_list_admin.vue b/src/views/admin/stock/stocking_list_admin.vue index edf1226..eb230b9 100644 --- a/src/views/admin/stock/stocking_list_admin.vue +++ b/src/views/admin/stock/stocking_list_admin.vue @@ -33,7 +33,7 @@ > @@ -124,8 +177,16 @@ import { router } from '@/router' import { manageService } from '@/api/adminApi' import { usePdfPreview } from '@/composables/usePdfPreview' + import OrderDetailContent from '@/components/custom/OrderDetailContent.vue' + import type { OrderData } from '@/composables/useOrderDetailDialog' // import { useAuth } from '@/composables/useAuth' // const { hasAuth } = useAuth() + // 订单详情弹窗 + const orderDialog = reactive({ + visible: false, + title: '订单详情', + orderData: {} as OrderData + }) const loading = ref(false) const keyword = ref('') @@ -179,31 +240,162 @@ getList() } - const handleCreate = () => { - // TODO: 跳转到创建备货单页面 - router.push('/crmpc/stocking/Add') - } - const handleView = (row: any) => { - router.push({ - path: '/admin/stock/show_admin', - query: { id: row.id } // 可带客户名等参数 - }) + const contractFile = ref<{ name: string; url: string; file_name: string } | null>(null) + const handleView = async (row: any) => { + try { + // 获取订单详情数据 + const res = await manageService.checkStock({ id: row.id }) + if (res?.contract) { + contractFile.value = { + name: '合同文件', + url: res.contract_url || res.contract, + file_name: res.contract + } + } + if (res) { + // 转换数据格式以适配 OrderDetailDialog + const orderData: OrderData = res + + orderDialog.orderData = orderData + orderDialog.title = '合塑实业-汽车事业部-备货单(客户下定)' + orderDialog.visible = true + } + } catch (error) { + console.error('获取订单详情失败:', error) + ElMessage.error('获取订单详情失败') + } + // router.push({ + // path: '/admin/stock/show_admin', + // query: { id: row.id } // 可带客户名等参数 + // }) // TODO: 跳转或弹窗查看备货单 } - const handleView1 = (row: any) => { - router.push({ - path: '/admin/stock/final_show_admin', - query: { id: row.object_id } // 可带客户名等参数 - }) + const handleView1 = async (row: any) => { + const res = await manageService.checkStock({ id: row.object_id }) + if (res?.contract) { + contractFile.value = { + name: '合同文件', + url: res.contract_url || res.contract, + file_name: res.contract + } + } + if (res) { + // 获取订单详情成功 + const orderData: OrderData = res + orderDialog.orderData = orderData + orderDialog.title = '合塑实业-汽车事业部-备货单(客户下定)' + orderDialog.visible = true + } + // router.push({ + // path: '/admin/stock/final_show_admin', + // query: { id: row.object_id } // 可带客户名等参数 + // }) // router.push('/crmpc/stocking/final_show') // TODO: 跳转或弹窗查看备货单 } - const handleCreateRepair = (row: any) => { - router.push({ - path: '/crmpc/stocking/final_add', - query: { id: row.id } // 可带客户名等参数 + // 判断是否为图片文件 + const isImageFile = (file: { name: string; url: string; file_name: string }) => { + // 检查文件名 + if (file.name && /\.(jpg|jpeg|png|gif|webp)$/i.test(file.name)) { + return true + } + + // 检查file_name字段 + if (file.file_name && file.file_name.startsWith('image/')) { + return true + } + + // 检查URL中的文件扩展名(去除查询参数) + if (file.url) { + const urlWithoutParams = file.url.split('?')[0] // 移除查询参数 + if (/\.(jpg|jpeg|png|gif|webp)$/i.test(urlWithoutParams)) { + return true + } + } + + return false + } + + // 预览图片 + const previewImage = (file: { name: string; url: string; file_name: string }) => { + // 创建图片预览弹窗 + const imagePreview = document.createElement('div') + imagePreview.style.cssText = ` + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.8); + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + cursor: pointer; + ` + + const image = document.createElement('img') + image.src = file.url + image.alt = file.name + image.style.cssText = ` + max-width: 90%; + max-height: 90%; + object-fit: contain; + border-radius: 4px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5); + ` + + const closeBtn = document.createElement('div') + closeBtn.innerHTML = '×' + closeBtn.style.cssText = ` + position: absolute; + top: 20px; + right: 30px; + color: white; + font-size: 30px; + cursor: pointer; + z-index: 10000; + ` + + imagePreview.appendChild(image) + imagePreview.appendChild(closeBtn) + document.body.appendChild(imagePreview) + + // 点击关闭 + const closePreview = () => { + document.body.removeChild(imagePreview) + } + + imagePreview.addEventListener('click', closePreview) + closeBtn.addEventListener('click', (e) => { + e.stopPropagation() + closePreview() }) - // TODO: 跳转创建维修保单 + + // ESC键关闭 + const handleKeydown = (e: KeyboardEvent) => { + if (e.key === 'Escape') { + closePreview() + document.removeEventListener('keydown', handleKeydown) + } + } + document.addEventListener('keydown', handleKeydown) + } + + // 下载文件 + const downloadFile = (file: { name: string; url: string; file_name: string }) => { + try { + const link = document.createElement('a') + link.href = file.url + link.download = file.name + link.target = '_blank' + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + } catch (error) { + console.error('下载失败:', error) + ElMessage.error('下载失败,请稍后重试') + } } //打印 const printfn = (row: any) => { @@ -259,5 +451,18 @@ color: #ff0000; font-weight: bold; } + .no-file { + display: flex; + flex-direction: column; + align-items: center; + gap: 12px; + color: #999; + font-size: 14px; + } + + .no-file i { + font-size: 48px; + color: #ddd; + } diff --git a/src/views/crmpc/approval/auth_detil.vue b/src/views/crmpc/approval/auth_detil.vue index 53fc45c..eff5ce3 100644 --- a/src/views/crmpc/approval/auth_detil.vue +++ b/src/views/crmpc/approval/auth_detil.vue @@ -1,259 +1,13 @@