Commit 192bbb6f2f94865908074ddad8a16b5d14274068

Authored by boyang
1 parent f267cff7

feat: 开发业务利润表导出

src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/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 === 'action'">
6 25 <TableAction
... ... @@ -8,30 +27,17 @@
8 27 :dropDownActions="createDropActions(record)"
9 28 />
10 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 39 </template>
22 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 41 <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" />
36 42 <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" />
37 43 <HistoryDetail @register="registerHistoryDetail" />
... ... @@ -41,6 +47,7 @@
41 47 import { BasicTable, useTable, TableAction } from '/@/components/Table';
42 48 import { getServiceProfit } from '@/api/project/invoice';
43 49 import { searchFormSchema, COLUMNS } from './data';
  50 + import axios from 'axios';
44 51 import { useMessage } from '/@/hooks/web/useMessage';
45 52 import { onMounted, ref, computed, unref } from 'vue';
46 53 import { useDrawer } from '/@/components/Drawer';
... ... @@ -56,6 +63,7 @@
56 63 const checkedKeys = ref<string[]>([]);
57 64 const invoiceIdKeys = ref<string[]>([]);
58 65 const checkIdKeys = ref<string[]>([]);
  66 + const detailProjectNoKeys = ref<string[]>([]);
59 67 const orderStore = useOrderStoreWithOut();
60 68 const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer();
61 69 const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer();
... ... @@ -66,16 +74,17 @@
66 74 return user?.roleSmallVO?.code;
67 75 });
68 76 const [registerTable, { reload, getSelectRowKeys, getDataSource, setSelectedRowKeys }] = useTable({
69   -
  77 + title: '',
70 78 api: getServiceProfit,
71 79 bordered: true,
72 80 columns: COLUMNS,
73 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 89 useSearchForm: true,
81 90 showTableSetting: true,
... ... @@ -97,23 +106,8 @@
97 106 label: '财务编辑',
98 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 110 label: '申请权限',
113   - // popConfirm: {
114   - // title: '确认申请?',
115   - // confirm: handleFalse.bind(null, record),
116   - // },
117 111 onClick: handleFalse.bind(null, record),
118 112 },
119 113 {
... ... @@ -173,11 +167,6 @@
173 167 return false;
174 168 }
175 169  
176   - // async function handleFalse(record: any) {
177   - // console.log(record);
178   - // // openModal(true, { record });
179   - // }
180   -
181 170 function handleSuccess() {
182 171 setTimeout(() => {
183 172 reload();
... ... @@ -189,26 +178,17 @@
189 178 handleCancel(record);
190 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 182 function handleCancel(record) {
200 183 record.onEdit?.(false, false);
201 184 }
202 185  
203 186 async function handleDelete(record) {
204   - // await deleteConfig({ ids: [record.id] });
205 187 reload();
206 188 }
207 189  
208 190 async function handleStatus(record, status) {
209 191 try {
210   - // You can implement the API call here
211   - // await someApiCall({ id: record.id, status });
212 192 reload();
213 193 } catch (error) {
214 194 console.error('Error updating status:', error);
... ... @@ -220,5 +200,158 @@
220 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 356 </script>
224 357 <style></style>
... ...