Commit 455e7b2972e0754c1f6df4871ce838fa559611bd

Authored by boyang
1 parent 192bbb6f

fix: 修改控制

src/api/project/invoice.ts
... ... @@ -52,10 +52,10 @@ enum Api {
52 52 AUDITAPPLY = '/project/audit', //审核
53 53 ACTIONRECORD = '/projectOptLog/listByPage', //业务/内部研发净利润操作记录以及申请记录
54 54 ORDERCOSTDETAILEDOPTLOG = '/orderCostDetailedOptLog/listByPage', //包装费用明细/内部生产明细操作记录表
55   - ORDERCOSTDETAILEDEXPORT = '/project/businessProfit/exportExcel', //业务研发净利润分析表导出
56   - INNERPRODUCEPROFITEXPORT = '/project/innerProfitInfo/exportExcel', //内部生产净利润分析表导出
57   - BUSINESSPROFITDETAIL = '/order/cost/businessProfitDetail/exportExcel', //包装费用明细导出
58   - INNERPROFITDETAIL = '/order/cost/innerProfitDetail/exportExcel', //内部生产明细导出
  55 + SETPACKSTATUS = '/order/cost/setPackStatus', //包装费用明细表审批
  56 + SETINNERSTATUS = '/order/cost/setInnerStatus', //内部生产明细表审批
  57 + PROJECTBUSINESSPROFITSETSTATUS = '/project/businessProfit/setStatus', //业务研发净利润分析表审批
  58 + PROJECTINNERPROFITSETSTATUS = '/project/innerProfitInfo/setStatus', //内部研发净利润分析表审批
59 59 }
60 60  
61 61 export const getRefundDate = async (params: any, data?: any) => {
... ... @@ -521,28 +521,29 @@ export const getOrderCostDetailedOptLog = async (params: any) => {
521 521 });
522 522 });
523 523 };
524   -export const getBusinessProfitExport = async (params: any) => {
  524 +export const setPackStatus = async (params: any) => {
525 525 return await defHttp.post<any>({
526   - url: Api.ORDERCOSTDETAILEDEXPORT,
  526 + url: Api.SETPACKSTATUS,
527 527 params,
528 528 });
529 529 };
530   -
531   -export const getInnerProfitInfoExport = async (params: any) => {
  530 +export const setInnerStatus = async (params: any) => {
532 531 return await defHttp.post<any>({
533   - url: Api.INNERPRODUCEPROFITEXPORT,
  532 + url: Api.SETINNERSTATUS,
534 533 params,
535 534 });
536 535 };
537   -export const getBusinessProfitDetailExport = async (params: any) => {
  536 +
  537 +export const setBusinessProfitSetStatus = async (params: any) => {
538 538 return await defHttp.post<any>({
539   - url: Api.BUSINESSPROFITDETAIL,
  539 + url: Api.PROJECTBUSINESSPROFITSETSTATUS,
540 540 params,
541 541 });
542 542 };
543   -export const getInnerProfitDetail = async (params: any) => {
  543 +
  544 +export const setInnerProfitSetStatus = async (params: any) => {
544 545 return await defHttp.post<any>({
545   - url: Api.INNERPROFITDETAIL,
  546 + url: Api.PROJECTINNERPROFITSETSTATUS,
546 547 params,
547 548 });
548 549 };
549 550 \ No newline at end of file
... ...
src/views/project/finance/financeProfit/ProductProfit/InnerData/data.tsx
... ... @@ -225,11 +225,11 @@ export const COLUMNS = [
225 225 dataIndex: 'status',
226 226 width: 120,
227 227 customRender: (column) => {
228   - if (column.record?.status === '-1') {
  228 + if (column.record?.innerProduceStatus === null || column.record?.innerProduceStatus === -1) {
229 229 return '未完成';
230   - } else if (column.record?.status === '0') {
  230 + } else if (column.record?.innerProduceStatus === 0) {
231 231 return '待审核';
232   - } else if (column.record?.status === '1') {
  232 + } else if (column.record?.innerProduceStatus === 1) {
233 233 return '已审核';
234 234 }
235 235 },
... ...
src/views/project/finance/financeProfit/ProductProfit/InnerData/index.vue
1 1 <template>
2 2 <div>
3 3 <BasicTable @register="registerTable" :bordered="true">
  4 + <template #headerTop>
  5 + <a-alert type="info" show-icon>
  6 + <template #message>
  7 + <template v-if="checkedKeys.length > 0">
  8 + <span>已选中{{ checkedKeys.length }}条记录(可跨页)</span>
  9 + <a-button
  10 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  11 + type="link"
  12 + @click="handleClearChoose"
  13 + size="small"
  14 + >清空</a-button
  15 + >
  16 + </template>
  17 + <template v-else>
  18 + <span>未选中任何订单</span>
  19 + </template>
  20 + </template>
  21 + </a-alert>
  22 + </template>
4 23 <template #bodyCell="{ column, record }">
5 24 <template v-if="column.key === 'picUrl'">
6 25 <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" />
... ... @@ -19,6 +38,15 @@
19 38 </span>
20 39 </template> -->
21 40 </template>
  41 + <template #toolbar>
  42 + <a-button
  43 + type="primary"
  44 + @click="handleExport"
  45 + v-if="role == ROLE.ADMIN || role == ROLE.FINANCE"
  46 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  47 + >导出</a-button
  48 + >
  49 + </template>
22 50 </BasicTable>
23 51 <!-- <BasicModal
24 52 title="拒绝原因"
... ... @@ -39,11 +67,12 @@
39 67 </template>
40 68 <script setup lang="ts">
41 69 import { BasicTable, useTable, TableAction } from '/@/components/Table';
42   - import { getInnerProfit } from '@/api/project/invoice';
  70 + import { getInnerProfit, setInnerStatus } from '@/api/project/invoice';
43 71 import { searchFormSchema, COLUMNS } from './data';
44 72 import { BasicModal, useModal } from '/@/components/Modal';
45 73 import { useMessage } from '/@/hooks/web/useMessage';
46 74 import { onMounted, ref, computed } from 'vue';
  75 + import axios from 'axios';
47 76 import { useDrawer } from '/@/components/Drawer';
48 77 import FinanceEdit from './FinanceEdit.vue';
49 78 import CheckDetail from './CheckDetail.vue';
... ... @@ -56,6 +85,14 @@
56 85 const { createMessage } = useMessage();
57 86 const { error } = createMessage;
58 87 const message = ref();
  88 + const checkedKeys = ref<string[]>([]);
  89 + // Define arrays to store collected data from selected rows
  90 + const orderIds = ref<number[]>([]);
  91 + const projectNo = ref<string[]>([]);
  92 + const customerCode = ref<string[]>([]);
  93 + const innerNo = ref<string[]>([]);
  94 + const productionDepartment = ref<string[]>([]);
  95 + const detailProjectNoKeys = ref<string[]>([]);
59 96 const orderStore = useOrderStoreWithOut();
60 97 const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer();
61 98 const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer();
... ... @@ -74,11 +111,17 @@
74 111 message.value = '';
75 112 }
76 113 };
77   - const [registerTable, { reload }] = useTable({
  114 + const [registerTable, { reload, setSelectedRowKeys }] = useTable({
78 115 api: getInnerProfit,
79 116 bordered: true,
80 117 columns: COLUMNS,
81   - rowKey: 'id',
  118 + rowKey: 'orderId',
  119 + rowSelection: {
  120 + type: 'checkbox',
  121 + selectedRowKeys: checkedKeys as any,
  122 + onSelect: onSelect,
  123 + onSelectAll: onSelectAll,
  124 + },
82 125 formConfig: {
83 126 labelWidth: 120,
84 127 schemas: searchFormSchema,
... ... @@ -215,6 +258,7 @@
215 258 try {
216 259 // Add your API call here for updating status
217 260 // Example: await updateStatus({ id: record.id, status: status ? 1 : 2 });
  261 + await setInnerStatus({ orderId: record.orderId });
218 262 reload();
219 263 } catch (error) {
220 264 console.error(error);
... ... @@ -228,7 +272,197 @@
228 272 }
229 273  
230 274 function handleGoFormDetail() {
231   - // Add your logic for form detail navigation
  275 + reload();
  276 + }
  277 +
  278 + function handleClearChoose() {
  279 + checkedKeys.value = [];
  280 + orderIds.value = [];
  281 + projectNo.value = [];
  282 + customerCode.value = [];
  283 + innerNo.value = [];
  284 + productionDepartment.value = [];
  285 + detailProjectNoKeys.value = [];
  286 + setSelectedRowKeys([]);
  287 + }
  288 +
  289 + function handleExport() {
  290 + console.log('Selected data:', {
  291 + orderIds: orderIds.value,
  292 + projectNo: projectNo.value,
  293 + customerCode: customerCode.value,
  294 + innerNo: innerNo.value,
  295 + productionDepartment: productionDepartment.value
  296 + });
  297 + if (checkedKeys.value.length <= 0) {
  298 + createMessage.warn('请选择数据!');
  299 + return;
  300 + }
  301 + const token = userStore.getToken;
  302 + axios
  303 + .post(
  304 + '/basic-api/order/cost/innerProfitDetail/exportExcel',
  305 + {
  306 + orderIds: orderIds.value,
  307 + projectNo: projectNo.value,
  308 + customerCode: customerCode.value,
  309 + innerNo: innerNo.value,
  310 + productionDepartment: productionDepartment.value
  311 + },
  312 + {
  313 + headers: {
  314 + Authorization: `${token}`,
  315 + },
  316 + responseType: 'blob',
  317 + },
  318 + )
  319 + .then((response) => {
  320 + // 创建一个 Blob 对象来保存二进制数据
  321 + const blob = new Blob([response.data], { type: 'application/zip' });
  322 + const getFormattedDate = (): string => {
  323 + const date = new Date();
  324 +
  325 + const year = date.getFullYear();
  326 + const month = String(date.getMonth() + 1).padStart(2, '0');
  327 + const day = String(date.getDate()).padStart(2, '0');
  328 +
  329 + const hours = String(date.getHours()).padStart(2, '0');
  330 + const minutes = String(date.getMinutes()).padStart(2, '0');
  331 + const seconds = String(date.getSeconds()).padStart(2, '0');
  332 +
  333 + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  334 + };
  335 + const date = getFormattedDate();
  336 + // 创建一个链接元素用于下载
  337 + const link = document.createElement('a');
  338 + link.href = window.URL.createObjectURL(blob);
  339 + link.download = `内研数据筛选净利润分析表${date}.xlsx`;
  340 + document.body.appendChild(link);
  341 + link.click(); // 自动点击链接,触发下载
  342 + document.body.removeChild(link); // 下载完成后移除链接
  343 + })
  344 + .catch((error) => {
  345 + console.error(error);
  346 + });
  347 + reload();
  348 + }
  349 +
  350 + async function onSelect(record, selected: boolean) {
  351 + const rowKey = record.orderId;
  352 + if (selected) {
  353 + checkedKeys.value = [...checkedKeys.value, rowKey];
  354 +
  355 + // Add data from the selected row to the corresponding arrays
  356 + if (record.orderId !== undefined && !orderIds.value.includes(record.orderId)) {
  357 + orderIds.value.push(record.orderId);
  358 + }
  359 +
  360 + if (record.projectNo !== undefined && !projectNo.value.includes(record.projectNo)) {
  361 + projectNo.value.push(record.projectNo);
  362 + }
  363 +
  364 + if (record.customerCode !== undefined && !customerCode.value.includes(record.customerCode)) {
  365 + customerCode.value.push(record.customerCode);
  366 + }
  367 +
  368 + if (record.innerNo !== undefined && !innerNo.value.includes(record.innerNo)) {
  369 + innerNo.value.push(record.innerNo);
  370 + }
  371 +
  372 + if (record.productionDepartment !== undefined && !productionDepartment.value.includes(record.productionDepartment)) {
  373 + productionDepartment.value.push(record.productionDepartment);
  374 + }
  375 +
  376 + if (record.detailProjectNo !== undefined && !detailProjectNoKeys.value.includes(record.detailProjectNo)) {
  377 + detailProjectNoKeys.value.push(record.detailProjectNo);
  378 + }
  379 + } else {
  380 + checkedKeys.value = checkedKeys.value.filter((key) => key !== rowKey);
  381 +
  382 + // Remove data from the deselected row from the corresponding arrays
  383 + if (record.orderId !== undefined) {
  384 + orderIds.value = orderIds.value.filter((id) => id !== record.orderId);
  385 + }
  386 +
  387 + if (record.projectNo !== undefined) {
  388 + projectNo.value = projectNo.value.filter((no) => no !== record.projectNo);
  389 + }
  390 +
  391 + if (record.customerCode !== undefined) {
  392 + customerCode.value = customerCode.value.filter((code) => code !== record.customerCode);
  393 + }
  394 +
  395 + if (record.innerNo !== undefined) {
  396 + innerNo.value = innerNo.value.filter((no) => no !== record.innerNo);
  397 + }
  398 +
  399 + if (record.productionDepartment !== undefined) {
  400 + productionDepartment.value = productionDepartment.value.filter(
  401 + (dept) => dept !== record.productionDepartment,
  402 + );
  403 + }
  404 +
  405 + if (record.detailProjectNo !== undefined) {
  406 + detailProjectNoKeys.value = detailProjectNoKeys.value.filter(
  407 + (projectNo) => projectNo !== record.detailProjectNo,
  408 + );
  409 + }
  410 + }
  411 + setSelectedRowKeys(checkedKeys.value as any);
  412 + }
  413 +
  414 + function onSelectAll(selected: boolean, selectedRows: any[]) {
  415 + if (selected) {
  416 + // First clear all previous selections to avoid duplicates
  417 + checkedKeys.value = [];
  418 + orderIds.value = [];
  419 + projectNo.value = [];
  420 + customerCode.value = [];
  421 + innerNo.value = [];
  422 + productionDepartment.value = [];
  423 + detailProjectNoKeys.value = [];
  424 +
  425 + // Add all selected rows
  426 + selectedRows.forEach((row) => {
  427 + const rowKey = row.orderId;
  428 + checkedKeys.value.push(rowKey);
  429 +
  430 + // Add data from each selected row to the corresponding arrays
  431 + if (row.orderId !== undefined) {
  432 + orderIds.value.push(row.orderId);
  433 + }
  434 +
  435 + if (row.projectNo !== undefined) {
  436 + projectNo.value.push(row.projectNo);
  437 + }
  438 +
  439 + if (row.customerCode !== undefined) {
  440 + customerCode.value.push(row.customerCode);
  441 + }
  442 +
  443 + if (row.innerNo !== undefined) {
  444 + innerNo.value.push(row.innerNo);
  445 + }
  446 +
  447 + if (row.productionDepartment !== undefined) {
  448 + productionDepartment.value.push(row.productionDepartment);
  449 + }
  450 +
  451 + if (row.detailProjectNo !== undefined) {
  452 + detailProjectNoKeys.value.push(row.detailProjectNo);
  453 + }
  454 + });
  455 + } else {
  456 + // Clear all selections when deselecting all
  457 + checkedKeys.value = [];
  458 + orderIds.value = [];
  459 + projectNo.value = [];
  460 + customerCode.value = [];
  461 + innerNo.value = [];
  462 + productionDepartment.value = [];
  463 + detailProjectNoKeys.value = [];
  464 + }
  465 + setSelectedRowKeys(checkedKeys.value as any);
232 466 }
233 467 </script>
234 468 <style></style>
... ...
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/data.tsx
... ... @@ -245,11 +245,12 @@ export const COLUMNS = [
245 245 dataIndex: 'status',
246 246 width: 120,
247 247 customRender: (column) => {
248   - if (column.record?.status === '-1') {
  248 + if (column.record?.innerProductionStatus === null ||
  249 + column.record?.innerProductionStatus === -1) {
249 250 return '未完成';
250   - } else if (column.record?.status === '0') {
  251 + } else if (column.record?.innerProductionStatus === 0) {
251 252 return '待审核';
252   - } else if (column.record?.status === '1') {
  253 + } else if (column.record?.innerProductionStatus === 1) {
253 254 return '已审核';
254 255 }
255 256 },
... ...
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/index.vue
1 1 <template>
2 2 <div>
3 3 <BasicTable @register="registerTable" :bordered="true">
  4 + <template #headerTop>
  5 + <a-alert type="info" show-icon>
  6 + <template #message>
  7 + <template v-if="checkedKeys.length > 0">
  8 + <span>已选中{{ checkedKeys.length }}条记录(可跨页)</span>
  9 + <a-button
  10 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  11 + type="link"
  12 + @click="handleClearChoose"
  13 + size="small"
  14 + >清空</a-button
  15 + >
  16 + </template>
  17 + <template v-else>
  18 + <span>未选中任何订单</span>
  19 + </template>
  20 + </template>
  21 + </a-alert>
  22 + </template>
4 23 <template #bodyCell="{ column, record }">
5 24 <template v-if="column.key === 'picUrl'">
6 25 <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" />
... ... @@ -22,6 +41,15 @@
22 41 </span>
23 42 </template> -->
24 43 </template>
  44 + <template #toolbar>
  45 + <a-button
  46 + type="primary"
  47 + @click="handleExport"
  48 + v-if="role == ROLE.ADMIN || role == ROLE.FINANCE"
  49 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  50 + >导出</a-button
  51 + >
  52 + </template>
25 53 </BasicTable>
26 54 <!-- <BasicModal
27 55 title="拒绝原因"
... ... @@ -42,11 +70,12 @@
42 70 </template>
43 71 <script setup lang="ts">
44 72 import { BasicTable, useTable, TableAction } from '/@/components/Table';
45   - import { getInnerProduceProfit } from '@/api/project/invoice';
  73 + import { getInnerProduceProfit, setInnerProfitSetStatus } from '@/api/project/invoice';
46 74 import { searchFormSchema, COLUMNS } from './data';
47 75 import { BasicModal, useModal } from '/@/components/Modal';
48 76 import { useMessage } from '/@/hooks/web/useMessage';
49 77 import { onMounted, ref, computed } from 'vue';
  78 + import axios from 'axios';
50 79 import { useDrawer } from '/@/components/Drawer';
51 80 import FinanceEdit from './FinanceEdit.vue';
52 81 import CheckDetail from './CheckDetail.vue';
... ... @@ -59,6 +88,10 @@
59 88 const { createMessage } = useMessage();
60 89 const { error } = createMessage;
61 90 const message = ref();
  91 + const checkedKeys = ref<string[]>([]);
  92 + const invoiceIdKeys = ref<string[]>([]);
  93 + const checkIdKeys = ref<string[]>([]);
  94 + const detailProjectNoKeys = ref<string[]>([]);
62 95 const orderStore = useOrderStoreWithOut();
63 96 const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer();
64 97 const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer();
... ... @@ -77,12 +110,18 @@
77 110 message.value = '';
78 111 }
79 112 };
80   - const [registerTable, { reload }] = useTable({
  113 + const [registerTable, { reload, setSelectedRowKeys }] = useTable({
81 114 api: getInnerProduceProfit,
82 115 bordered: true,
83 116 columns: COLUMNS,
84 117 clickToRowSelect: false,
85   - rowKey: 'id',
  118 + rowKey: (record) => record.projectNoPrefix || record.id || record.serialNumber,
  119 + rowSelection: {
  120 + type: 'checkbox',
  121 + selectedRowKeys: checkedKeys as any,
  122 + onSelect: onSelect,
  123 + onSelectAll: onSelectAll,
  124 + },
86 125 formConfig: {
87 126 labelWidth: 120,
88 127 schemas: searchFormSchema,
... ... @@ -214,8 +253,10 @@
214 253  
215 254 async function handleStatus(record, status) {
216 255 try {
217   - // Add your API call here for updating status
218   - // Example: await updateStatus({ id: record.id, status: status ? 1 : 2 });
  256 + await setInnerProfitSetStatus({
  257 + projectNo: record.projectNo,
  258 + customerCode: record.customerCode
  259 + });
219 260 reload();
220 261 } catch (error) {
221 262 console.error(error);
... ... @@ -231,5 +272,140 @@
231 272 function handleGoFormDetail() {
232 273 // Add your logic for form detail navigation
233 274 }
  275 +
  276 + function handleClearChoose() {
  277 + checkedKeys.value = [];
  278 + detailProjectNoKeys.value = [];
  279 + invoiceIdKeys.value = [];
  280 + checkIdKeys.value = [];
  281 + }
  282 + async function onSelect(record, selected: boolean) {
  283 + const rowKey = record.projectNoPrefix || record.id || record.serialNumber;
  284 + if (selected) {
  285 + checkedKeys.value = [...checkedKeys.value, rowKey];
  286 +
  287 + // 使用projectNoPrefix作为单个值,添加到detailProjectNoKeys中
  288 + if (record.projectNoPrefix !== undefined) {
  289 + // 如果是单个值,检查是否已存在,然后添加到数组
  290 + if (!detailProjectNoKeys.value.includes(record.projectNoPrefix)) {
  291 + detailProjectNoKeys.value.push(record.projectNoPrefix);
  292 + }
  293 + }
  294 +
  295 + if (record.invoiceId !== undefined) {
  296 + invoiceIdKeys.value = [...invoiceIdKeys.value, record.invoiceId];
  297 + }
  298 +
  299 + if (record.checkId !== undefined) {
  300 + checkIdKeys.value = [...checkIdKeys.value, record.checkId];
  301 + }
  302 + } else {
  303 + checkedKeys.value = checkedKeys.value.filter((key) => key !== rowKey);
  304 +
  305 + // 从detailProjectNoKeys中移除projectNoPrefix
  306 + if (record.projectNoPrefix !== undefined) {
  307 + // 直接移除单个值
  308 + detailProjectNoKeys.value = detailProjectNoKeys.value.filter(
  309 + (projectNo) => projectNo !== record.projectNoPrefix
  310 + );
  311 + }
  312 +
  313 + if (record.invoiceId !== undefined) {
  314 + invoiceIdKeys.value = invoiceIdKeys.value.filter(
  315 + (invoiceId) => invoiceId !== record.invoiceId,
  316 + );
  317 + }
  318 +
  319 + if (record.checkId !== undefined) {
  320 + checkIdKeys.value = checkIdKeys.value.filter((checkId) => checkId !== record.checkId);
  321 + }
  322 + }
  323 + setSelectedRowKeys(checkedKeys.value as any);
  324 + }
  325 +
  326 + function onSelectAll(selected: boolean, selectedRows: any[]) {
  327 + if (selected) {
  328 + // 先清空之前的选择,避免重复添加
  329 + checkedKeys.value = [];
  330 + detailProjectNoKeys.value = [];
  331 + invoiceIdKeys.value = [];
  332 + checkIdKeys.value = [];
  333 +
  334 + // 重新添加所有选中的行
  335 + selectedRows.forEach((row) => {
  336 + const rowKey = row.projectNoPrefix || row.id || row.serialNumber;
  337 + checkedKeys.value.push(rowKey);
  338 +
  339 + // 使用projectNoPrefix作为单个值,添加到detailProjectNoKeys中
  340 + if (row.projectNoPrefix !== undefined) {
  341 + // 由于已经清空了数组,不需要检查是否存在
  342 + detailProjectNoKeys.value.push(row.projectNoPrefix);
  343 + }
  344 +
  345 + if (row.invoiceId !== undefined) {
  346 + invoiceIdKeys.value.push(row.invoiceId);
  347 + }
  348 +
  349 + if (row.checkId !== undefined) {
  350 + checkIdKeys.value.push(row.checkId);
  351 + }
  352 + });
  353 + } else {
  354 + // 取消全选时,清空所有选择
  355 + checkedKeys.value = [];
  356 + detailProjectNoKeys.value = [];
  357 + invoiceIdKeys.value = [];
  358 + checkIdKeys.value = [];
  359 + }
  360 + setSelectedRowKeys(checkedKeys.value as any);
  361 + }
  362 + function handleExport() {
  363 + console.log(detailProjectNoKeys.value, '5656detailProjectNoKeys.value');
  364 + if (checkedKeys.value.length <= 0) {
  365 + createMessage.warn('请选择数据!');
  366 + return;
  367 + }
  368 + const token = userStore.getToken;
  369 + axios
  370 + .post(
  371 + '/basic-api/project/innerProfitInfo/exportExcel',
  372 + { detailProjectNo: detailProjectNoKeys.value },
  373 + {
  374 + headers: {
  375 + Authorization: `${token}`, // 去掉引号
  376 + },
  377 + responseType: 'blob', // 设置响应类型为 'blob'
  378 + },
  379 + )
  380 + .then((response) => {
  381 + // 创建一个 Blob 对象来保存二进制数据
  382 + const blob = new Blob([response.data], { type: 'application/zip' });
  383 + const getFormattedDate = (): string => {
  384 + const date = new Date();
  385 +
  386 + const year = date.getFullYear();
  387 + const month = String(date.getMonth() + 1).padStart(2, '0');
  388 + const day = String(date.getDate()).padStart(2, '0');
  389 +
  390 + const hours = String(date.getHours()).padStart(2, '0');
  391 + const minutes = String(date.getMinutes()).padStart(2, '0');
  392 + const seconds = String(date.getSeconds()).padStart(2, '0');
  393 +
  394 + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  395 + };
  396 + const date = getFormattedDate();
  397 + // 创建一个链接元素用于下载
  398 + const link = document.createElement('a');
  399 + link.href = window.URL.createObjectURL(blob);
  400 + link.download = `内产生产净利润分析表${date}.xlsx`; // 你可以为文件命名
  401 + document.body.appendChild(link);
  402 + link.click(); // 自动点击链接,触发下载
  403 + document.body.removeChild(link); // 下载完成后移除链接
  404 + })
  405 + .catch((error) => {
  406 + console.error(error);
  407 + });
  408 + reload();
  409 + }
234 410 </script>
235 411 <style></style>
... ...
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/data.tsx
... ... @@ -192,11 +192,11 @@ export const COLUMNS = [
192 192 dataIndex: 'status',
193 193 width: 120,
194 194 customRender: (column) => {
195   - if (column.record?.status === '-1') {
  195 + if (column.record?.packStatus === null || column.record?.packStatus === -1) {
196 196 return '未完成';
197   - } else if (column.record?.status === '0') {
  197 + } else if (column.record?.packStatus === 0) {
198 198 return '待审核';
199   - } else if (column.record?.status === '1') {
  199 + } else if (column.record?.packStatus === 1) {
200 200 return '已审核';
201 201 }
202 202 },
... ...
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/index.vue
1 1 <template>
2 2 <div>
3 3 <BasicTable @register="registerTable" :bordered="true">
  4 + <template #headerTop>
  5 + <a-alert type="info" show-icon>
  6 + <template #message>
  7 + <template v-if="checkedKeys.length > 0">
  8 + <span>已选中{{ checkedKeys.length }}条记录(可跨页)</span>
  9 + <a-button
  10 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  11 + type="link"
  12 + @click="handleClearChoose"
  13 + size="small"
  14 + >清空</a-button
  15 + >
  16 + </template>
  17 + <template v-else>
  18 + <span>未选中任何订单</span>
  19 + </template>
  20 + </template>
  21 + </a-alert>
  22 + </template>
4 23 <template #bodyCell="{ column, record }">
5 24 <template v-if="column.key === 'picUrl'">
6 25 <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" />
... ... @@ -22,6 +41,15 @@
22 41 </span>
23 42 </template> -->
24 43 </template>
  44 + <template #toolbar>
  45 + <a-button
  46 + type="primary"
  47 + @click="handleExport"
  48 + v-if="role == ROLE.ADMIN || role == ROLE.FINANCE"
  49 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  50 + >导出</a-button
  51 + >
  52 + </template>
25 53 </BasicTable>
26 54 <!-- <BasicModal
27 55 title="拒绝原因"
... ... @@ -42,7 +70,7 @@
42 70 </template>
43 71 <script setup lang="ts">
44 72 import { BasicTable, useTable, TableAction } from '/@/components/Table';
45   - import { getPackageProfit } from '@/api/project/invoice';
  73 + import { getPackageProfit, setPackStatus } from '@/api/project/invoice';
46 74 import { searchFormSchema, COLUMNS } from './data';
47 75 import { BasicModal, useModal } from '/@/components/Modal';
48 76 import { useMessage } from '/@/hooks/web/useMessage';
... ... @@ -51,6 +79,7 @@
51 79 import FinanceEdit from './FinanceEdit.vue';
52 80 import CheckDetail from './CheckDetail.vue';
53 81 import HistoryDetail from './HistoryDetail.vue';
  82 + import axios from 'axios';
54 83 import { FilePptOutlined } from '@ant-design/icons-vue';
55 84 import { useOrderStoreWithOut } from '/@/store/modules/order';
56 85 import { useUserStoreWithOut } from '/@/store/modules/user';
... ... @@ -60,6 +89,14 @@
60 89 const { createMessage } = useMessage();
61 90 const { error } = createMessage;
62 91 const message = ref();
  92 + const checkedKeys = ref<string[]>([]);
  93 + // Define arrays to store collected data from selected rows
  94 + const orderIds = ref<number[]>([]);
  95 + const projectNo = ref<string[]>([]);
  96 + const customerCode = ref<string[]>([]);
  97 + const innerNo = ref<string[]>([]);
  98 + const productionDepartment = ref<string[]>([]);
  99 + const detailProjectNoKeys = ref<string[]>([]);
63 100 const orderStore = useOrderStoreWithOut();
64 101 const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer();
65 102 const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer();
... ... @@ -78,7 +115,7 @@
78 115 message.value = '';
79 116 }
80 117 };
81   - const [registerTable, { reload }] = useTable({
  118 + const [registerTable, { reload, setSelectedRowKeys }] = useTable({
82 119 api: getPackageProfit,
83 120 bordered: true,
84 121 columns: COLUMNS,
... ... @@ -88,6 +125,13 @@
88 125 schemas: searchFormSchema,
89 126 autoSubmitOnEnter: true,
90 127 },
  128 + rowKey: (record) => record.orderId,
  129 + rowSelection: {
  130 + type: 'checkbox',
  131 + selectedRowKeys: checkedKeys as any,
  132 + onSelect: onSelect,
  133 + onSelectAll: onSelectAll,
  134 + },
91 135 useSearchForm: true,
92 136 showTableSetting: true,
93 137 showIndexColumn: false,
... ... @@ -213,8 +257,7 @@
213 257  
214 258 async function handleStatus(record, status) {
215 259 try {
216   - // Add your API call here for updating status
217   - // Example: await updateStatus({ id: record.id, status: status ? 1 : 2 });
  260 + await setPackStatus({ orderId: record.orderId });
218 261 reload();
219 262 } catch (error) {
220 263 console.error(error);
... ... @@ -234,5 +277,180 @@
234 277 onMounted(async () => {
235 278 await orderStore.getDict();
236 279 });
  280 +
  281 + function handleClearChoose() {
  282 + checkedKeys.value = [];
  283 + // Clear all collected data arrays
  284 + orderIds.value = [];
  285 + projectNo.value = [];
  286 + customerCode.value = [];
  287 + innerNo.value = [];
  288 + productionDepartment.value = [];
  289 + detailProjectNoKeys.value = []; // Add this line
  290 + }
  291 +
  292 + function handleExport() {
  293 + console.log('Selected data:', {
  294 + orderIds: orderIds.value,
  295 + projectNo: projectNo.value,
  296 + customerCode: customerCode.value,
  297 + innerNo: innerNo.value,
  298 + productionDepartment: productionDepartment.value
  299 + });
  300 + if (checkedKeys.value.length <= 0) {
  301 + createMessage.warn('请选择数据!');
  302 + return;
  303 + }
  304 + const token = userStore.getToken;
  305 + axios
  306 + .post(
  307 + '/basic-api/order/cost/businessProfitDetail/exportExcel',
  308 + {
  309 + orderIds: orderIds.value,
  310 + projectNo: projectNo.value,
  311 + customerCode: customerCode.value,
  312 + innerNo: innerNo.value,
  313 + productionDepartment: productionDepartment.value
  314 + },
  315 + {
  316 + headers: {
  317 + Authorization: `${token}`, // 去掉引号
  318 + },
  319 + responseType: 'blob', // 设置响应类型为 'blob'
  320 + },
  321 + )
  322 + .then((response) => {
  323 + // 创建一个 Blob 对象来保存二进制数据
  324 + const blob = new Blob([response.data], { type: 'application/zip' });
  325 + const getFormattedDate = (): string => {
  326 + const date = new Date();
  327 +
  328 + const year = date.getFullYear();
  329 + const month = String(date.getMonth() + 1).padStart(2, '0');
  330 + const day = String(date.getDate()).padStart(2, '0');
  331 +
  332 + const hours = String(date.getHours()).padStart(2, '0');
  333 + const minutes = String(date.getMinutes()).padStart(2, '0');
  334 + const seconds = String(date.getSeconds()).padStart(2, '0');
  335 +
  336 + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  337 + };
  338 + const date = getFormattedDate();
  339 + // 创建一个链接元素用于下载
  340 + const link = document.createElement('a');
  341 + link.href = window.URL.createObjectURL(blob);
  342 + link.download = `业务利润分析表${date}.xlsx`; // 你可以为文件命名
  343 + document.body.appendChild(link);
  344 + link.click(); // 自动点击链接,触发下载
  345 + document.body.removeChild(link); // 下载完成后移除链接
  346 + })
  347 + .catch((error) => {
  348 + console.error(error);
  349 + });
  350 + reload();
  351 + }
  352 + async function onSelect(record, selected: boolean) {
  353 + const rowKey = record.orderId;
  354 + if (selected) {
  355 + checkedKeys.value = [...checkedKeys.value, rowKey];
  356 +
  357 + // Add data from the selected row to the corresponding arrays
  358 + if (record.orderId !== undefined && !orderIds.value.includes(record.orderId)) {
  359 + orderIds.value.push(record.orderId);
  360 + }
  361 +
  362 + if (record.projectNo !== undefined && !projectNo.value.includes(record.projectNo)) {
  363 + projectNo.value.push(record.projectNo);
  364 + }
  365 +
  366 + if (record.customerCode !== undefined && !customerCode.value.includes(record.customerCode)) {
  367 + customerCode.value.push(record.customerCode);
  368 + }
  369 +
  370 + if (record.innerNo !== undefined && !innerNo.value.includes(record.innerNo)) {
  371 + innerNo.value.push(record.innerNo);
  372 + }
  373 +
  374 + if (record.productionDepartment !== undefined && !productionDepartment.value.includes(record.productionDepartment)) {
  375 + productionDepartment.value.push(record.productionDepartment);
  376 + }
  377 +
  378 + if (record.detailProjectNoKey !== undefined && !detailProjectNoKeys.value.includes(record.detailProjectNoKey)) {
  379 + detailProjectNoKeys.value.push(record.detailProjectNoKey);
  380 + }
  381 + } else {
  382 + checkedKeys.value = checkedKeys.value.filter((key) => key !== rowKey);
  383 +
  384 + // Remove data from the deselected row from the corresponding arrays
  385 + if (record.orderId !== undefined) {
  386 + orderIds.value = orderIds.value.filter(id => id !== record.orderId);
  387 + }
  388 +
  389 + if (record.projectNo !== undefined) {
  390 + projectNo.value = projectNo.value.filter(no => no !== record.projectNo);
  391 + }
  392 +
  393 + if (record.customerCode !== undefined) {
  394 + customerCode.value = customerCode.value.filter(code => code !== record.customerCode);
  395 + }
  396 +
  397 + if (record.innerNo !== undefined) {
  398 + innerNo.value = innerNo.value.filter(no => no !== record.innerNo);
  399 + }
  400 +
  401 + if (record.productionDepartment !== undefined) {
  402 + productionDepartment.value = productionDepartment.value.filter(dept => dept !== record.productionDepartment);
  403 + }
  404 + }
  405 + setSelectedRowKeys(checkedKeys.value as any);
  406 + }
  407 +
  408 + function onSelectAll(selected: boolean, selectedRows: any[]) {
  409 + if (selected) {
  410 + // First clear all previous selections to avoid duplicates
  411 + checkedKeys.value = [];
  412 + orderIds.value = [];
  413 + projectNo.value = [];
  414 + customerCode.value = [];
  415 + innerNo.value = [];
  416 + productionDepartment.value = [];
  417 +
  418 + // Add all selected rows
  419 + selectedRows.forEach((row) => {
  420 + const rowKey = row.orderId;
  421 + checkedKeys.value.push(rowKey);
  422 +
  423 + // Add data from each selected row to the corresponding arrays
  424 + if (row.orderId !== undefined) {
  425 + orderIds.value.push(row.orderId);
  426 + }
  427 +
  428 + if (row.projectNo !== undefined) {
  429 + projectNo.value.push(row.projectNo);
  430 + }
  431 +
  432 + if (row.customerCode !== undefined) {
  433 + customerCode.value.push(row.customerCode);
  434 + }
  435 +
  436 + if (row.innerNo !== undefined) {
  437 + innerNo.value.push(row.innerNo);
  438 + }
  439 +
  440 + if (row.productionDepartment !== undefined) {
  441 + productionDepartment.value.push(row.productionDepartment);
  442 + }
  443 + });
  444 + } else {
  445 + // Clear all selections when deselecting all
  446 + checkedKeys.value = [];
  447 + orderIds.value = [];
  448 + projectNo.value = [];
  449 + customerCode.value = [];
  450 + innerNo.value = [];
  451 + productionDepartment.value = [];
  452 + }
  453 + setSelectedRowKeys(checkedKeys.value as any);
  454 + }
237 455 </script>
238 456 <style></style>
... ...
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/data.tsx
... ... @@ -377,11 +377,11 @@ export const COLUMNS = [
377 377 dataIndex: 'status',
378 378 width: 120,
379 379 customRender: (column) => {
380   - if (column.record?.status === '-1') {
  380 + if (column.record?.developmentStatus === null || column.record?.developmentStatus === -1) {
381 381 return '未完成';
382   - } else if (column.record?.status === '0') {
  382 + } else if (column.record?.developmentStatus === 0) {
383 383 return '待审核';
384   - } else if (column.record?.status === '1') {
  384 + } else if (column.record?.developmentStatus === 1) {
385 385 return '已审核';
386 386 }
387 387 },
... ...
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/index.vue
... ... @@ -45,7 +45,7 @@
45 45 </template>
46 46 <script setup lang="ts">
47 47 import { BasicTable, useTable, TableAction } from '/@/components/Table';
48   - import { getServiceProfit } from '@/api/project/invoice';
  48 + import { getServiceProfit, setBusinessProfitSetStatus } from '@/api/project/invoice';
49 49 import { searchFormSchema, COLUMNS } from './data';
50 50 import axios from 'axios';
51 51 import { useMessage } from '/@/hooks/web/useMessage';
... ... @@ -183,12 +183,12 @@
183 183 record.onEdit?.(false, false);
184 184 }
185 185  
186   - async function handleDelete(record) {
187   - reload();
188   - }
189   -
190 186 async function handleStatus(record, status) {
191 187 try {
  188 + await setBusinessProfitSetStatus({
  189 + customerCode: record.customerCode,
  190 + projectNo: record.projectNo
  191 + });
192 192 reload();
193 193 } catch (error) {
194 194 console.error('Error updating status:', error);
... ... @@ -317,35 +317,40 @@
317 317  
318 318 function onSelectAll(selected: boolean, selectedRows: any[]) {
319 319 if (selected) {
  320 + // 先清空之前的选择,避免重复添加
  321 + checkedKeys.value = [];
  322 + detailProjectNoKeys.value = [];
  323 + invoiceIdKeys.value = [];
  324 + checkIdKeys.value = [];
  325 +
  326 + // 重新添加所有选中的行
320 327 selectedRows.forEach((row) => {
321 328 const rowKey = row.detailProjectNo || row.id || row.serialNumber;
322   - checkedKeys.value = [...checkedKeys.value, rowKey];
  329 + checkedKeys.value.push(rowKey);
323 330  
324 331 // 如果detailProjectNo是数组,将每个元素添加到detailProjectNoKeys中
325 332 if (row.detailProjectNo !== undefined) {
326 333 if (Array.isArray(row.detailProjectNo)) {
327 334 row.detailProjectNo.forEach((projectNo) => {
328   - if (!detailProjectNoKeys.value.includes(projectNo)) {
329   - detailProjectNoKeys.value.push(projectNo);
330   - }
  335 + // 由于已经清空了数组,不需要检查是否存在
  336 + detailProjectNoKeys.value.push(projectNo);
331 337 });
332 338 } else {
333 339 // 如果是单个值,直接添加
334   - if (!detailProjectNoKeys.value.includes(row.detailProjectNo)) {
335   - detailProjectNoKeys.value.push(row.detailProjectNo);
336   - }
  340 + detailProjectNoKeys.value.push(row.detailProjectNo);
337 341 }
338 342 }
339 343  
340 344 if (row.invoiceId !== undefined) {
341   - invoiceIdKeys.value = [...invoiceIdKeys.value, row.invoiceId];
  345 + invoiceIdKeys.value.push(row.invoiceId);
342 346 }
343 347  
344 348 if (row.checkId !== undefined) {
345   - checkIdKeys.value = [...checkIdKeys.value, row.checkId];
  349 + checkIdKeys.value.push(row.checkId);
346 350 }
347 351 });
348 352 } else {
  353 + // 取消全选时,清空所有选择
349 354 checkedKeys.value = [];
350 355 detailProjectNoKeys.value = [];
351 356 invoiceIdKeys.value = [];
... ...