From 4d629b54ee8411b4c6a68deef6491d732b5e12c9 Mon Sep 17 00:00:00 2001 From: boyang <1920788179@qq.com> Date: Thu, 15 Aug 2024 22:47:07 +0800 Subject: [PATCH] 应收款与应付款前后端联调完成 --- src/api/project/approve.ts | 2 +- src/api/project/invoice.ts | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/api/project/order.ts | 10 ++++++++++ src/api/sys/config.ts | 6 ++++++ src/components/Modal/src/hooks/useModal.ts | 2 +- src/router/routes/modules/project/approve.ts | 3 ++- src/views/project/approve/ReceivePanel.vue | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/views/project/approve/index.vue | 8 ++++++++ src/views/project/config/CreateModal.vue | 11 +++++++++-- src/views/project/config/DrawerEdit.vue | 2 +- src/views/project/config/EmailPanel.vue | 2 +- src/views/project/config/TablePanel.vue | 2 +- src/views/project/config/data.tsx | 16 +++++++++++++++- src/views/project/config/index.vue | 9 ++++++++- src/views/project/finance/pay/CheckDetail.vue | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/views/project/finance/pay/CheckSum.vue | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/views/project/finance/pay/FinanceEdit.vue | 45 +++++++++++++++++++++++++++------------------ src/views/project/finance/pay/InvoiceUpload.vue | 50 ++++++++++++++++++++++++++++++++------------------ src/views/project/finance/pay/TrackEdit.vue | 58 ++++++++++++++++++++++++++++++++++++++++++---------------- src/views/project/finance/pay/index.vue | 332 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- src/views/project/finance/pay/pay.data.tsx | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------- src/views/project/finance/receive/FinanceEdit.vue | 13 ++++++++----- src/views/project/finance/receive/InvoiceAnalysis.vue | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------- src/views/project/finance/receive/InvoiceDetail.vue | 46 +++++++++++++++++++++++++++++++++++++++++----- src/views/project/finance/receive/TrackEdit.vue | 24 ++++++++++++++++-------- src/views/project/finance/receive/index.vue | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- src/views/project/finance/receive/receive.data.tsx | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- src/views/project/finance/receive/type.d.ts | 9 +++++++++ src/views/project/order/ExportModal.vue | 1 - src/views/project/order/FormDetail/index.vue | 32 +++++++++++++++++++++++--------- src/views/project/order/InvoiceCreate.vue | 11 ++++++----- src/views/project/order/PassCalculate.vue | 33 ++++++++++++++------------------- src/views/project/order/ProductInvoice.vue | 14 ++++++++++---- src/views/project/order/ProductText.vue | 35 +++++++++++++++++++++-------------- src/views/project/order/TrackHistory.vue | 33 ++++++++++++++++++++++++++++----- src/views/project/order/index.vue | 314 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------------------------- src/views/project/order/tableData.tsx | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ vite.config.ts | 3 +++ 38 files changed, 1939 insertions(+), 322 deletions(-) create mode 100644 src/views/project/approve/ReceivePanel.vue create mode 100644 src/views/project/finance/pay/CheckDetail.vue create mode 100644 src/views/project/finance/pay/CheckSum.vue create mode 100644 src/views/project/finance/receive/type.d.ts diff --git a/src/api/project/approve.ts b/src/api/project/approve.ts index ec5d6b7..854688a 100644 --- a/src/api/project/approve.ts +++ b/src/api/project/approve.ts @@ -30,7 +30,7 @@ export const getWaitListApi = async (params: DemoParams) => { res.records = res.records.map((item) => { return item; }); - + console.log(res.records, 5656565656); return new Promise((resolve) => { resolve({ items: res.records, total: res.total }); }); diff --git a/src/api/project/invoice.ts b/src/api/project/invoice.ts index 5b11834..2a006ff 100644 --- a/src/api/project/invoice.ts +++ b/src/api/project/invoice.ts @@ -11,9 +11,21 @@ enum Api { UPDATE_AMOUNT = '/order/erp/invoice_bill/update_amount_info', //更新其他金额信息 INVOICE_DELETE = '/order/erp/invoice_bill/delete_by_id', //删除数据 COMMIT = '/order/erp/invoice_bill/commit_apply', //提交审核 + + PRODUCT_CREATE = '/order/erp/check_bill/create', //创建生产科应付单据 + PAYED_DATE = '/order/erp/check_bill/get_payed_date', //获取生产科应回款日期 + UPDATE_DEDUCT_INFO = '/order/erp/check_bill/update_deduct_info', //更新扣款信息 + UPDATE_AMOUNT_INFO = '/order/erp/check_bill/update_amount_info', //更新其他金额信息 + UPDATE_INVOICE_INFO = '/order/erp/check_bill/update_invoice_info', //更新发票信息 + CHECK_COMMIT = '/order/erp/check_bill/commit_apply', //提交审核 + CHECK_DELETE = '/order/erp/check_bill/delete_by_id', //删除数据 + CHECK_BILL = '/order/erp/check_bill/list_by_page', //分页查询列表 + CHECK_DETAIL = '/order/erp/check_bill/list_base_order_info_by', //基础订单查询 + CHECK_ANALYSIS = '/order/erp/check_bill/list_analysis_by', //分析列表 + EXPORT_CHECK_ANALYSIS = '/order/erp/check_bill/export', //导出分析列表 } -export const getRefundDate = async (params: any) => { +export const getRefundDate = async (params: any, data?: any) => { const res = await defHttp.post<any>({ url: Api.REFUND_DATE, params, @@ -33,7 +45,6 @@ export const getInvoice = async (params: any) => { url: Api.INVOICE, params, }); - console.log(res, 5656); return res.records; }; export const getBaseInvoice = async (params: any) => { @@ -55,13 +66,15 @@ export const exportAnalysis = async (params: any) => { params, }); }; + export const updateDeduct = async (params: any) => { return await defHttp.post<any>({ url: Api.UPDATE_DEDUCT, params, }); }; -export const updateAmount = async (params: any, p0?: { id: any; bgUrl: any }) => { +// export const updateAmount = async (params: any, p0?: { id: any; bgUrl: any }) => { +export const updateAmount = async (params: any) => { return await defHttp.post<any>({ url: Api.UPDATE_AMOUNT, params, @@ -79,3 +92,72 @@ export const commit = async (params: any) => { params, }); }; + +export const checkCreate = async (params: any) => { + return await defHttp.post<any>({ + url: Api.PRODUCT_CREATE, + params, + }); +}; +export const payDate = async (params: any) => { + return await defHttp.post<any>({ + url: Api.PAYED_DATE, + params, + }); +}; +export const updateDeductInfo = async (params: any) => { + return await defHttp.post<any>({ + url: Api.UPDATE_DEDUCT_INFO, + params, + }); +}; +export const updateAmountInfo = async (params: any) => { + return await defHttp.post<any>({ + url: Api.UPDATE_AMOUNT_INFO, + params, + }); +}; +export const checkCommit = async (params: any) => { + return await defHttp.post<any>({ + url: Api.CHECK_COMMIT, + params, + }); +}; +export const checkDelete = async (params: any, id?: string[]) => { + return await defHttp.post<any>({ + url: Api.CHECK_DELETE, + params, + }); +}; +export const getCheck = async (params: any) => { + const res = await defHttp.post<any>({ + url: Api.CHECK_BILL, + params, + }); + console.log(res, '5656check'); + return res.records; +}; +export const checkDetail = async (params: any) => { + return await defHttp.post<any>({ + url: Api.CHECK_DETAIL, + params, + }); +}; +export const checkAnalysis = async (params: any) => { + return await defHttp.post<any>({ + url: Api.CHECK_ANALYSIS, + params, + }); +}; +export const updateInvoiceInfo = async (params: any) => { + return await defHttp.post<any>({ + url: Api.UPDATE_INVOICE_INFO, + params, + }); +}; +export const exportCheckAnalysis = async (params: any) => { + return await defHttp.post<any>({ + url: Api.EXPORT_CHECK_ANALYSIS, + params, + }); +}; diff --git a/src/api/project/order.ts b/src/api/project/order.ts index de03148..44d170b 100644 --- a/src/api/project/order.ts +++ b/src/api/project/order.ts @@ -33,6 +33,7 @@ enum Api { ORDER_FIELD_CHECK = '/order/erp/order/check', // 校验内部编号是否重复 TRACK_HISTORY = '/order/erp/opinion/log/query_by_id', //跟单结果记录 + PASS_CALCULATE = '/order/erp/order/passRate', //一次性通过率 } export const formatSearchData = (params) => { @@ -187,6 +188,7 @@ export const orderExport = async (data: any = {}) => { a.download = `${strArr.join('_')} ${date}.xlsx`; // 你可以为文件命名 document.body.appendChild(a); a.click(); // 模拟点击操作来下载文件 + console.log(a, '5656a'); URL.revokeObjectURL(downloadUrl); // 释放掉 blob 对象所占用的内存 document.body.removeChild(a); @@ -305,3 +307,11 @@ export const trackHistory = async (data: any) => { }); return res; }; + +export const passCalculate = async (data: any) => { + const res = await defHttp.post<any>({ + url: Api.PASS_CALCULATE, + data: data, + }); + return res; +}; diff --git a/src/api/sys/config.ts b/src/api/sys/config.ts index 0696780..4766d4d 100644 --- a/src/api/sys/config.ts +++ b/src/api/sys/config.ts @@ -91,6 +91,12 @@ export const getEmailList = async (params: any) => { params, }); const resAll = dealRecords(res.records); + resAll.sort((a, b) => { + if (a.enableFlag === b.enableFlag) { + return 0; + } + return a.enableFlag === 10 ? -1 : 1; + }); return resAll; }; diff --git a/src/components/Modal/src/hooks/useModal.ts b/src/components/Modal/src/hooks/useModal.ts index c4cade2..d33f404 100644 --- a/src/components/Modal/src/hooks/useModal.ts +++ b/src/components/Modal/src/hooks/useModal.ts @@ -100,7 +100,7 @@ export function useModal(): UseModalReturnType { return [register, methods]; } -export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType => { +export const useModalInner = (callbackFn?: Fn, p0?: () => Promise<void>): UseModalInnerReturnType => { const modalInstanceRef = ref<Nullable<ModalMethods>>(null); const currentInstance = getCurrentInstance(); const uidRef = ref<string>(''); diff --git a/src/router/routes/modules/project/approve.ts b/src/router/routes/modules/project/approve.ts index 1c7945a..fd2a9f9 100644 --- a/src/router/routes/modules/project/approve.ts +++ b/src/router/routes/modules/project/approve.ts @@ -1,6 +1,7 @@ import type { AppRouteModule } from '/@/router/types'; import { LAYOUT } from '/@/router/constant'; +import { RoleEnum } from '/@/enums/roleEnum'; const order: AppRouteModule = { path: '/approve', @@ -10,7 +11,7 @@ const order: AppRouteModule = { meta: { hideChildrenInMenu: true, orderNo: 3, - // icon: 'ion:grid-outline', + icon: 'ion:grid-outline', title: '审批管理', }, children: [ diff --git a/src/views/project/approve/ReceivePanel.vue b/src/views/project/approve/ReceivePanel.vue new file mode 100644 index 0000000..8d02d13 --- /dev/null +++ b/src/views/project/approve/ReceivePanel.vue @@ -0,0 +1,222 @@ +<template> + <BasicTable @register="registerTable" className="p-0"> + <template #form-custom> custom-slot </template> + <template #bodyCell="{ column, record }"> + <template v-if="column.key === 'picUrl'"> + <img + :width="50" + :height="50" + :src="record?.orderBaseInfo?.smallPicUrl" + @click="handlePreview(record?.orderBaseInfo?.picUrl)" + /> + </template> + <template v-if="column.key === 'action'"> + <TableAction + :actions="[ + { + label: '编辑', + // icon: 'ic:outline-delete-outline', + onClick: handleDetail.bind(null, record), + }, + ]" + /> + </template> + </template> + </BasicTable> + <BasicDrawer + :showFooter="!isApproved && role === ROLE.ADMIN" + @register="registerDrawer" + title="申请信息" + okText="通过" + @ok="handleTrue" + > + <BaseInfo :baseInfos="baseInfos" /> + <h2>收款单信息</h2> + <div v-for="field in fieldInfos" :key="field"> + <span className="w-[140px] inline-block text-right mr-3">{{ field.label }}:</span + ><span>{{ field.value }}</span> + </div> + <template #appendFooter> + <a-button @click="handleFalse"> 不通过</a-button> + </template> + </BasicDrawer> + <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" /> +</template> +<script lang="ts"> + import MsgModal from './MsgModal.vue'; + import { computed, defineComponent, ref } from 'vue'; + import { BasicTable, useTable, TableAction } from '/@/components/Table'; + import { BasicDrawer, useDrawer } from '/@/components/Drawer'; + + import { approveAuditApi, getApprovedListApi, getWaitListApi } from '/@/api/project/approve'; + import { FIELDS_BASE_INFO, FIELDS_PROFIT_INFO, FIELDS_REPORT_INFO } from '../order/tableData'; + import { ROLE } from '../order//type.d'; + import { useUserStoreWithOut } from '/@/store/modules/user'; + import BaseInfo from './BaseInfo.vue'; + import { createImgPreview } from '/@/components/Preview'; + import { getFormConfig } from './data'; + + const userStore = useUserStoreWithOut(); + + export default defineComponent({ + components: { + BasicTable, + BasicDrawer, + TableAction, + BaseInfo, + MsgModal, + }, + props: { + isApproved: { type: Boolean }, + }, + setup(props) { + // visible 用于msgModal显示隐藏 + const msgVisible = ref(false); + const checkedKeys = ref<Array<string | number>>([]); + const currentKey = ref('1'); + const [registerDrawer, { openDrawer, closeDrawer }] = useDrawer(); + const fieldInfos = ref({}); + const baseInfos = ref({}); + const id = ref(''); + + let columns = [ + { + title: '申请人', + dataIndex: 'createBy', + width: 150, + }, + { + title: 'INVOICE编号', + dataIndex: 'invoiceNo', + width: 150, + customRender: (column) => { + const { record } = column || {}; + return record?.fieldInfos?.invoiceBillOrderDO?.invoiceNo; + }, + }, + // { + // title: '内部编号', + // dataIndex: 'innerNo', + // width: 150, + // customRender: (column) => { + // const { record } = column || {}; + // return record?.fieldInfos?.invoiceBillOrderDO?.innerNo; + // }, + // }, + ]; + + if (props.isApproved) { + columns = columns.concat([ + { + title: '状态', + dataIndex: 'status', + width: 150, + customRender: (column) => { + const { record } = column || {}; + + return record.status === 10 ? '通过' : '拒绝'; + }, + }, + { title: '拒绝原因', dataIndex: 'refuseRemark', width: 250 }, + ]); + } + + const [registerTable, { reload }] = useTable({ + api: props.isApproved ? getApprovedListApi : getWaitListApi, + searchInfo: { type: 30 }, + // scroll: { + // scrollToFirstRowOnChange: true, + // }, + columns, + useSearchForm: true, + formConfig: getFormConfig(), + rowKey: 'id', + actionColumn: { + width: 160, + title: 'Action', + dataIndex: 'action', + // slots: { customRender: 'action' }, + }, + }); + + function onSelect(record, selected) { + if (selected) { + checkedKeys.value = [...checkedKeys.value, record.id]; + } else { + checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id); + } + } + function onSelectAll(selected, selectedRows, changeRows) { + const changeIds = changeRows.map((item) => item.id); + if (selected) { + checkedKeys.value = [...checkedKeys.value, ...changeIds]; + } else { + checkedKeys.value = checkedKeys.value.filter((id) => { + return !changeIds.includes(id); + }); + } + } + function handleEdit(record, e) { + e?.stopPropagation(); + return false; + } + + function handleProfitModal() {} + + async function handleDetail(data) {} + + async function handleTrue() { + await approveAuditApi({ status: 10, id: id.value }); + reload(); + closeDrawer(); + } + + async function handleFalse() { + msgVisible.value = true; + // await approveAuditApi({ status: 20, id: id.value }); + // reload(); + // closeDrawer(); + } + + const role = computed(() => { + return userStore.getUserInfo?.roleSmallVO?.code; + }); + + // 定义MsgModalClose的事件,方便子组件调用 + const handleMsgModalClose = async (data) => { + if (data) { + await approveAuditApi({ status: 20, id: id.value, refuseRemark: data }); + reload(); + closeDrawer(); + } + msgVisible.value = false; + }; + + const handlePreview = (url) => { + createImgPreview({ imageList: [url], defaultWidth: 500 }); + return false; + }; + + return { + handleProfitModal, + registerTable, + checkedKeys, + currentKey, + onSelect, + handleEdit, + onSelectAll, + handleDetail, + registerDrawer, + fieldInfos, + baseInfos, + handleTrue, + handleFalse, + role, + ROLE, + msgVisible, + handleMsgModalClose, + handlePreview, + }; + }, + }); +</script> diff --git a/src/views/project/approve/index.vue b/src/views/project/approve/index.vue index b63cc9c..fead471 100644 --- a/src/views/project/approve/index.vue +++ b/src/views/project/approve/index.vue @@ -10,6 +10,9 @@ <a-tab-pane key="5" tab="项目报告书待审核"> <ReportPanel /> </a-tab-pane> + <a-tab-pane key="7" tab="应收款待审核"> + <ReceivePanel /> + </a-tab-pane> <a-tab-pane key="2" tab="字段已审核"> <FieldPanel isApproved /> </a-tab-pane> @@ -19,6 +22,9 @@ <a-tab-pane key="6" tab="项目报告书已审核"> <ReportPanel isApproved /> </a-tab-pane> + <a-tab-pane key="8" tab="应收款已审核"> + <ReceivePanel isApproved /> + </a-tab-pane> </a-tabs> </div> </template> @@ -28,6 +34,7 @@ import ReportPanel from './ReportPanel.vue'; import ProfitPanel from './ProfitPanel.vue'; import FieldPanel from './FieldPanel.vue'; + import ReceivePanel from './ReceivePanel.vue'; import { useOrderStoreWithOut } from '/@/store/modules/order'; const orderStore = useOrderStoreWithOut(); @@ -39,6 +46,7 @@ ReportPanel, FieldPanel, ProfitPanel, + ReceivePanel, }, setup() { const checkedKeys = ref<Array<string | number>>([]); diff --git a/src/views/project/config/CreateModal.vue b/src/views/project/config/CreateModal.vue index 2dca6b8..bc26ba7 100644 --- a/src/views/project/config/CreateModal.vue +++ b/src/views/project/config/CreateModal.vue @@ -58,7 +58,7 @@ { field: 'relationValue', component: 'InputNumber', - label: props.column === 1 ? '利润率' : '包装费用', + label: props.column === 1 ? '利润率' : props.column === 5 ? '回款时间' : '包装费用', rules: [{ required: true }], colProps: { span: 24, @@ -96,7 +96,14 @@ settingName: '客户编码', settingValue: values.settingValue, settingType: 1, - relationCode: props.column === 1 ? 'profitRate' : 'packetPrice', + // relationCode: props.column === 1 ? 'profitRate' : 'packetPrice', + relationCode: + props.column === 1 + ? 'profitRate' + : props.column === 5 + ? 'orderHodTime' + : 'packetPrice', + relationName: '包装费用', relationValue: values.relationValue, }; diff --git a/src/views/project/config/DrawerEdit.vue b/src/views/project/config/DrawerEdit.vue index be8e4b3..373f579 100644 --- a/src/views/project/config/DrawerEdit.vue +++ b/src/views/project/config/DrawerEdit.vue @@ -50,7 +50,7 @@ colProps: { span: 23, }, - label: '确认样品确认状态(填写邮箱)', + label: '确认样品确认状态(填写邮箱,请用逗号隔开)', rules: [{ required: true }], }, { diff --git a/src/views/project/config/EmailPanel.vue b/src/views/project/config/EmailPanel.vue index 1e289f3..bb3d906 100644 --- a/src/views/project/config/EmailPanel.vue +++ b/src/views/project/config/EmailPanel.vue @@ -1,5 +1,5 @@ <template> - <div class="p-4"> + <div :style="{ marginLeft: '0px' }"> <BasicTable @register="registerTable"> <template #toolbar> <!-- <a-button type="primary" class="my-4" @click="handleCreate"> 新增 </a-button> --> diff --git a/src/views/project/config/TablePanel.vue b/src/views/project/config/TablePanel.vue index b24667c..c1afa54 100644 --- a/src/views/project/config/TablePanel.vue +++ b/src/views/project/config/TablePanel.vue @@ -1,5 +1,5 @@ <template> - <BasicTable @register="registerTable"> + <BasicTable @register="registerTable" :bordered="true"> <template #toolbar> <a-button v-if="props.column !== 3" type="primary" @click="handleCreateModal">新建</a-button> </template> diff --git a/src/views/project/config/data.tsx b/src/views/project/config/data.tsx index f6ca632..93f7c5d 100644 --- a/src/views/project/config/data.tsx +++ b/src/views/project/config/data.tsx @@ -45,6 +45,20 @@ export const COLUMNS = { editRow: true, }, ], + 5: [ + { + title: '客户编码', + dataIndex: 'settingValue', + width: 150, + }, + { + title: '最后汇款日期', + dataIndex: 'relationValue', + width: 150, + editComponent: 'InputNumber', + editRow: true, + }, + ], }; export const columns: BasicColumn[] = [ @@ -56,7 +70,7 @@ export const columns: BasicColumn[] = [ { title: '状态', dataIndex: 'enableFlag', - width: 70, + width: 100, customRender: (column) => { const { record } = column || {}; return record.enableFlag === 10 ? <Tag color="green">启用</Tag> : <Tag color="red">禁用</Tag>; diff --git a/src/views/project/config/index.vue b/src/views/project/config/index.vue index 3b2a57f..babbe0e 100644 --- a/src/views/project/config/index.vue +++ b/src/views/project/config/index.vue @@ -1,7 +1,11 @@ <template> <PageWrapper contentBackground> <div className="config-page"> - <Tabs v-model:selectedKey="currentKey" className="ml-2 mb-0"> + <Tabs + v-model:selectedKey="currentKey" + className="ml-2 mb-0" + :style="{ marginLeft: '30px', marginRight: '5px' }" + > <Tabs.TabPane key="1" tab="利润率配置"> <TablePanel :searchInfo="{ relationCode: 'profitRate' }" :column="1" /> </Tabs.TabPane> @@ -12,6 +16,9 @@ <TablePanel :searchInfo="{ settingCode: 'exchangeRate' }" :column="3" /></Tabs.TabPane> <Tabs.TabPane key="4" tab="邮件发送配置"><EmailPanel /></Tabs.TabPane> + <Tabs.TabPane key="5" tab="最后汇款日期"> + <TablePanel :searchInfo="{ relationCode: 'orderHodTime' }" :column="5" /> + </Tabs.TabPane> </Tabs> </div> </PageWrapper> diff --git a/src/views/project/finance/pay/CheckDetail.vue b/src/views/project/finance/pay/CheckDetail.vue new file mode 100644 index 0000000..1f62300 --- /dev/null +++ b/src/views/project/finance/pay/CheckDetail.vue @@ -0,0 +1,120 @@ +<template> + <template> + <BasicDrawer + @register="register" + v-bind="$attrs" + title="订单信息" + width="60%" + :isDetail="true" + :showDetailBack="false" + :destroyOnClose="true" + > + <div class="p-4"> + <BasicTable @register="registerTable"> + <template #bodyCell="{ column, record }"> + <template v-if="column.key === 'action'"> </template> + <template v-if="column.key === 'picUrl'"> + <img :z-index="100000" :width="50" :height="50" :src="record?.smallPicUrl" /> + </template> + </template> + </BasicTable> + </div> + </BasicDrawer> + </template> +</template> +<script lang="ts" setup> + import { BasicDrawer, useDrawerInner } from '@/components/Drawer'; + import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue'; + import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table'; + import { checkDetail } from '/@/api/project/invoice'; + import { useDesign } from '@/hooks/web/useDesign'; + + // const handlePreview = (url) => { + // createImgPreview({ imageList: [url], defaultWidth: 500 }); + // return false; + // }; + const columns: BasicColumn[] = [ + { + title: '客户编码', + dataIndex: 'customerCode', + width: 100, + }, + { + title: '项目号', + dataIndex: 'projectNo', + width: 100, + }, + { + title: '内部编码', + dataIndex: 'innerNo', + width: 100, + }, + { + title: '客户po号', + dataIndex: 'customerPo', + width: 100, + }, + { + title: '客户STYLE', + width: 150, + dataIndex: 'customerStyle', + }, + { + title: 'Model(REFERENCE)', + width: 150, + dataIndex: 'modeleLo', + }, + { + title: '订单图片', + width: 150, + dataIndex: 'picUrl', + }, + { + title: '数量', + width: 150, + dataIndex: 'orderCount', + }, + { + title: '生产科单价¥', + width: 150, + dataIndex: 'productionDepartmentPrice', + customRender: (column) => { + const { record } = column || {}; + return record?.profitAnalysisInfo?.productionDepartmentPrice; + // ? `¥ ${record?.profitAnalysisInfo?.productionDepartmentPrice}` + // : ''; + }, + }, + { + title: '生产科总价¥', + width: 150, + dataIndex: 'productionDepartmentTotalPrice', + customRender: (column) => { + const { record } = column || {}; + return record?.profitAnalysisInfo?.productionDepartmentTotalPrice; + // ? `¥ ${record?.profitAnalysisInfo?.productionDepartmentTotalPrice}` + // : ''; + }, + }, + ]; + const checkNo = ref(); + + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { + // 方式1 + checkNo.value = data.data.checkNo; + console.log(data, '56562vvsdfv'); + // checkDetail({ checkNo: checkNo.value }); + }); + const params = ref({ + checkNo: checkNo.value, + }); + const [registerTable] = useTable({ + api: () => { + const res = checkDetail({ checkNo: checkNo.value }); + console.log(res, 56565555); + return res; + }, + columns: columns, + bordered: true, + }); +</script> diff --git a/src/views/project/finance/pay/CheckSum.vue b/src/views/project/finance/pay/CheckSum.vue new file mode 100644 index 0000000..50acdf8 --- /dev/null +++ b/src/views/project/finance/pay/CheckSum.vue @@ -0,0 +1,146 @@ +<template> + <BasicModal + v-bind="$attrs" + @register="register" + title="收款单汇总" + width="80%" + :isDetail="true" + :showDetailBack="false" + @ok="handleOk" + @visible-change="handleShow" + > + <div class="p-4"> + <BasicTable @register="registerTable"> + <template #bodyCell="{ column, record }"> + <template v-if="column.key === 'action'"> </template> + </template> + </BasicTable> + </div> + </BasicModal> +</template> +<script lang="ts" setup> + import { BasicModal, useModalInner } from '@/components/Modal'; + import { computed, ref } from 'vue'; + import { checkAnalysis, exportCheckAnalysis } from '@/api/project/invoice'; + import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table'; + // 处理弹窗的确定按钮点击事件 + import axios from 'axios'; + + const columnsAnalysis: BasicColumn[] = [ + { + title: '生产科名称', + dataIndex: 'productionDepartment', + width: 50, + customRender: (res) => { + // console.log(res, 56562); + return res.record.exportVOS[0].productionDepartment; + }, + }, + { + title: '生产科总价汇总', + dataIndex: 'productionDepartmentTotalPrice', + width: 50, + }, + { + title: '生产科扣款金额汇总', + dataIndex: 'actualReceivableAmount', + width: 50, + }, + { + title: '生产科实际应付金额', + dataIndex: 'calculateActualPayedAmount', + width: 50, + }, + { + title: '实际付款金额汇总', + dataIndex: 'actualPayedAmount', + width: 50, + }, + { + title: '未付金额', + dataIndex: 'unPayedAmount', + width: 50, + }, + ]; + // const ids = ref<number[]>([]); + const ids = ref(); + // const res = ref(); + + const [register, { closeModal }] = useModalInner(async (data) => { + ids.value = data.data; + setTimeout(() => { + reload(); + }, 50); + }); + const [registerTable, { reload }] = useTable({ + // api: () => invoiceAnalysis({ ids: ids.value }), + api: async () => { + const res = await checkAnalysis({ ids: ids.value }); + const arrayRes = ref([]); + arrayRes.value.push(res); + console.log(res, 56561); + return arrayRes.value; + }, + columns: columnsAnalysis, + bordered: true, + }); + function handleShow(visible: boolean) { + reload(); + } + const searchData = ref({}); + async function handleOk() { + // 构造符合 API 要求的参数 + // const ids = [23]; + // const requestData = { + // ids: ids.value, + // }; + const idss = ids.value; + // await exportCheckAnalysis({ ids: ids }); + axios + .post( + '/basic-api/order/erp/check_bill/export', + { ids: idss }, + { + responseType: 'blob', // 设置响应类型为 'blob' + }, + ) + .then((response) => { + // 创建一个 Blob 对象来保存二进制数据 + const blob = new Blob([response.data], { type: 'application/zip' }); + const getFormattedDate = (): string => { + const date = new Date(); + + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const seconds = String(date.getSeconds()).padStart(2, '0'); + + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; + }; + const date = getFormattedDate(); + // 创建一个链接元素用于下载 + const link = document.createElement('a'); + link.href = window.URL.createObjectURL(blob); + link.download = `应付款分析${date}.xlsx`; // 你可以为文件命名 + document.body.appendChild(link); + link.click(); // 自动点击链接,触发下载 + console.log(link, 5656); + document.body.removeChild(link); // 下载完成后移除链接 + }) + .catch((error) => { + console.error(error); + }); + reload(); + closeModal(); + } +</script> +<style scoped> + .divAll { + display: flex; + justify-content: center; + align-items: center; + } +</style> diff --git a/src/views/project/finance/pay/FinanceEdit.vue b/src/views/project/finance/pay/FinanceEdit.vue index 6874405..817df63 100644 --- a/src/views/project/finance/pay/FinanceEdit.vue +++ b/src/views/project/finance/pay/FinanceEdit.vue @@ -28,11 +28,13 @@ import { BasicForm, FormSchema, useForm } from '@/components/Form'; import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue'; import { getEmailList } from '/@/api/sys/config'; + import { updateAmountInfo } from '@/api/project/invoice'; + const emit = defineEmits(['success']); const schemas: FormSchema[] = [ { - field: 'configSample', - component: 'Input', + field: 'actualPayedAmount', + component: 'InputNumber', labelWidth: 250, colProps: { span: 23, @@ -40,31 +42,31 @@ label: '生产科实际应付金额', }, { - field: 'configSample', - component: 'Input', + field: 'actualPayedAmount1', + component: 'InputNumber', labelWidth: 250, colProps: { span: 23, }, - label: '实际应收金额1', + label: '实际应付金额1', }, { - field: 'configSample', - component: 'Input', + field: 'actualPayedAmount2', + component: 'InputNumber', labelWidth: 250, colProps: { span: 23, }, - label: '实际应收金额2', + label: '实际应付金额2', }, { - field: 'configSample', - component: 'Input', + field: 'actualPayedAmount3', + component: 'InputNumber', labelWidth: 250, colProps: { span: 23, }, - label: '实际应收金额3', + label: '实际应付金额3', }, ]; const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({ @@ -76,23 +78,30 @@ span: 24, }, }); + + const update = ref(); const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { // 方式1 - console.log(data, 56561); resetFields(); setDrawerProps({ confirmLoading: false }); setFieldsValue({ ...toRaw(data.data), }); + update.value = data; + console.log(data, '5656data'); }); - //获取现有的列表 - async function getData() { - const emailAll = await getEmailList({}); - return emailAll; - } //完成编辑 async function handleSubmit() { const values = await validate(); - console.log('5656handleSubmit'); + const updatedValues = { + ...values, + id: update.value.data.id, + }; + console.log(updatedValues, 56565); + await updateAmountInfo({ + ...updatedValues, + }); + emit('success'); + closeDrawer(); } </script> diff --git a/src/views/project/finance/pay/InvoiceUpload.vue b/src/views/project/finance/pay/InvoiceUpload.vue index b9c4996..8460940 100644 --- a/src/views/project/finance/pay/InvoiceUpload.vue +++ b/src/views/project/finance/pay/InvoiceUpload.vue @@ -4,13 +4,15 @@ @register="register" title="发票上传" width="500px" - :bodyStyle="{ height: '200px' }" + :bodyStyle="{ height: '240px' }" @ok="handleOk" ><a-upload-dragger v-model:fileList="fileList" name="file" + :beforeUpload="beforeUpload" + :max-count="1" :multiple="true" - action="https://www.mocky.io/v2/5cc8019d300000980a055e76" + :action="updateInvoiceUrl" @change="handleChange" @drop="handleDrop" > @@ -27,31 +29,43 @@ import type { UploadProps, UploadChangeParam } from 'ant-design-vue'; import { InboxOutlined } from '@ant-design/icons-vue'; import { message } from 'ant-design-vue'; + import { updateInvoiceInfo } from '@/api/project/invoice'; - const handleChange = (info: UploadChangeParam) => { - const status = info.file.status; - if (status !== 'uploading') { - console.log(info.file, info.fileList); - } - if (status === 'done') { - message.success(`${info.file.name} file uploaded successfully.`); - } else if (status === 'error') { - message.error(`${info.file.name} file upload failed.`); + const emit = defineEmits(['success']); + const uploadUrl = ref('http://47.104.8.35:18000/api/localStorage/upload_file_oss?name='); + const updateInvoiceUrl = ref('http://47.104.8.35:18000/api/localStorage/upload_file_oss?name='); + const invoiceUrl = ref(); + const id = ref(); + + const [register, { closeModal }] = useModalInner(async (data) => { + // fileList.value = []; + fileList.value = []; + invoiceUrl.value = data.data.invoiceUrl; + id.value = data.data.id; + }); + + const handleChange = (info) => { + if (info.file.status == 'done') { + updateInvoiceUrl.value = info.file.response.data.fileUrl; + invoiceUrl.value = updateInvoiceUrl.value; } }; + function beforeUpload(info) { + updateInvoiceUrl.value = uploadUrl.value + info.name; + } function handleDrop(e: DragEvent) { console.log(e); } const fileList = ref<UploadProps['fileList']>([]); - const Input1 = ref(''); - const Input2 = ref('123'); - - const [register, { closeModal }] = useModalInner(async (data) => { - title.value = data.title; - }); - const title = ref(''); async function handleOk() { + await updateInvoiceInfo({ + id: id.value, + invoiceUrl: invoiceUrl.value, + }); + // await updateDeduct(requestData); + fileList.value = []; + emit('success'); closeModal(); } </script> diff --git a/src/views/project/finance/pay/TrackEdit.vue b/src/views/project/finance/pay/TrackEdit.vue index d21d769..0840ac7 100644 --- a/src/views/project/finance/pay/TrackEdit.vue +++ b/src/views/project/finance/pay/TrackEdit.vue @@ -3,7 +3,7 @@ <BasicDrawer @register="register" v-bind="$attrs" - title="编辑" + title="跟单编辑" width="30%" :isDetail="true" @ok="handleSubmit" @@ -14,23 +14,22 @@ > <div> <div style="font-size: 15px">生产科扣款金额</div> - <a-input v-model:value="Input1" placeholder="请输入" auto-size /> + <a-input v-model:value="input1" placeholder="请输入" auto-size /> <div style="margin: 16px 0"></div> <div style="font-size: 15px">扣款责任部门</div> - <a-input v-model:value="Input2" placeholder="请输入" auto-size /> + <a-input v-model:value="deductDept" placeholder="请输入" auto-size /> <div style="margin: 16px 0"></div> <div>上传扣款单</div ><a-space direction="vertical" style="width: 100%" size="large"> <a-upload v-model:file-list="fileList" + :beforeUpload="beforeUpload" list-type="picture" :max-count="1" - action="https://www.mocky.io/v2/5cc8019d300000980a055e76" + :action="updateDeductUrl" + @change="handleChange" > - <a-button> - <!-- <upload-outlined></upload-outlined> --> - 上传报关单 - </a-button> + <a-button> 上传扣款单 </a-button> </a-upload> </a-space> </div> @@ -47,22 +46,49 @@ import { getEmailList } from '/@/api/sys/config'; import { UploadOutlined } from '@ant-design/icons-vue'; import type { UploadProps } from 'ant-design-vue'; + import { updateDeductInfo } from '@/api/project/invoice'; + const emit = defineEmits(['success']); const fileList = ref<UploadProps['fileList']>([]); - const Input1 = ref(''); - const Input2 = ref('123'); + const input1 = ref(); + const deductUrl = ref(); + const id = ref(); + const checkNo = ref(); + const deductDept = ref(); + const uploadUrl = ref('http://47.104.8.35:18000/api/localStorage/upload_file_oss?name='); + const updateDeductUrl = ref('http://47.104.8.35:18000/api/localStorage/upload_file_oss?name='); const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { - console.log(data, 56561); + id.value = data.data.id; + checkNo.value = data.data.checkNo; + input1.value = data.data.deductAmount; + deductDept.value = data.data.deductDept; + deductUrl.value = data.data.deductUrl; }); - //获取现有的列表 - async function getData() { - const emailAll = await getEmailList({}); - return emailAll; + + function handleChange(info) { + if (info.file.status == 'done') { + updateDeductUrl.value = info.file.response.data.fileUrl; + deductUrl.value = updateDeductUrl.value; + } + } + function beforeUpload(info) { + updateDeductUrl.value = uploadUrl.value + info.name; } + //完成编辑 async function handleSubmit() { - console.log('5656handleSubmit'); + await updateDeductInfo({ + id: id.value, + checkNo: checkNo.value, + deductAmount: input1.value, + deductDept: deductDept.value, + deductUrl: deductUrl.value, + }); + // await updateDeduct(requestData); + fileList.value = []; + emit('success'); + closeDrawer(); } </script> diff --git a/src/views/project/finance/pay/index.vue b/src/views/project/finance/pay/index.vue index 148bbcd..d4a58ff 100644 --- a/src/views/project/finance/pay/index.vue +++ b/src/views/project/finance/pay/index.vue @@ -2,10 +2,12 @@ <div class="p-4"> <BasicTable @register="registerTable"> <template #toolbar> - <a-button type="primary">导出</a-button> - <FinanceEdit @register="registerFinanceEdit" /> - <TrackEdit @register="registerTrackEdit" /> - <InvoiceUpload @register="registerInvoiceUpload" /> + <a-button type="primary" @click="handleCheckSum">应付款汇总</a-button> + <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> + <TrackEdit @register="registerTrackEdit" @success="handleSuccess" /> + <CheckSum @register="registerCheckSum" /> + <InvoiceUpload @register="registerInvoiceUpload" @success="handleSuccess" /> + <CheckDetail @register="registerInvoiceDetail" /> </template> <template #bodyCell="{ column, record }"> <template v-if="column.key === 'action'"> @@ -26,11 +28,15 @@ ]" :dropDownActions="[ { - label: '应付款提交', - onClick: handleDelete.bind(null, record), + label: '提交审核', + onClick: handleCommit.bind(null, record), }, { label: '订单信息', + onClick: handleDetail.bind(null, record), + }, + { + label: '删除', onClick: handleDelete.bind(null, record), }, ]" @@ -41,28 +47,38 @@ </div> </template> <script lang="ts" setup> - import { defineComponent } from 'vue'; + import { defineComponent, ref } from 'vue'; import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table'; import { searchFormSchema, columns } from './pay.data'; - import { demoListApi } from '/@/api/demo/table'; import TrackEdit from './TrackEdit.vue'; import FinanceEdit from './FinanceEdit.vue'; import InvoiceUpload from './InvoiceUpload.vue'; + import CheckDetail from './CheckDetail.vue'; + import CheckSum from './CheckSum.vue'; import { useDrawer } from '/@/components/Drawer'; import { useModal } from '/@/components/Modal'; + import { getCheck, checkDelete, checkCommit, checkDetail } from '@/api/project/invoice'; + import { useMessage } from '/@/hooks/web/useMessage'; + const [registerCheckSum, { openModal: openCheckSum }] = useModal(); const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); const [registerTrackEdit, { openDrawer: openTrackEdit }] = useDrawer(); const [registerInvoiceUpload, { openModal: openInvoiceUpload }] = useModal(); + const [registerInvoiceDetail, { openDrawer: openCheckDetail }] = useDrawer(); + const checkedKeys = ref<Array<string | number>>([]); - const [registerTable] = useTable({ + const [registerTable, { reload }] = useTable({ title: '', - api: demoListApi, + api: getCheck, columns: columns, bordered: true, + clickToRowSelect: false, rowKey: 'id', rowSelection: { type: 'checkbox', + selectedRowKeys: checkedKeys, + onSelect, + onSelectAll, }, formConfig: { labelWidth: 120, @@ -82,28 +98,314 @@ // slots: { customRender: 'action' }, }, }); + //选择 + // function onSelect(record, selected) { + // if (selected) { + // checkedKeys.value = [...checkedKeys.value, record.id]; + // } else { + // checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id); + // } + // } + // function onSelectAll(selected, selectedRows, changeRows) { + // const changeIds = changeRows.map((item) => item.id); + // if (selected) { + // checkedKeys.value = [...checkedKeys.value, ...changeIds]; + // } else { + // checkedKeys.value = checkedKeys.value.filter((id) => { + // return !changeIds.includes(id); + // }); + // } + // } + + // type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count] + + // const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref + + // // 选择函数 + // async function onSelect(record: any, selected: boolean) { + // if (selected) { + // const res = await checkDetail({ checkNo: record.checkNo }); + // const customerCode = res[0].customerCode; + + // const index = selectedCustomCodes.value.findIndex(([code]) => code === customerCode); + + // if (index !== -1) { + // // 如果存在,增加计数 + // selectedCustomCodes.value[index][1] += 1; + // } else { + // // 如果不存在,添加新项 [customerCode, 1] + // selectedCustomCodes.value.push([customerCode, 1]); + // } + + // checkedKeys.value = [...checkedKeys.value, record.id]; + // } else { + // const res = await checkDetail({ checkNo: record.checkNo }); + // const customerCode = res[0].customerCode; + + // const index = selectedCustomCodes.value.findIndex(([code]) => code === customerCode); + + // if (index !== -1) { + // if (selectedCustomCodes.value[index][1] > 1) { + // // 如果计数大于 1,减少计数 + // selectedCustomCodes.value[index][1] -= 1; + // } else { + // // 如果计数为 1,移除该项 + // selectedCustomCodes.value.splice(index, 1); + // } + // } + + // checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id); + // } + // console.log(selectedCustomCodes.value, 56561); + // console.log(checkedKeys.value, 56562); + // } + + // async function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) { + // const changeIds = changeRows.map((item) => item.id); + // const changeCustomerCodes = await Promise.all( + // changeRows.map(async (item) => { + // const res = await checkDetail({ checkNo: item.checkNo }); + // return res[0].customerCode; + // }), + // ); + + // if (selected) { + // // 添加到 checkedKeys + // checkedKeys.value = [...checkedKeys.value, ...changeIds]; + + // // 处理每个 customerCode + // changeCustomerCodes.forEach((code) => { + // const index = selectedCustomCodes.value.findIndex( + // ([customerCode]) => customerCode === code, + // ); + // if (index !== -1) { + // // 如果存在,增加计数 + // selectedCustomCodes.value[index][1] += 1; + // } else { + // // 如果不存在,添加新项 [customerCode, 1] + // selectedCustomCodes.value.push([code, 1]); + // } + // }); + // } else { + // // 从 checkedKeys 中移除 + // checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id)); + + // // 处理每个 customerCode + // changeCustomerCodes.forEach((code) => { + // const index = selectedCustomCodes.value.findIndex( + // ([customerCode]) => customerCode === code, + // ); + // if (index !== -1) { + // if (selectedCustomCodes.value[index][1] > 1) { + // // 如果计数大于 1,减少计数 + // selectedCustomCodes.value[index][1] -= 1; + // } else { + // // 如果计数为 1,移除该项 + // selectedCustomCodes.value.splice(index, 1); + // } + // } + // }); + // } + // console.log(selectedCustomCodes.value, 56561); + // console.log(checkedKeys.value, 56562); + // } + + type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count] + type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count] + + const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref + const selectedProductionDepartment = ref<ProductionDepartmentEntry[]>([]); // 创建一个二维数组的 ref + // const checkedKeys = ref<string[]>([]); // 选中的键值列表 + + // 单选函数 + async function onSelect(record, selected: boolean) { + const res = await checkDetail({ checkNo: record.checkNo }); + + const customerCode = res[0].customerCode; + const productionDepartment = res[0].productionDepartment; + + const customerCodeIndex = selectedCustomCodes.value.findIndex( + ([code]) => code === customerCode, + ); + + const productionDepartmentIndex = selectedProductionDepartment.value.findIndex( + ([department]) => department === productionDepartment, + ); + + if (selected) { + checkedKeys.value = [...checkedKeys.value, record.id]; + + // 更新 selectedCustomCodes + if (customerCodeIndex !== -1) { + selectedCustomCodes.value[customerCodeIndex][1] += 1; + } else { + selectedCustomCodes.value.push([customerCode, 1]); + } + + // 更新 selectedProductionDepartment + if (productionDepartmentIndex !== -1) { + selectedProductionDepartment.value[productionDepartmentIndex][1] += 1; + } else { + selectedProductionDepartment.value.push([productionDepartment, 1]); + } + } else { + checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id); + + // 更新 selectedCustomCodes + if (customerCodeIndex !== -1) { + if (selectedCustomCodes.value[customerCodeIndex][1] > 1) { + selectedCustomCodes.value[customerCodeIndex][1] -= 1; + } else { + selectedCustomCodes.value.splice(customerCodeIndex, 1); + } + } + + // 更新 selectedProductionDepartment + if (productionDepartmentIndex !== -1) { + if (selectedProductionDepartment.value[productionDepartmentIndex][1] > 1) { + selectedProductionDepartment.value[productionDepartmentIndex][1] -= 1; + } else { + selectedProductionDepartment.value.splice(productionDepartmentIndex, 1); + } + } + } + console.log(checkedKeys.value, 565666666); // 输出当前的 selectedCustomCodes 值 + console.log(selectedCustomCodes.value, 565666666); // 输出当前的 selectedCustomCodes 值 + console.log(selectedProductionDepartment.value, 565666666); // 输出当前的 selectedCustomCodes 值 + } + + // 全选函数 + async function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) { + const changeIds = changeRows.map((item) => item.id); + const changeCustomerCodes = await Promise.all( + changeRows.map(async (item) => { + const res = await checkDetail({ checkNo: item.checkNo }); + return res[0].customerCode; + }), + ); + + const changeProductionDepartments = await Promise.all( + changeRows.map(async (item) => { + const res = await checkDetail({ checkNo: item.checkNo }); + return res[0].productionDepartment; + }), + ); + + if (selected) { + checkedKeys.value = [...checkedKeys.value, ...changeIds]; + + // 更新 selectedCustomCodes + changeCustomerCodes.forEach((code) => { + const index = selectedCustomCodes.value.findIndex( + ([customerCode]) => customerCode === code, + ); + if (index !== -1) { + selectedCustomCodes.value[index][1] += 1; + } else { + selectedCustomCodes.value.push([code, 1]); + } + }); + + // 更新 selectedProductionDepartment + changeProductionDepartments.forEach((department) => { + const index = selectedProductionDepartment.value.findIndex( + ([prodDepartment]) => prodDepartment === department, + ); + if (index !== -1) { + selectedProductionDepartment.value[index][1] += 1; + } else { + selectedProductionDepartment.value.push([department, 1]); + } + }); + } else { + checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id)); + + // 更新 selectedCustomCodes + changeCustomerCodes.forEach((code) => { + const index = selectedCustomCodes.value.findIndex( + ([customerCode]) => customerCode === code, + ); + if (index !== -1) { + if (selectedCustomCodes.value[index][1] > 1) { + selectedCustomCodes.value[index][1] -= 1; + } else { + selectedCustomCodes.value.splice(index, 1); + } + } + }); + + // 更新 selectedProductionDepartment + changeProductionDepartments.forEach((department) => { + const index = selectedProductionDepartment.value.findIndex( + ([prodDepartment]) => prodDepartment === department, + ); + if (index !== -1) { + if (selectedProductionDepartment.value[index][1] > 1) { + selectedProductionDepartment.value[index][1] -= 1; + } else { + selectedProductionDepartment.value.splice(index, 1); + } + } + }); + } + + console.log(checkedKeys.value, 565666666); // 输出当前的 selectedCustomCodes 值 + console.log(selectedCustomCodes.value, 565666666); // 输出当前的 selectedCustomCodes 值 + console.log(selectedProductionDepartment.value, 565666666); // 输出当前的 selectedCustomCodes 值 + } + function handleFinanceEdit(record) { - console.log('点击了编辑', record); openFinanceEdit(true, { data: record, }); } function handleTrackEdit(record) { - console.log('点击了编辑', record); openTrackEdit(true, { data: record, }); } function handleInvoiceUpload(record) { - console.log('点击了编辑', record); openInvoiceUpload(true, { data: record, }); } function handleDelete(record) { - console.log('点击了编辑', record); - openTrackEdit(true, { + const id: string[] = Array.isArray(record.id) ? record.id : [record.id]; + checkDelete({ ids: id }); + setTimeout(() => { + reload(); + }, 50); + } + function handleDetail(record) { + openCheckDetail(true, { data: record, }); } + function handleCommit(record) { + checkCommit({ id: record.id }); + setTimeout(() => { + reload(); + }, 50); + } + + const { createMessage } = useMessage(); + const { error } = createMessage; + function handleCheckSum(record) { + if (checkedKeys.value.length == 0) { + error('请选择订单'); + return; + } + if (selectedProductionDepartment.value.length > 1) { + error('勾选订单的生产科需一致'); + return; + } + openCheckSum(true, { + data: checkedKeys.value, + }); + } + function handleSuccess() { + setTimeout(() => { + reload(); + }, 150); + } </script> diff --git a/src/views/project/finance/pay/pay.data.tsx b/src/views/project/finance/pay/pay.data.tsx index 1c50f6a..e768525 100644 --- a/src/views/project/finance/pay/pay.data.tsx +++ b/src/views/project/finance/pay/pay.data.tsx @@ -1,89 +1,137 @@ import { FormSchema } from '/@/components/Form'; import { BasicColumn } from '/@/components/Table'; import { icon } from 'ant-design-vue'; -import { FolderAddOutlined } from '@ant-design/icons-vue'; +import { FolderAddOutlined, FilePptOutlined } from '@ant-design/icons-vue'; import { size } from 'lodash-es'; export const searchFormSchema: FormSchema[] = [ { - field: 'phone', + field: 'checkNo', label: '生产科对账单号', component: 'Input', colProps: { span: 8 }, }, { - field: 'nickName', - label: '总经理审核', + field: 'productionDepartment', + label: '生产科', component: 'Input', colProps: { span: 8 }, }, + { + field: 'status', + label: '总经理审核', + component: 'Select', + colProps: { span: 8 }, + componentProps: { + options: [ + { label: '未提交审核', value: -1 }, + { label: '待审核', value: 0 }, + { label: '审核通过', value: 1 }, + { label: '审核驳回', value: 2 }, + ], + }, + }, + { + field: 'customerCode', + label: '客户编码', + component: 'Input', + colProps: { + span: 8, + }, + }, ]; export const columns: BasicColumn[] = [ { title: '生产科对账单号', - dataIndex: 'no', + dataIndex: 'checkNo', width: 120, - customRender: (column) => { - return '5667'; - }, }, { title: '生产科应付款日期', - dataIndex: 'no', + dataIndex: 'payedDate', width: 140, }, { title: '生产科扣款金额', - dataIndex: 'no', + dataIndex: 'deductAmount', width: 120, }, { title: '扣款责任部门', - dataIndex: 'no', + dataIndex: 'deductDept', width: 120, }, { title: '上传扣款单', - dataIndex: 'no', + dataIndex: 'deductUrl', width: 120, + customRender: (column) => { + const deductUrl = column.record.deductUrl; + if (deductUrl == undefined) { + return; + } + return <FilePptOutlined style="font-size:25px" onClick={() => window.open(deductUrl)} />; + }, }, { title: '生产科实际应付金额', - dataIndex: 'no', + dataIndex: 'actualPayedAmount', width: 120, }, { title: '生产科发票上传', - dataIndex: 'no', + dataIndex: 'invoiceUrl', width: 80, customRender: (column) => { - return <FolderAddOutlined style="font-size:25px" />; + const deductUrl = column.record.invoiceUrl; + if (deductUrl == undefined) { + return; + } + return <FilePptOutlined style="font-size:25px" onClick={() => window.open(deductUrl)} />; }, }, { title: '实际付款金额1', - dataIndex: 'no', + dataIndex: 'actualPayedAmount1', width: 120, }, { title: '实际付款金额2', - dataIndex: 'no', + dataIndex: 'actualPayedAmount2', width: 120, }, { title: '实际付款金额3', - dataIndex: 'no', + dataIndex: 'actualPayedAmount3', width: 120, }, { title: '生产科发票', - dataIndex: 'no', + dataIndex: 'invoiceUrl', width: 120, + customRender: (column) => { + const deductUrl = column.record.invoiceUrl; + if (deductUrl == undefined) { + return; + } + return <FilePptOutlined style="font-size:25px" onClick={() => window.open(deductUrl)} />; + }, }, { title: '总经理审核', - dataIndex: 'no', + dataIndex: 'status', width: 120, + customRender: (column) => { + if (column.record.status == -1) { + return '未提交审核'; + } else if (column.record.status == 0) { + return '待审核'; + } else if (column.record.status == 1) { + return '审核通过'; + } else if (column.record.status == 2) { + return '审核驳回'; + } + }, }, ]; diff --git a/src/views/project/finance/receive/FinanceEdit.vue b/src/views/project/finance/receive/FinanceEdit.vue index b901b16..3202b41 100644 --- a/src/views/project/finance/receive/FinanceEdit.vue +++ b/src/views/project/finance/receive/FinanceEdit.vue @@ -30,10 +30,11 @@ import { getEmailList } from '/@/api/sys/config'; import { updateAmount } from '@/api/project/invoice'; + const emit = defineEmits(['success']); const schemas: FormSchema[] = [ { field: 'actualReceivableAmount', - component: 'Input', + component: 'InputNumber', labelWidth: 250, colProps: { span: 23, @@ -42,7 +43,7 @@ }, { field: 'actualPayedAmount1', - component: 'Input', + component: 'InputNumber', labelWidth: 250, colProps: { span: 23, @@ -51,7 +52,7 @@ }, { field: 'actualPayedAmount2', - component: 'Input', + component: 'InputNumber', labelWidth: 250, colProps: { span: 23, @@ -60,7 +61,7 @@ }, { field: 'actualPayedAmount3', - component: 'Input', + component: 'InputNumber', labelWidth: 250, colProps: { span: 23, @@ -69,7 +70,7 @@ }, { field: 'otherAmount', - component: 'Input', + component: 'InputNumber', labelWidth: 250, colProps: { span: 23, @@ -108,5 +109,7 @@ await updateAmount({ ...updatedValues, }); + emit('success'); + closeDrawer(); } </script> diff --git a/src/views/project/finance/receive/InvoiceAnalysis.vue b/src/views/project/finance/receive/InvoiceAnalysis.vue index 3a1387d..970a09e 100644 --- a/src/views/project/finance/receive/InvoiceAnalysis.vue +++ b/src/views/project/finance/receive/InvoiceAnalysis.vue @@ -3,51 +3,137 @@ v-bind="$attrs" @register="register" title="收款单分析" - width="700px" - :bodyStyle="{ height: '400px' }" + width="80%" + :isDetail="true" + :showDetailBack="false" @ok="handleOk" + @visible-change="handleShow" > - <a-space direction="vertical"> - <div style="margin: 16px 0"></div> - <div class="divAll"> - <div - style=" - margin-left: 22px; - margin-right: 5px; - width: 100px; - text-align: center; - line-height: 30px; - " - >生产科对账单号</div - ><a-input v-model:value="Input1" placeholder="请输入" style="width: 320px" /> - </div> - <div class="divAll"> - <div - style=" - margin-left: 0px; - margin-right: 1px; - width: 180px; - text-align: center; - line-height: 30px; - " - >生产科应付款日期</div - ><a-input v-model:value="Input2" disabled /> - </div> </a-space - ></BasicModal> + <div class="p-4"> + <BasicTable @register="registerTable"> + <template #bodyCell="{ column, record }"> + <template v-if="column.key === 'action'"> </template> + </template> + </BasicTable> + </div> + </BasicModal> </template> <script lang="ts" setup> import { BasicModal, useModalInner } from '@/components/Modal'; import { computed, ref } from 'vue'; - import { getRefundDate } from '@/api/project/invoice'; + import { invoiceAnalysis, exportAnalysis } from '@/api/project/invoice'; + import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table'; + // 处理弹窗的确定按钮点击事件 + import axios from 'axios'; - const Input1 = ref(''); - const Input2 = ref(); + const columnsAnalysis: BasicColumn[] = [ + { + title: '客户编码', + dataIndex: 'actualPayedAmount', + width: 50, + customRender: (res) => { + // console.log(res, 56562); + return res.record.exportVOS[0].customerCode; + }, + }, + { + title: '实际应付金额总计', + dataIndex: 'actualPayedAmount', + width: 50, + }, + { + title: '实际应收金额总计', + dataIndex: 'actualReceivableAmount', + width: 50, + }, + { + title: '客户总价', + dataIndex: 'customerTotalPrice', + width: 50, + }, + { + title: '发生扣款金额总计', + dataIndex: 'deductAmount', + width: 50, + }, + { + title: '实际应收', + dataIndex: 'otherAmount', + width: 50, + }, + { + title: '其他费用金额汇总', + dataIndex: 'otherTotalAmount', + width: 50, + }, + ]; + // const ids = ref<number[]>([]); + const ids = ref(); + // const res = ref(); const [register, { closeModal }] = useModalInner(async (data) => { - Input2.value = getRefundDate(data.data); - console.log(Input2.value, 5656); + ids.value = data.data; + setTimeout(() => { + reload(); + }, 50); }); + const [registerTable, { reload }] = useTable({ + // api: () => invoiceAnalysis({ ids: ids.value }), + api: async () => { + const res = await invoiceAnalysis({ ids: ids.value }); + const arrayRes = ref([]); + arrayRes.value.push(res); + console.log(res, 56561); + return arrayRes.value; + }, + columns: columnsAnalysis, + bordered: true, + }); + function handleShow(visible: boolean) { + reload(); + } + const searchData = ref({}); async function handleOk() { + // 构造符合 API 要求的参数 + const idss = ids.value; + // await exportAnalysis({ ids: ids }); + axios + .post( + '/basic-api/order/erp/invoice_bill/export', + { ids: idss }, + { + responseType: 'blob', // 设置响应类型为 'blob' + }, + ) + .then((response) => { + // 创建一个 Blob 对象来保存二进制数据 + const blob = new Blob([response.data], { type: 'application/zip' }); + const getFormattedDate = (): string => { + const date = new Date(); + + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const seconds = String(date.getSeconds()).padStart(2, '0'); + + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; + }; + const date = getFormattedDate(); + // 创建一个链接元素用于下载 + const link = document.createElement('a'); + link.href = window.URL.createObjectURL(blob); + link.download = `收款单分析${date}.xlsx`; // 你可以为文件命名 + document.body.appendChild(link); + link.click(); // 自动点击链接,触发下载 + console.log(link, 5656); + document.body.removeChild(link); // 下载完成后移除链接 + }) + .catch((error) => { + console.error(error); + }); closeModal(); } </script> diff --git a/src/views/project/finance/receive/InvoiceDetail.vue b/src/views/project/finance/receive/InvoiceDetail.vue index 33c71b6..aeed728 100644 --- a/src/views/project/finance/receive/InvoiceDetail.vue +++ b/src/views/project/finance/receive/InvoiceDetail.vue @@ -13,6 +13,9 @@ <BasicTable @register="registerTable"> <template #bodyCell="{ column, record }"> <template v-if="column.key === 'action'"> </template> + <template v-if="column.key === 'picUrl'"> + <img :z-index="100000" :width="50" :height="50" :src="record?.smallPicUrl" /> + </template> </template> </BasicTable> </div> @@ -31,22 +34,52 @@ { title: '客户编码', dataIndex: 'customerCode', - width: 50, + width: 100, }, { title: '项目号', dataIndex: 'projectNo', - width: 60, + width: 100, }, { title: '内部编码', dataIndex: 'innerNo', - width: 60, + width: 100, }, { title: '客户po号', dataIndex: 'customerPo', - width: 60, + width: 100, + }, + { + title: '客户STYLE', + width: 150, + dataIndex: 'customerStyle', + }, + { + title: 'Model(REFERENCE)', + width: 150, + dataIndex: 'modeleLo', + }, + { + title: '订单图片', + width: 150, + dataIndex: 'picUrl', + }, + { + title: '数量', + width: 150, + dataIndex: 'orderCount', + }, + { + title: '客户单价$', + width: 150, + dataIndex: 'orderCount', + }, + { + title: '客户总价$', + width: 150, + dataIndex: 'orderCount', }, ]; const invoiceNo = ref(); @@ -59,7 +92,10 @@ invoiceNo: invoiceNo.value, }); const [registerTable] = useTable({ - api: () => getBaseInvoice({ invoiceNo: invoiceNo.value }), + api: () => { + const res = getBaseInvoice({ invoiceNo: invoiceNo.value }); + return res; + }, columns: columns, bordered: true, }); diff --git a/src/views/project/finance/receive/TrackEdit.vue b/src/views/project/finance/receive/TrackEdit.vue index e77bac6..ebc3630 100644 --- a/src/views/project/finance/receive/TrackEdit.vue +++ b/src/views/project/finance/receive/TrackEdit.vue @@ -26,10 +26,7 @@ :action="updateDeductUrl" @change="handleChange" > - <a-button> - <!-- <upload-outlined></upload-outlined> --> - 上传扣款单 - </a-button> + <a-button> 上传扣款单 </a-button> </a-upload> </a-space> </div> @@ -48,16 +45,17 @@ import type { UploadProps } from 'ant-design-vue'; import { updateDeduct } from '@/api/project/invoice'; + const emit = defineEmits(['success']); const fileList = ref<UploadProps['fileList']>([]); - const input1 = ref(''); + const input1 = ref(); const deductUrl = ref(); const id = ref(); const invoiceNo = ref(); + const uploadUrl = ref('http://47.104.8.35:18000/api/localStorage/upload_file_oss?name='); const updateDeductUrl = ref('http://47.104.8.35:18000/api/localStorage/upload_file_oss?name='); const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { - console.log(data, 56561); id.value = data.data.id; invoiceNo.value = data.data.invoiceNo; input1.value = data.data.deductAmount; @@ -66,21 +64,31 @@ function handleChange(info) { if (info.file.status == 'done') { - updateDeductUrl.value = info.file.response.data.deductUrl; + updateDeductUrl.value = info.file.response.data.fileUrl; deductUrl.value = updateDeductUrl.value; } } function beforeUpload(info) { - updateDeductUrl.value += info.name; + updateDeductUrl.value = uploadUrl.value + info.name; } //完成编辑 async function handleSubmit() { + const requestData = { + id: id.value, + invoiceNo: invoiceNo.value, + deductAmount: input1.value, + deductUrl: deductUrl.value, + }; await updateDeduct({ id: id.value, invoiceNo: invoiceNo.value, deductAmount: input1.value, deductUrl: deductUrl.value, }); + // await updateDeduct(requestData); + fileList.value = []; + emit('success'); + closeDrawer(); } </script> diff --git a/src/views/project/finance/receive/index.vue b/src/views/project/finance/receive/index.vue index 23ce78a..88d4904 100644 --- a/src/views/project/finance/receive/index.vue +++ b/src/views/project/finance/receive/index.vue @@ -3,9 +3,9 @@ <BasicTable @register="registerTable"> <template #toolbar> <a-button type="primary" @click="handleInvoiceAnalysis">收款单分析</a-button> - <FinanceEdit @register="registerFinanceEdit" /> + <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> <InvoiceAnalysis @register="registerInvoiceAnalysis" /> - <TrackEdit @register="registerTrackEdit" /> + <TrackEdit @register="registerTrackEdit" @success="handleSuccess" /> <InvoiceDetail @register="registerInvoiceDetail" /> </template> <template #bodyCell="{ column, record }"> @@ -42,7 +42,7 @@ </div> </template> <script lang="ts" setup> - import { defineComponent } from 'vue'; + import { computed, defineComponent, ref } from 'vue'; import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table'; import { searchFormSchema, columns } from './receive.data'; import FinanceEdit from './FinanceEdit.vue'; @@ -50,25 +50,37 @@ import InvoiceAnalysis from './InvoiceAnalysis.vue'; import InvoiceDetail from './InvoiceDetail.vue'; import { useDrawer } from '/@/components/Drawer'; - import { getInvoice, deleteInvoice, commit } from '@/api/project/invoice'; + import { getInvoice, deleteInvoice, commit, getBaseInvoice } from '@/api/project/invoice'; import { useModal } from '/@/components/Modal'; import { FilePptOutlined } from '@ant-design/icons-vue'; import { icon } from 'ant-design-vue'; + import { ROLE } from './type.d'; + import { useUserStoreWithOut } from '/@/store/modules/user'; + import { useMessage } from '/@/hooks/web/useMessage'; const [registerInvoiceAnalysis, { openModal: openInvoiceAnalysis }] = useModal(); const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); const [registerTrackEdit, { openDrawer: openTrackEdit }] = useDrawer(); const [registerInvoiceDetail, { openDrawer: openInvoiceDetail }] = useDrawer(); - - const [registerTable] = useTable({ + const checkedKeys = ref<Array<string | number>>([]); + const userStore = useUserStoreWithOut(); + const user = userStore.getUserInfo; + const role = computed(() => { + return user?.roleSmallVO?.code; + }); + const [registerTable, { reload }] = useTable({ title: '', api: getInvoice, columns: columns, bordered: true, + clickToRowSelect: false, rowKey: 'id', rowSelection: { type: 'checkbox', + selectedRowKeys: checkedKeys, + onSelect, + onSelectAll, }, formConfig: { labelWidth: 120, @@ -88,6 +100,98 @@ // slots: { customRender: 'action' }, }, }); + + type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count] + + const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref + + // 选择函数 + async function onSelect(record: any, selected: boolean) { + if (selected) { + const res = await getBaseInvoice({ invoiceNo: record.invoiceNo }); + const customerCode = res[0].customerCode; + + const index = selectedCustomCodes.value.findIndex(([code]) => code === customerCode); + + if (index !== -1) { + // 如果存在,增加计数 + selectedCustomCodes.value[index][1] += 1; + } else { + // 如果不存在,添加新项 [customerCode, 1] + selectedCustomCodes.value.push([customerCode, 1]); + } + + checkedKeys.value = [...checkedKeys.value, record.id]; + } else { + const res = await getBaseInvoice({ invoiceNo: record.invoiceNo }); + const customerCode = res[0].customerCode; + + const index = selectedCustomCodes.value.findIndex(([code]) => code === customerCode); + + if (index !== -1) { + if (selectedCustomCodes.value[index][1] > 1) { + // 如果计数大于 1,减少计数 + selectedCustomCodes.value[index][1] -= 1; + } else { + // 如果计数为 1,移除该项 + selectedCustomCodes.value.splice(index, 1); + } + } + + checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id); + } + console.log(selectedCustomCodes.value, 56561); + console.log(checkedKeys.value, 56562); + } + + async function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) { + const changeIds = changeRows.map((item) => item.id); + const changeCustomerCodes = await Promise.all( + changeRows.map(async (item) => { + const res = await getBaseInvoice({ invoiceNo: item.invoiceNo }); + return res[0].customerCode; + }), + ); + + if (selected) { + // 添加到 checkedKeys + checkedKeys.value = [...checkedKeys.value, ...changeIds]; + + // 处理每个 customerCode + changeCustomerCodes.forEach((code) => { + const index = selectedCustomCodes.value.findIndex( + ([customerCode]) => customerCode === code, + ); + if (index !== -1) { + // 如果存在,增加计数 + selectedCustomCodes.value[index][1] += 1; + } else { + // 如果不存在,添加新项 [customerCode, 1] + selectedCustomCodes.value.push([code, 1]); + } + }); + } else { + // 从 checkedKeys 中移除 + checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id)); + + // 处理每个 customerCode + changeCustomerCodes.forEach((code) => { + const index = selectedCustomCodes.value.findIndex( + ([customerCode]) => customerCode === code, + ); + if (index !== -1) { + if (selectedCustomCodes.value[index][1] > 1) { + // 如果计数大于 1,减少计数 + selectedCustomCodes.value[index][1] -= 1; + } else { + // 如果计数为 1,移除该项 + selectedCustomCodes.value.splice(index, 1); + } + } + }); + } + } + function handleFinanceEdit(record) { openFinanceEdit(true, { data: record, @@ -101,18 +205,40 @@ function handleDelete(record) { const id: string[] = Array.isArray(record.id) ? record.id : [record.id]; deleteInvoice({ ids: id }); + setTimeout(() => { + reload(); + }, 50); } function handleCommit(record) { commit({ id: record.id }); + setTimeout(() => { + reload(); + }, 50); } function handleInvoiceDetail(record) { openInvoiceDetail(true, { data: record, }); } + const { createMessage } = useMessage(); + const { error } = createMessage; function handleInvoiceAnalysis(record) { + if (checkedKeys.value.length == 0) { + error('请选择订单'); + return; + } + if (selectedCustomCodes.value.length > 1) { + error('勾选订单的客户编码需一致'); + return; + } openInvoiceAnalysis(true, { - data: record, + data: checkedKeys.value, }); } + + function handleSuccess() { + setTimeout(() => { + reload(); + }, 50); + } </script> diff --git a/src/views/project/finance/receive/receive.data.tsx b/src/views/project/finance/receive/receive.data.tsx index 06b71ce..4948b58 100644 --- a/src/views/project/finance/receive/receive.data.tsx +++ b/src/views/project/finance/receive/receive.data.tsx @@ -7,16 +7,33 @@ import { ref } from 'vue'; export const searchFormSchema: FormSchema[] = [ { - field: 'invoice', + field: 'invoiceNo', label: 'Invoice编号', - component: 'Select', - colProps: { span: 8 }, + component: 'Input', + colProps: { span: 6 }, }, { - field: 'nickName', + field: 'status', label: '总经理审核', + component: 'Select', + colProps: { span: 6 }, + componentProps: { + options: [ + { label: '未提交审核', value: -1 }, + { label: '待审核', value: 0 }, + { label: '审核通过', value: 1 }, + { label: '审核驳回', value: 2 }, + ], + }, + }, + { + field: 'customerCode', + label: '客户编码', component: 'Input', - colProps: { span: 8 }, + colProps: { + span: 6, + }, + // labelWidth: 140, }, ]; @@ -51,6 +68,9 @@ export const columns: BasicColumn[] = [ width: 80, customRender: (column) => { const deductUrl = column.record.deductUrl; + if (deductUrl == undefined) { + return; + } return <FilePptOutlined style="font-size:25px" onClick={() => window.open(deductUrl)} />; }, }, @@ -96,3 +116,45 @@ export const columns: BasicColumn[] = [ }, }, ]; + +export const columnsAnalysis: BasicColumn[] = [ + { + title: '实际应付金额总计', + dataIndex: 'actualPayedAmount', + width: 50, + // customRender: (column) => { + // console.log(column, 5656666); + // return 1; + // }, + }, + { + title: '实际应收金额总计', + dataIndex: 'actualReceivableAmount', + width: 50, + }, + { + title: '客户总价', + dataIndex: 'customerTotalPrice', + width: 50, + }, + { + title: '发生扣款金额总计', + dataIndex: 'deductAmount', + width: 50, + }, + { + title: '实际应收金额总计', + dataIndex: 'actualReceivableAmount', + width: 50, + }, + { + title: '实际应收', + dataIndex: 'otherAmount', + width: 50, + }, + { + title: '其他费用金额汇总', + dataIndex: 'otherTotalAmount', + width: 50, + }, +]; diff --git a/src/views/project/finance/receive/type.d.ts b/src/views/project/finance/receive/type.d.ts new file mode 100644 index 0000000..83a35d3 --- /dev/null +++ b/src/views/project/finance/receive/type.d.ts @@ -0,0 +1,9 @@ +export enum ROLE { + ADMIN = 'admin', // 超管 + CUSTOM_ADMIN = 'custom_admin', // 客户管理员 + DATA_REPORT_USER = 'data_report_user', //数据分析员 + BUSINESS = 'business_user', // 业务员 + TRACKER = 'tracker_user', // 跟单员 + INSPECT = 'inspect_user', // 质检员 + PRODUCE = 'produce_user', //生产科 +} diff --git a/src/views/project/order/ExportModal.vue b/src/views/project/order/ExportModal.vue index 4a6d44d..828a3d1 100644 --- a/src/views/project/order/ExportModal.vue +++ b/src/views/project/order/ExportModal.vue @@ -162,7 +162,6 @@ //导出选中的订单 fieldVO.orderIds = props.ids; exportLoading.value = true; - console.log(fieldVO, 5656); await orderExport({ ...searchData.value, fieldVO }); exportLoading.value = false; diff --git a/src/views/project/order/FormDetail/index.vue b/src/views/project/order/FormDetail/index.vue index 023a91e..a0d6d6d 100644 --- a/src/views/project/order/FormDetail/index.vue +++ b/src/views/project/order/FormDetail/index.vue @@ -324,10 +324,10 @@ trackFormPanelRef?.value?.setFieldsValue({ ...toRaw(data.trackStageInfo), }); - ppUpdate.value = data.trackStageInfo.ppConfirmResult; - shipUpdate.value = data.trackStageInfo.shippmentSampleConfirmTime; - altexUpdate.value = data.trackStageInfo.aitexTestFinishTime; - sgsUpdate.value = data.trackStageInfo.sgsTestFinishTime; + ppUpdate.value = data?.trackStageInfo?.ppConfirmResult; + shipUpdate.value = data?.trackStageInfo?.shippmentSampleConfirmTime; + altexUpdate.value = data?.trackStageInfo?.aitexTestFinishTime; + sgsUpdate.value = data?.trackStageInfo?.sgsTestFinishTime; } if (inspectionFormPanelRef.value) { @@ -408,19 +408,30 @@ forms.inspectionStageInfo = inspectionFormPanelRef?.value?.getFieldsValue() || {}; } //跟单信息标记 - if (forms.trackStageInfo.ppConfirmResult !== ppUpdate.value) { + if ( + forms.trackStageInfo?.ppConfirmResult !== undefined && + forms.trackStageInfo?.ppConfirmResult !== ppUpdate.value + ) { forms.trackStageInfo.ppConfirmTime = getFormattedDate(); } - if (forms.trackStageInfo.shippmentSampleConfirmResult !== shipUpdate.value) { + if ( + forms.trackStageInfo?.shippmentSampleConfirmResult !== undefined && + forms.trackStageInfo?.shippmentSampleConfirmResult !== shipUpdate.value + ) { forms.trackStageInfo.shippmentSampleConfirmTime = getFormattedDate(); } - if (forms.trackStageInfo.aitexTestFinishResult !== altexUpdate.value) { + if ( + forms.trackStageInfo?.aitexTestFinishResult !== altexUpdate.value && + forms.trackStageInfo?.aitexTestFinishResult !== undefined + ) { forms.trackStageInfo.aitexTestFinishTime = getFormattedDate(); } - if (forms.trackStageInfo.sgsTestFinishResult !== sgsUpdate.value) { + if ( + forms.trackStageInfo?.sgsTestFinishResult !== sgsUpdate.value && + forms.trackStageInfo?.sgsTestFinishResult !== undefined + ) { forms.trackStageInfo.sgsTestFinishTime = getFormattedDate(); } - // console.log(forms.trackStageInfo, 5656); await orderUpdate(forms); closeDrawer(); emit('success', {}); @@ -440,6 +451,9 @@ }; await orderCreate(forms); closeDrawer(); + setTimeout(() => { + reload(); + }, 50); emit('success', {}); } } catch (error) { diff --git a/src/views/project/order/InvoiceCreate.vue b/src/views/project/order/InvoiceCreate.vue index 91b15b0..4fe9d99 100644 --- a/src/views/project/order/InvoiceCreate.vue +++ b/src/views/project/order/InvoiceCreate.vue @@ -32,7 +32,7 @@ import { BasicModal, useModalInner } from '@/components/Modal'; import { computed, ref } from 'vue'; import type { UploadProps } from 'ant-design-vue'; - import { getRefundDate, getInvoice } from '@/api/project/invoice'; + import { getRefundDate, getInvoice, createInvoice } from '@/api/project/invoice'; const fileList = ref<UploadProps['fileList']>([]); @@ -43,13 +43,14 @@ const orderIds = ref(); const [register, { closeModal }] = useModalInner(async (data) => { - const res = getRefundDate(data.data); - Input2.value = res.data; + const ids = data.data; + const res = await getRefundDate({ orderIds: ids }); + Input2.value = res; orderIds.value = data.data; }); // const title = ref(''); async function handleOk() { - await getInvoice({ + await createInvoice({ invoiceNo: Input1.value, bgUrl: bgUrl.value, backRefundDate: Input2.value, @@ -59,7 +60,7 @@ } function handleChange(info) { if (info.file.status == 'done') { - bgUrl.value = info.file.response.data; + bgUrl.value = info.file.response.data.fileUrl; } } function beforeUpload(info) { diff --git a/src/views/project/order/PassCalculate.vue b/src/views/project/order/PassCalculate.vue index b8d14f9..629054a 100644 --- a/src/views/project/order/PassCalculate.vue +++ b/src/views/project/order/PassCalculate.vue @@ -7,37 +7,32 @@ :bodyStyle="{ height: '100px' }" @ok="handleOk" > - <div style="margin-left: 10px; font-size: 16px">一次通过率:{{ result }}</div> + <div style="margin-left: 10px; font-size: 16px">一次通过率:{{ num }}</div> </BasicModal> </template> <script lang="ts" setup> import { BasicModal, useModalInner } from '@/components/Modal'; import { computed, ref } from 'vue'; + import { passCalculate } from '@/api/project/order'; const [register, { closeModal }] = useModalInner(async (data) => { - console.log(data, 56562); title.value = data.title; + const id = data.check[0]; + const opinionType = ref(); + if (data.title == '确认意见') { + opinionType.value = 'pp样品确认意见'; + } else if (data.title == '生产样品') { + opinionType.value = 'shipment sample确认意见'; + } else if (data.title == '测试样品') { + opinionType.value = 'Altex测试结果'; + } + num.value = await passCalculate({ orderId: id, opinionType: opinionType.value }); }); const title = ref(''); - const result = computed(() => { - const res = 1234; - return res; - }); - // onMounted(async () => { - // // 获取包装费用和客户编码的关联关系 - // const res = await getConfigList({ - // page: 1, - // pageSize: 1000, - // // relationCode: 'packetPrice', - // }); - - // configList.value = res?.items || []; - - // // 获取业务员 - // const res1 = await getUserList({ page: 1, pageSize: 1000 }); - // businessUsers.value = res1.items + const num = ref(); async function handleOk() { closeModal(); + num.value = ''; } </script> diff --git a/src/views/project/order/ProductInvoice.vue b/src/views/project/order/ProductInvoice.vue index bcb8d93..51990f6 100644 --- a/src/views/project/order/ProductInvoice.vue +++ b/src/views/project/order/ProductInvoice.vue @@ -38,16 +38,22 @@ <script lang="ts" setup> import { BasicModal, useModalInner } from '@/components/Modal'; import { computed, ref } from 'vue'; - import { getRefundDate } from '@/api/project/invoice'; + import { payDate, checkCreate } from '@/api/project/invoice'; const Input1 = ref(''); const Input2 = ref(); - + const res = ref(); const [register, { closeModal }] = useModalInner(async (data) => { - Input2.value = getRefundDate(data.data); - console.log(Input2.value, 5656); + res.value = data.data; + Input2.value = await payDate({ orderIds: res.value }); + console.log(Input2.value, 565656); }); async function handleOk() { + await checkCreate({ + orderIds: res.value, + payedDate: Input2.value, + checkNo: Input1.value, + }); closeModal(); } </script> diff --git a/src/views/project/order/ProductText.vue b/src/views/project/order/ProductText.vue index c29253f..47da7bd 100644 --- a/src/views/project/order/ProductText.vue +++ b/src/views/project/order/ProductText.vue @@ -50,7 +50,7 @@ </BasicModal> </template> <script lang="ts"> - import { defineComponent, ref, computed } from 'vue'; + import { defineComponent, ref, computed, onMounted, onUpdated } from 'vue'; import { BasicModal, useModalInner } from '/@/components/Modal'; import { RadioGroup } from 'ant-design-vue'; import { EyeOutlined, FilePptOutlined } from '@ant-design/icons-vue'; @@ -74,7 +74,12 @@ const isShow1 = ref(true); //选择公司页面 const isShow2 = ref(false); //生成PDF页面 const pdf = ref(['/pdf.png']); - const [register, { setModalProps, closeModal }] = useModalInner(async (data) => {}); + const [register, { setModalProps, closeModal }] = useModalInner(async (data) => { + // if (data.customers.length == 0) { + // error('请选择订单'); + // closeModal(); + // } + }); const options = computed(() => { // 运营总监-基本信息,跟单,质检 return [ @@ -114,27 +119,29 @@ isShow2.value = false; } } - //判断选择公司与客户编码是否对应 - function validateCustomerCodes(customerCodes: string[], chooseCompany: string): boolean { - for (const code of customerCodes) { - const expectedCompanyValue = customerCodeToCompanyMap[code]; - if (expectedCompanyValue === undefined) { - // 如果代码不在映射中,不需要对应公司 + function validateCompany(selectedCodes: any, company: string): boolean { + for (const [customerCode] of selectedCodes) { + const mappedCompany = customerCodeToCompanyMap[customerCode]; + + if (mappedCompany === undefined) { + // 如果 customerCode 不在 customerCodeToCompanyMap 中,跳过 + console.warn(`Customer code ${customerCode} not found in the mapping, skipping.`); continue; } - if (customerCodeToCompanyMap[code] !== chooseCompany) { - // 如果属于 customerCodes 的值与其公司不匹配,返回 false + + if (mappedCompany !== company) { + // 如果有一个不匹配,返回 false return false; } } - return true; // 如果所有 customerCodes 内的代码正确匹配,返回 true + // 如果所有匹配,返回 true + return true; } //生成pdf // const customerCodeList: string[] = props.customerCodes; function handleProduct() { - const customerCodeList: string[] = props.customerCodes; - const areValid = validateCustomerCodes(customerCodeList, choose.value); - console.log(customerCodeList, 5656, props.customerCodes); + const customerCodeList = props.customerCodes; + const areValid = validateCompany(customerCodeList, choose.value); //如果选错了,弹出提示 if (!areValid) { error('勾选订单与选择的公司不匹配'); diff --git a/src/views/project/order/TrackHistory.vue b/src/views/project/order/TrackHistory.vue index 82788c1..a9921f7 100644 --- a/src/views/project/order/TrackHistory.vue +++ b/src/views/project/order/TrackHistory.vue @@ -21,10 +21,10 @@ </template> <template #description> <div class="description"> - {{ item.modifyTime }} + {{ item.showOpinionType }} </div> <div class="info"> - <!-- <div><span>操作时间:</span>{{ formatToDateTime(item.createTime) }}</div> --> + <div>操作时间:{{ item.modifyTime }}</div> </div> </template> </a-list-item-meta> @@ -54,20 +54,43 @@ const orderId = ref(''); // const activeKey = ref(1); + function removeTFromTimestamp(timestamp: string): string { + // 使用 replace 方法将 "T" 替换为空字符串 + return timestamp.replace('T', ' '); + } + const getOrderOptLogFunc = async (data, page) => { console.log('%c [ data ]-135', 'font-size:13px; background:pink; color:#bf2c9f;', data); const res = await trackHistory({ orderId: data, page: page, pageSize: 20 }); list1.value = res; - // total1.value = res.total; - // page1.value = page; + for (const item of list1.value) { + item.modifyTime = removeTFromTimestamp(item.modifyTime); + item.showOpinionType = modifyConfirmResult(item.field, item.modifyTime); + } }; const [register] = useDrawerInner((data) => { - console.log(data, 5656); orderId.value = data.id; // const res = await trackHistory({ orderId: data, page: page, pageSize: 20 }); getOrderOptLogFunc(orderId.value, 1); }); + function modifyConfirmResult(Result: string, Time: string): string { + // 获取 Time 的日期部分,去掉时间 + let datePart = Time.split(' ')[0]; // 获取日期部分 + datePart += ' '; + // 找到第一个"."的位置 + const dotIndex = Result.indexOf('.'); + // 如果找到了".",则进行拼接 + if (dotIndex !== -1) { + // 生成新的结果 + const modifiedResult = `${Result.slice(0, dotIndex + 1)}${datePart}${Result.slice( + dotIndex + 1, + )}`; + return modifiedResult; + } + // 如果没有找到".",直接返回原始字符串 + return Result; + } const pagination1 = computed(() => { return { show: true, diff --git a/src/views/project/order/index.vue b/src/views/project/order/index.vue index c9f71ad..ca2b535 100644 --- a/src/views/project/order/index.vue +++ b/src/views/project/order/index.vue @@ -31,32 +31,36 @@ <template #bodyCell="{ column, record }"> <template v-if="column.key === 'action'"> <TableAction - :actions="[ - { - // 数据分析没有编辑权限 - ...(role !== ROLE.DATA_REPORT_USER && { - label: '编辑', - // icon: 'ic:outline-delete-outline', - onClick: handleEdit.bind(null, record), - }), - }, - { - ...(role !== ROLE.DATA_REPORT_USER && { - label: '申请权限', - // icon: 'ic:outline-delete-outline', - onClick: handleCheck.bind(null, record), - }), - }, - // { - // ...(role !== ROLE.DATA_REPORT_USER && { - // label: '申请', - // // icon: 'ic:outline-delete-outline', - // onClick: handleCheck.bind(null, record), - // }), - // }, - ]" + :actions=" + role !== ROLE.PRODUCE + ? [ + { + // 数据分析没有编辑权限 + ...(role !== ROLE.DATA_REPORT_USER && { + label: '编辑', + // icon: 'ic:outline-delete-outline', + onClick: handleEdit.bind(null, record), + }), + }, + { + ...(role !== ROLE.DATA_REPORT_USER && { + label: '申请权限', + // icon: 'ic:outline-delete-outline', + onClick: handleCheck.bind(null, record), + }), + }, + // { + // ...(role !== ROLE.DATA_REPORT_USER && { + // label: '申请', + // // icon: 'ic:outline-delete-outline', + // onClick: handleCheck.bind(null, record), + // }), + // }, + ] + : [] + " :dropDownActions=" - role !== ROLE.DATA_REPORT_USER + role !== ROLE.DATA_REPORT_USER && role !== ROLE.PRODUCE ? [ { label: '历史记录', @@ -120,9 +124,10 @@ @change="handleChange" class="passCalculate" dropdown-class-name="dropdown-class" + v-if="role === ROLE.ADMIN || role === ROLE.TRACKER || role === ROLE.BUSINESS" > - <a-select-option value1="confirm">一次通过率</a-select-option> - <a-select-option value="确认样品" @click="handlePassModal('确认样品')" + <a-select-option value1="一次通过率">一次通过率</a-select-option> + <a-select-option value="确认样品" @click="handlePassModal('确认意见')" >确认样品</a-select-option > <a-select-option value="生产样品" @click="handlePassModal('生产样品')" @@ -142,7 +147,12 @@ >比重计算</a-button > <!-- 质检角色不能导出任何信息 --> - <a-button type="primary" @click="handleExportModal">导出</a-button> + <a-button + type="primary" + @click="handleExportModal" + v-if="role === ROLE.ADMIN || role === ROLE.TRACKER || role === ROLE.BUSINESS" + >导出</a-button + > <a-button type="primary" @click="handleProfitModal" @@ -208,6 +218,8 @@ import { useUserStoreWithOut } from '/@/store/modules/user'; import { ROLE } from './type.d'; import { getUserList } from '/@/api/project/account'; + import { useMessage } from '/@/hooks/web/useMessage'; + import { getBaseInvoice } from '/@/api/project/invoice'; const orderStore = useOrderStoreWithOut(); const userStore = useUserStoreWithOut(); @@ -234,7 +246,7 @@ }, setup() { const checkedKeys = ref<Array<string | number>>([]); - const selectedCustomCodes = ref<Array<string>>([]); + // const selectedCustomCodes = ref<Array<string>>([]); const [profitModalRegister, { openModal: openProfitModal }] = useModal(); const [invoiceCreateModalRegister, { openModal: openInvoiceCreateModal }] = useModal(); const [productInvoiceModalRegister, { openModal: openProductInvoiceModal }] = useModal(); @@ -279,6 +291,7 @@ pagination: { total: 60, }, + clickToRowSelect: false, columns: getOrderColumns(user?.roleSmallVO?.code), useSearchForm: true, formConfig: formConfig, @@ -292,47 +305,165 @@ onSelect, onSelectAll, }, - actionColumn: { - width: 160, - title: 'Action', - dataIndex: 'action', - // slots: { customRender: 'action' }, - }, + // actionColumn: { + // width: 160, + // title: 'Action', + // dataIndex: 'action', + // // slots: { customRender: 'action' }, + // }, + actionColumn: + role.value !== ROLE.PRODUCE + ? { + width: 160, + title: 'Action', + dataIndex: 'action', + // slots: { customRender: 'action' }, + } + : undefined, }); function getFormValues() { console.log(getForm().getFieldsValue()); } - function onSelect(record, selected) { + + type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count] + type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count] + + const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref + const selectedProductionDepartment = ref<ProductionDepartmentEntry[]>([]); // 创建一个二维数组的 ref + + // 单选处理函数 + function onSelect( + record: { customerCode: string; productionDepartment: string; id: string }, + selected: boolean, + ) { + // 查找 customerCode 在 selectedCustomCodes 中的位置 + const customerCodeIndex = selectedCustomCodes.value.findIndex( + ([customerCode]) => customerCode === record.customerCode, + ); + + // 查找 productionDepartment 在 selectedProductionDepartment 中的位置 + const productionDepartmentIndex = selectedProductionDepartment.value.findIndex( + ([department]) => department === record.productionDepartment, + ); + if (selected) { - if (!selectedCustomCodes.value.includes(record.customerCode)) { - // 如果不包含,则添加到 selectedCustomCodes - selectedCustomCodes.value = [...selectedCustomCodes.value, record.customerCode]; - } + // 添加到 checkedKeys checkedKeys.value = [...checkedKeys.value, record.id]; + + // 更新 selectedCustomCodes + if (customerCodeIndex !== -1) { + // 如果已存在,增加计数 + selectedCustomCodes.value[customerCodeIndex][1] += 1; + } else { + // 如果不存在,添加新项 [customerCode, 1] + selectedCustomCodes.value.push([record.customerCode, 1]); + } + + // 更新 selectedProductionDepartment + if (productionDepartmentIndex !== -1) { + // 如果已存在,增加计数 + selectedProductionDepartment.value[productionDepartmentIndex][1] += 1; + } else { + // 如果不存在,添加新项 [productionDepartment, 1] + selectedProductionDepartment.value.push([record.productionDepartment, 1]); + } } else { + // 从 checkedKeys 中移除 checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id); - selectedCustomCodes.value = selectedCustomCodes.value.filter( - (customerCode) => customerCode !== record.customerCode, - ); + + // 更新 selectedCustomCodes + if (customerCodeIndex !== -1) { + if (selectedCustomCodes.value[customerCodeIndex][1] > 1) { + selectedCustomCodes.value[customerCodeIndex][1] -= 1; + } else { + selectedCustomCodes.value.splice(customerCodeIndex, 1); + } + } + + // 更新 selectedProductionDepartment + if (productionDepartmentIndex !== -1) { + if (selectedProductionDepartment.value[productionDepartmentIndex][1] > 1) { + selectedProductionDepartment.value[productionDepartmentIndex][1] -= 1; + } else { + selectedProductionDepartment.value.splice(productionDepartmentIndex, 1); + } + } } + + console.log('5656Checked Keys:', checkedKeys.value); + console.log('5656Selected Customer Codes:', selectedCustomCodes.value); + console.log('5656Selected Production Departments:', selectedProductionDepartment.value); } - function onSelectAll(selected, selectedRows, changeRows) { + + // 全选处理函数 + function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) { const changeIds = changeRows.map((item) => item.id); const changeCustomerCodes = changeRows.map((item) => item.customerCode); + const changeProductionDepartments = changeRows.map((item) => item.productionDepartment); + if (selected) { + // 添加到 checkedKeys checkedKeys.value = [...checkedKeys.value, ...changeIds]; - // 创建一个集合来去除重复的代码 - const allCodes = new Set([...selectedCustomCodes.value, ...changeCustomerCodes]); - // 将集合转换回数组 - selectedCustomCodes.value = Array.from(allCodes); + + // 更新 selectedCustomCodes + changeCustomerCodes.forEach((code) => { + const index = selectedCustomCodes.value.findIndex( + ([customerCode]) => customerCode === code, + ); + if (index !== -1) { + selectedCustomCodes.value[index][1] += 1; + } else { + selectedCustomCodes.value.push([code, 1]); + } + }); + + // 更新 selectedProductionDepartment + changeProductionDepartments.forEach((department) => { + const index = selectedProductionDepartment.value.findIndex( + ([prodDepartment]) => prodDepartment === department, + ); + if (index !== -1) { + selectedProductionDepartment.value[index][1] += 1; + } else { + selectedProductionDepartment.value.push([department, 1]); + } + }); } else { - checkedKeys.value = checkedKeys.value.filter((id) => { - return !changeIds.includes(id); + // 从 checkedKeys 中移除 + checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id)); + + // 更新 selectedCustomCodes + changeCustomerCodes.forEach((code) => { + const index = selectedCustomCodes.value.findIndex( + ([customerCode]) => customerCode === code, + ); + if (index !== -1) { + if (selectedCustomCodes.value[index][1] > 1) { + selectedCustomCodes.value[index][1] -= 1; + } else { + selectedCustomCodes.value.splice(index, 1); + } + } }); - selectedCustomCodes.value = selectedCustomCodes.value.filter((customerCode) => { - return !changeCustomerCodes.includes(customerCode); + + // 更新 selectedProductionDepartment + changeProductionDepartments.forEach((department) => { + const index = selectedProductionDepartment.value.findIndex( + ([prodDepartment]) => prodDepartment === department, + ); + if (index !== -1) { + if (selectedProductionDepartment.value[index][1] > 1) { + selectedProductionDepartment.value[index][1] -= 1; + } else { + selectedProductionDepartment.value.splice(index, 1); + } + } }); } + + console.log('5656Checked Keys:', checkedKeys.value); + console.log('5656Selected Customer Codes:', selectedCustomCodes.value); + console.log('5656Selected Production Departments:', selectedProductionDepartment.value); } function handleEdit(record, e) { @@ -377,10 +508,20 @@ }); } - function handleInvoiceCreateModal() { + function handleInvoiceCreateModal(record) { const form = getForm(); const values = form.getFieldsValue(); + if (checkedKeys.value.length == 0) { + error('请选择订单'); + return; + } + if (selectedCustomCodes.value.length > 1) { + error('勾选订单的客户编码需一致'); + return; + } openInvoiceCreateModal(true, { + record: record, + customersCodes: selectedCustomCodes.value, data: checkedKeys.value, searchData: values, }); @@ -389,6 +530,14 @@ function handleProductInvoiceModal() { const form = getForm(); const values = form.getFieldsValue(); + if (checkedKeys.value.length == 0) { + error('请选择订单'); + return; + } + if (selectedProductionDepartment.value.length > 1) { + error('勾选订单的生产科需一致'); + return; + } openProductInvoiceModal(true, { data: checkedKeys.value, searchData: values, @@ -401,35 +550,46 @@ function handlePassModal(title) { const form = getForm(); const values = form.getFieldsValue(); - if (title == '确认样品') { - openPassModal(true, { - check: checkedKeys.value, - data: values, - title: title, - }); - return false; - } else if (title == '生产样品') { - openPassModal(true, { - check: checkedKeys.value, - data: values, - title: title, - }); - return false; - } else if (title == '测试样品') { - openPassModal(true, { - check: checkedKeys.value, - data: values, - title: title, - }); - return false; - } + openPassModal(true, { + check: checkedKeys.value, + title: title, + searchData: values, + }); } - + // const form = getForm(); + // const values = form.getFieldsValue(); + // if (title == '确认样品') { + // openPassModal(true, { + // check: checkedKeys.value, + // title: title, + // }); + // return false; + // } else if (title == '生产样品') { + // openPassModal(true, { + // check: checkedKeys.value, + // title: title, + // }); + // return false; + // } else if (title == '测试样品') { + // openPassModal(true, { + // check: checkedKeys.value, + // title: title, + // }); + // return false; + // } + // } + const { createMessage } = useMessage(); + const { error } = createMessage; function handleProductModal() { const form = getForm(); const values = form.getFieldsValue(); - + console.log(selectedCustomCodes.value, 5656); + if (selectedCustomCodes.value.length == 0) { + error('请选择订单'); + return; + } openProductModal(true, { + customers: selectedCustomCodes.value, data: values, }); } diff --git a/src/views/project/order/tableData.tsx b/src/views/project/order/tableData.tsx index ea8a07a..61a7c8a 100644 --- a/src/views/project/order/tableData.tsx +++ b/src/views/project/order/tableData.tsx @@ -12,6 +12,8 @@ import { formatToDate } from '/@/utils/dateUtil'; const innerNoOptions = ref([]); const projectNoOptions = ref([]); +const orderStore = useOrderStoreWithOut(); +// const { productionDepartment: productionDepartmentOptions } = useOrderInfo(orderStore); // 可选择的列 export const SELECT_FIELD_COLUMNS = [ @@ -353,6 +355,24 @@ export const ORDER_LIST_PROFIT_FIELDS = [ }, ]; +function modifyConfirmResult(ppConfirmResult: string, ppConfirmTime: string): string { + // 获取 ppConfirmTime 的日期部分,去掉时间 + let datePart = ppConfirmTime.split(' ')[0]; // 获取日期部分 + datePart += ' '; + // 找到第一个"."的位置 + const dotIndex = ppConfirmResult.indexOf('.'); + + // 如果找到了".",则进行拼接 + if (dotIndex !== -1) { + // 生成新的结果 + const modifiedResult = `${ppConfirmResult.slice(0, dotIndex + 1)}${datePart}${ppConfirmResult.slice(dotIndex + 1)}`; + return modifiedResult; + } + + // 如果没有找到".",直接返回原始字符串 + return ppConfirmResult; +} + export const ORDER_LIST_TRACK_FIELDS = [ { title: '跟单信息', @@ -370,13 +390,17 @@ export const ORDER_LIST_TRACK_FIELDS = [ }, { title: 'pp样品确认意见', - width: 150, + width: 180, dataIndex: 'ppConfirmResult', customRender: (column) => { const { record } = column || {}; - if (record?.trackStageInfo?.ppConfirmResult !== undefined) { + if ( + record?.trackStageInfo?.ppConfirmResult !== undefined && + record?.trackStageInfo?.ppConfirmTime !== undefined + ) { const ppUpdate = record?.trackStageInfo?.ppConfirmResult; - const ppUpdate2 = ppUpdate + '123'; + const ppUpdateTime = record?.trackStageInfo?.ppConfirmTime; + const ppUpdate2 = modifyConfirmResult(ppUpdate, ppUpdateTime); return ppUpdate2; } else { return record?.trackStageInfo?.ppConfirmResult; @@ -407,7 +431,17 @@ export const ORDER_LIST_TRACK_FIELDS = [ dataIndex: 'shippmentSampleConfirmResult', customRender: (column) => { const { record } = column || {}; - return record?.trackStageInfo?.shippmentSampleConfirmResult; + if ( + record?.trackStageInfo?.shippmentSampleConfirmResult !== undefined && + record?.trackStageInfo?.shippmentSampleConfirmTime !== undefined + ) { + const shipUpdate = record?.trackStageInfo?.shippmentSampleConfirmResult; + const shipUpdateTime = record?.trackStageInfo?.shippmentSampleConfirmTime; + const shipUpdate2 = modifyConfirmResult(shipUpdate, shipUpdateTime); + return shipUpdate2; + } else { + return record?.trackStageInfo?.shippmentSampleConfirmResult; + } }, }, { @@ -434,7 +468,17 @@ export const ORDER_LIST_TRACK_FIELDS = [ dataIndex: 'aitexTestFinishResult', customRender: (column) => { const { record } = column || {}; - return record?.trackStageInfo?.aitexTestFinishResult; + if ( + record?.trackStageInfo?.aitexTestFinishResult !== undefined && + record?.trackStageInfo?.aitexTestFinishTime !== undefined + ) { + const aitexUpdate = record?.trackStageInfo?.aitexTestFinishResult; + const aitexUpdateTime = record?.trackStageInfo?.aitexTestFinishTime; + const aitexUpdate2 = modifyConfirmResult(aitexUpdate, aitexUpdateTime); + return aitexUpdate2; + } else { + return record?.trackStageInfo?.aitexTestFinishResult; + } }, }, { @@ -452,7 +496,17 @@ export const ORDER_LIST_TRACK_FIELDS = [ dataIndex: 'sgsTestFinishResult', customRender: (column) => { const { record } = column || {}; - return record?.trackStageInfo?.sgsTestFinishResult; + if ( + record?.trackStageInfo?.sgsTestFinishResult !== undefined && + record?.trackStageInfo?.sgsTestFinishTime !== undefined + ) { + const sgsUpdate = record?.trackStageInfo?.sgsTestFinishResult; + const sgsUpdateTime = record?.trackStageInfo?.sgsTestFinishTime; + const sgsUpdate2 = modifyConfirmResult(sgsUpdate, sgsUpdateTime); + return sgsUpdate2; + } else { + return record?.trackStageInfo?.sgsTestFinishResult; + } }, }, { @@ -725,6 +779,9 @@ export const FIELDS_BASE_INFO = [ { field: 'productionDepartment', component: 'Select', + // componentProps: { + // options: productionDepartmentOptions, + // }, labelWidth: 150, label: '生产科', rules: [{ required: true }], @@ -1122,29 +1179,29 @@ export const FIELDS_TRACK_STAGE_INFO = [ }, { field: 'latestArrivalTime', - component: 'Select', - componentProps: { - options: [ - { - label: 'ok', - value: 'ok', - }, - ], - }, + component: 'DatePicker', + // componentProps: { + // options: [ + // { + // label: 'ok', + // value: 'ok', + // }, + // ], + // }, label: '最晚包材到货时间', labelWidth: 250, }, { field: 'latestBkTime', - component: 'Select', - componentProps: { - options: [ - { - label: 'ok', - value: 'ok', - }, - ], - }, + component: 'DatePicker', + // componentProps: { + // options: [ + // { + // label: 'ok', + // value: 'ok', + // }, + // ], + // }, label: '最晚订舱+报关资料时间', labelWidth: 250, }, diff --git a/vite.config.ts b/vite.config.ts index d6a6ad3..950069d 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -21,6 +21,7 @@ export default defineApplicationConfig({ proxy: { '/basic-api/order': { target: 'http://47.104.8.35:18000', + // target: 'http://39.108.227.113:8000', // target: 'http://localhost:8000', // target: 'http://39.108.227.113:3000/mock/35', // http://39.108.227.113:8000/order/erp/captcha/get_img_captcha_code @@ -30,6 +31,8 @@ export default defineApplicationConfig({ }, '/api/localStorage/upload': { target: 'http://47.104.8.35:18000', + // target: 'http://39.108.227.113:8000', + // target: '192.168.31.250:18000', // target: 'http://localhost:8000', changeOrigin: true, ws: true, -- libgit2 0.23.3