Commit 192bbb6f2f94865908074ddad8a16b5d14274068

Authored by boyang
1 parent f267cff7

feat: 开发业务利润表导出

src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/index.vue
1 <template> 1 <template>
2 <div> 2 <div>
3 <BasicTable @register="registerTable" :bordered="true"> 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 <template #bodyCell="{ column, record }"> 23 <template #bodyCell="{ column, record }">
5 <template v-if="column.key === 'action'"> 24 <template v-if="column.key === 'action'">
6 <TableAction 25 <TableAction
@@ -8,30 +27,17 @@ @@ -8,30 +27,17 @@
8 :dropDownActions="createDropActions(record)" 27 :dropDownActions="createDropActions(record)"
9 /> 28 />
10 </template> 29 </template>
11 - <!-- <template v-if="column.key === 'relationValue'">  
12 - <a-input  
13 - v-if="record.settingValue === 'A01'"  
14 - v-model:value="record.settingValue"  
15 - :max-length="50"  
16 - />  
17 - <span v-else style="color: red">  
18 - {{ record.settingValue }}  
19 - </span>  
20 - </template> --> 30 + </template>
  31 + <template #toolbar>
  32 + <a-button
  33 + type="primary"
  34 + @click="handleExport"
  35 + v-if="role == ROLE.ADMIN || role == ROLE.FINANCE"
  36 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  37 + >导出</a-button
  38 + >
21 </template> 39 </template>
22 </BasicTable> 40 </BasicTable>
23 - <!-- <BasicModal  
24 - title="拒绝原因"  
25 - width="30%"  
26 - @register="registerModal"  
27 - @visible-change="handleClose"  
28 - @ok="handleOk"  
29 - wrapClassName="approve-modal"  
30 - >  
31 - <div className="pa-8">  
32 - <a-textarea :rows="6" placeholder="请输入拒绝原因" v-model:value="message" />  
33 - </div>  
34 - </BasicModal> -->  
35 <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> 41 <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" />
36 <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> 42 <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" />
37 <HistoryDetail @register="registerHistoryDetail" /> 43 <HistoryDetail @register="registerHistoryDetail" />
@@ -41,6 +47,7 @@ @@ -41,6 +47,7 @@
41 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 47 import { BasicTable, useTable, TableAction } from '/@/components/Table';
42 import { getServiceProfit } from '@/api/project/invoice'; 48 import { getServiceProfit } from '@/api/project/invoice';
43 import { searchFormSchema, COLUMNS } from './data'; 49 import { searchFormSchema, COLUMNS } from './data';
  50 + import axios from 'axios';
44 import { useMessage } from '/@/hooks/web/useMessage'; 51 import { useMessage } from '/@/hooks/web/useMessage';
45 import { onMounted, ref, computed, unref } from 'vue'; 52 import { onMounted, ref, computed, unref } from 'vue';
46 import { useDrawer } from '/@/components/Drawer'; 53 import { useDrawer } from '/@/components/Drawer';
@@ -56,6 +63,7 @@ @@ -56,6 +63,7 @@
56 const checkedKeys = ref<string[]>([]); 63 const checkedKeys = ref<string[]>([]);
57 const invoiceIdKeys = ref<string[]>([]); 64 const invoiceIdKeys = ref<string[]>([]);
58 const checkIdKeys = ref<string[]>([]); 65 const checkIdKeys = ref<string[]>([]);
  66 + const detailProjectNoKeys = ref<string[]>([]);
59 const orderStore = useOrderStoreWithOut(); 67 const orderStore = useOrderStoreWithOut();
60 const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); 68 const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer();
61 const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); 69 const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer();
@@ -66,16 +74,17 @@ @@ -66,16 +74,17 @@
66 return user?.roleSmallVO?.code; 74 return user?.roleSmallVO?.code;
67 }); 75 });
68 const [registerTable, { reload, getSelectRowKeys, getDataSource, setSelectedRowKeys }] = useTable({ 76 const [registerTable, { reload, getSelectRowKeys, getDataSource, setSelectedRowKeys }] = useTable({
69 - 77 + title: '',
70 api: getServiceProfit, 78 api: getServiceProfit,
71 bordered: true, 79 bordered: true,
72 columns: COLUMNS, 80 columns: COLUMNS,
73 clickToRowSelect: false, 81 clickToRowSelect: false,
74 - rowKey: 'id',  
75 - formConfig: {  
76 - labelWidth: 120,  
77 - schemas: searchFormSchema,  
78 - autoSubmitOnEnter: true, 82 + rowKey: (record) => record.detailProjectNo || record.id || record.serialNumber,
  83 + rowSelection: {
  84 + type: 'checkbox',
  85 + selectedRowKeys: checkedKeys as any,
  86 + onSelect: onSelect,
  87 + onSelectAll: onSelectAll,
79 }, 88 },
80 useSearchForm: true, 89 useSearchForm: true,
81 showTableSetting: true, 90 showTableSetting: true,
@@ -97,23 +106,8 @@ @@ -97,23 +106,8 @@
97 label: '财务编辑', 106 label: '财务编辑',
98 onClick: handleFinanceEdit.bind(null, record), 107 onClick: handleFinanceEdit.bind(null, record),
99 }, 108 },
100 - // {  
101 - // label: '编辑',  
102 - // onClick: handleEdit.bind(null, record),  
103 - // },  
104 - // {  
105 - // label: '删除',  
106 - // popConfirm: {  
107 - // title: '确认删除?',  
108 - // confirm: handleDelete.bind(null, record),  
109 - // },  
110 - // },  
111 { 109 {
112 label: '申请权限', 110 label: '申请权限',
113 - // popConfirm: {  
114 - // title: '确认申请?',  
115 - // confirm: handleFalse.bind(null, record),  
116 - // },  
117 onClick: handleFalse.bind(null, record), 111 onClick: handleFalse.bind(null, record),
118 }, 112 },
119 { 113 {
@@ -173,11 +167,6 @@ @@ -173,11 +167,6 @@
173 return false; 167 return false;
174 } 168 }
175 169
176 - // async function handleFalse(record: any) {  
177 - // console.log(record);  
178 - // // openModal(true, { record });  
179 - // }  
180 -  
181 function handleSuccess() { 170 function handleSuccess() {
182 setTimeout(() => { 171 setTimeout(() => {
183 reload(); 172 reload();
@@ -189,26 +178,17 @@ @@ -189,26 +178,17 @@
189 handleCancel(record); 178 handleCancel(record);
190 reload(); 179 reload();
191 } 180 }
192 - function handleEdit(record: any) {  
193 - // if (record.settingValue == 'A01') {  
194 - // error('请勿连续点击生成按钮,需要等待三秒再点击生成');  
195 - // } else {  
196 - record.onEdit?.(true);  
197 - }  
198 181
199 function handleCancel(record) { 182 function handleCancel(record) {
200 record.onEdit?.(false, false); 183 record.onEdit?.(false, false);
201 } 184 }
202 185
203 async function handleDelete(record) { 186 async function handleDelete(record) {
204 - // await deleteConfig({ ids: [record.id] });  
205 reload(); 187 reload();
206 } 188 }
207 189
208 async function handleStatus(record, status) { 190 async function handleStatus(record, status) {
209 try { 191 try {
210 - // You can implement the API call here  
211 - // await someApiCall({ id: record.id, status });  
212 reload(); 192 reload();
213 } catch (error) { 193 } catch (error) {
214 console.error('Error updating status:', error); 194 console.error('Error updating status:', error);
@@ -220,5 +200,158 @@ @@ -220,5 +200,158 @@
220 data: record, 200 data: record,
221 }); 201 });
222 } 202 }
  203 +
  204 + function handleExport() {
  205 + console.log(detailProjectNoKeys.value, '5656detailProjectNoKeys.value');
  206 + if (checkedKeys.value.length <= 0) {
  207 + createMessage.warn('请选择数据!');
  208 + return;
  209 + }
  210 + const token = userStore.getToken;
  211 + axios
  212 + .post(
  213 + '/basic-api/project/businessProfit/exportExcel',
  214 + { detailProjectNo: detailProjectNoKeys.value },
  215 + {
  216 + headers: {
  217 + Authorization: `${token}`, // 去掉引号
  218 + },
  219 + responseType: 'blob', // 设置响应类型为 'blob'
  220 + },
  221 + )
  222 + .then((response) => {
  223 + // 创建一个 Blob 对象来保存二进制数据
  224 + const blob = new Blob([response.data], { type: 'application/zip' });
  225 + const getFormattedDate = (): string => {
  226 + const date = new Date();
  227 +
  228 + const year = date.getFullYear();
  229 + const month = String(date.getMonth() + 1).padStart(2, '0');
  230 + const day = String(date.getDate()).padStart(2, '0');
  231 +
  232 + const hours = String(date.getHours()).padStart(2, '0');
  233 + const minutes = String(date.getMinutes()).padStart(2, '0');
  234 + const seconds = String(date.getSeconds()).padStart(2, '0');
  235 +
  236 + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  237 + };
  238 + const date = getFormattedDate();
  239 + // 创建一个链接元素用于下载
  240 + const link = document.createElement('a');
  241 + link.href = window.URL.createObjectURL(blob);
  242 + link.download = `业务利润分析表${date}.xlsx`; // 你可以为文件命名
  243 + document.body.appendChild(link);
  244 + link.click(); // 自动点击链接,触发下载
  245 + document.body.removeChild(link); // 下载完成后移除链接
  246 + })
  247 + .catch((error) => {
  248 + console.error(error);
  249 + });
  250 + reload();
  251 + }
  252 +
  253 + function handleClearChoose() {
  254 + checkedKeys.value = [];
  255 + detailProjectNoKeys.value = [];
  256 + invoiceIdKeys.value = [];
  257 + checkIdKeys.value = [];
  258 + }
  259 +
  260 + async function onSelect(record, selected: boolean) {
  261 + const rowKey = record.detailProjectNo || record.id || record.serialNumber;
  262 + if (selected) {
  263 + checkedKeys.value = [...checkedKeys.value, rowKey];
  264 +
  265 + // 如果detailProjectNo是数组,将每个元素添加到detailProjectNoKeys中
  266 + if (record.detailProjectNo !== undefined) {
  267 + if (Array.isArray(record.detailProjectNo)) {
  268 + record.detailProjectNo.forEach((projectNo) => {
  269 + if (!detailProjectNoKeys.value.includes(projectNo)) {
  270 + detailProjectNoKeys.value.push(projectNo);
  271 + }
  272 + });
  273 + } else {
  274 + // 如果是单个值,直接添加
  275 + if (!detailProjectNoKeys.value.includes(record.detailProjectNo)) {
  276 + detailProjectNoKeys.value.push(record.detailProjectNo);
  277 + }
  278 + }
  279 + }
  280 +
  281 + if (record.invoiceId !== undefined) {
  282 + invoiceIdKeys.value = [...invoiceIdKeys.value, record.invoiceId];
  283 + }
  284 +
  285 + if (record.checkId !== undefined) {
  286 + checkIdKeys.value = [...checkIdKeys.value, record.checkId];
  287 + }
  288 + } else {
  289 + checkedKeys.value = checkedKeys.value.filter((key) => key !== rowKey);
  290 +
  291 + // 如果detailProjectNo是数组,从detailProjectNoKeys中移除每个元素
  292 + if (record.detailProjectNo !== undefined) {
  293 + if (Array.isArray(record.detailProjectNo)) {
  294 + detailProjectNoKeys.value = detailProjectNoKeys.value.filter(
  295 + (projectNo) => !record.detailProjectNo.includes(projectNo)
  296 + );
  297 + } else {
  298 + // 如果是单个值,直接移除
  299 + detailProjectNoKeys.value = detailProjectNoKeys.value.filter(
  300 + (projectNo) => projectNo !== record.detailProjectNo
  301 + );
  302 + }
  303 + }
  304 +
  305 + if (record.invoiceId !== undefined) {
  306 + invoiceIdKeys.value = invoiceIdKeys.value.filter(
  307 + (invoiceId) => invoiceId !== record.invoiceId,
  308 + );
  309 + }
  310 +
  311 + if (record.checkId !== undefined) {
  312 + checkIdKeys.value = checkIdKeys.value.filter((checkId) => checkId !== record.checkId);
  313 + }
  314 + }
  315 + setSelectedRowKeys(checkedKeys.value as any);
  316 + }
  317 +
  318 + function onSelectAll(selected: boolean, selectedRows: any[]) {
  319 + if (selected) {
  320 + selectedRows.forEach((row) => {
  321 + const rowKey = row.detailProjectNo || row.id || row.serialNumber;
  322 + checkedKeys.value = [...checkedKeys.value, rowKey];
  323 +
  324 + // 如果detailProjectNo是数组,将每个元素添加到detailProjectNoKeys中
  325 + if (row.detailProjectNo !== undefined) {
  326 + if (Array.isArray(row.detailProjectNo)) {
  327 + row.detailProjectNo.forEach((projectNo) => {
  328 + if (!detailProjectNoKeys.value.includes(projectNo)) {
  329 + detailProjectNoKeys.value.push(projectNo);
  330 + }
  331 + });
  332 + } else {
  333 + // 如果是单个值,直接添加
  334 + if (!detailProjectNoKeys.value.includes(row.detailProjectNo)) {
  335 + detailProjectNoKeys.value.push(row.detailProjectNo);
  336 + }
  337 + }
  338 + }
  339 +
  340 + if (row.invoiceId !== undefined) {
  341 + invoiceIdKeys.value = [...invoiceIdKeys.value, row.invoiceId];
  342 + }
  343 +
  344 + if (row.checkId !== undefined) {
  345 + checkIdKeys.value = [...checkIdKeys.value, row.checkId];
  346 + }
  347 + });
  348 + } else {
  349 + checkedKeys.value = [];
  350 + detailProjectNoKeys.value = [];
  351 + invoiceIdKeys.value = [];
  352 + checkIdKeys.value = [];
  353 + }
  354 + setSelectedRowKeys(checkedKeys.value as any);
  355 + }
223 </script> 356 </script>
224 <style></style> 357 <style></style>