diff --git a/apps/finance/src/api/defaultRequest.ts b/apps/finance/src/api/defaultRequest.ts new file mode 100644 index 0000000..6753d41 --- /dev/null +++ b/apps/finance/src/api/defaultRequest.ts @@ -0,0 +1,110 @@ +/** + * 该文件可自行根据业务逻辑进行调整 + */ +import type { RequestClientOptions } from '@vben/request'; + +import { useAppConfig } from '@vben/hooks'; +import { preferences } from '@vben/preferences'; +import { + authenticateResponseInterceptor, + defaultResponseInterceptor, + errorMessageResponseInterceptor, + RequestClient, +} from '@vben/request'; +import { useAccessStore } from '@vben/stores'; + +import { message } from 'ant-design-vue'; + +import { useAuthStore } from '#/store'; + +import { refreshTokenApi } from './core'; + +const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD); + +function createRequestClient(baseURL: string, options?: RequestClientOptions) { + const client = new RequestClient({ + ...options, + baseURL, + }); + + /** + * 重新认证逻辑 + */ + async function doReAuthenticate() { + console.warn('Access token or refresh token is invalid or expired. '); + const accessStore = useAccessStore(); + const authStore = useAuthStore(); + accessStore.setAccessToken(null); + if (preferences.app.loginExpiredMode === 'modal' && accessStore.isAccessChecked) { + accessStore.setLoginExpired(true); + } else { + await authStore.logout(); + } + } + + /** + * 刷新token逻辑 + */ + async function doRefreshToken() { + const accessStore = useAccessStore(); + const resp = await refreshTokenApi(); + const newToken = resp.data; + accessStore.setAccessToken(newToken); + return newToken; + } + + function formatToken(token: null | string) { + return token ? `${token}` : null; + } + + // 请求头处理 + client.addRequestInterceptor({ + fulfilled: async (config) => { + const accessStore = useAccessStore(); + + config.headers.Token = formatToken(accessStore.accessToken); + config.headers['Accept-Language'] = preferences.app.locale; + return config; + }, + }); + + // 处理返回的响应数据格式 + client.addResponseInterceptor( + defaultResponseInterceptor({ + codeField: 'code', + dataField: 'data', + successCode: 0, + }), + ); + + // token过期的处理 + client.addResponseInterceptor( + authenticateResponseInterceptor({ + client, + doReAuthenticate, + doRefreshToken, + enableRefreshToken: preferences.app.enableRefreshToken, + formatToken, + }), + ); + + // 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里 + client.addResponseInterceptor( + errorMessageResponseInterceptor((msg: string, error) => { + // 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg + // 当前mock接口返回的错误字段是 error 或者 message + const responseData = error?.response?.data ?? {}; + const errorMessage = responseData?.error ?? responseData?.message ?? ''; + // 如果没有错误信息,则会根据状态码进行提示 + message.error(errorMessage || msg); + }), + ); + + return client; +} + +export const defaultRequestClient = createRequestClient(apiURL, { + responseReturn: 'data', +}); + +export const baseRequestClient = new RequestClient({ baseURL: apiURL }); diff --git a/apps/finance/src/api/statistics/index.ts b/apps/finance/src/api/statistics/index.ts index a31d7dc..7206ae3 100644 --- a/apps/finance/src/api/statistics/index.ts +++ b/apps/finance/src/api/statistics/index.ts @@ -1,3 +1,4 @@ +import { defaultRequestClient } from '#/api/defaultRequest'; import { requestClient } from '#/api/request'; export const statisticsApi = { @@ -58,10 +59,62 @@ export const statisticsApi = { /** * 下载天医币报表 + * @param data 请求参数 + * @param data.month 月份 + * @param data.year 年份 + * @returns 天医币报表数据 */ - downloadReportTianyibi: (data: { date: string }) => { - return requestClient.post('/common/import/getImportFile', data, { - responseType: 'blob', + downloadReportTianyibi: (data: { month?: string; year: number }) => { + return defaultRequestClient.download('common/statistics/pointInfoExport', { + data, + }); + }, + /** + * 下载实物报表 + * @param data 请求参数 + * @param data.month 月份 + * @param data.year 年份 + * @returns 实物报表数据 + */ + downloadReportPhysical: (data: { month?: string; year: number }) => { + return defaultRequestClient.download('common/statistics/physicalInfoExport', { + data, + }); + }, + /** + * 下载培训班报表 + * @param data 请求参数 + * @param data.month 月份 + * @param data.year 年份 + * @returns 培训班报表数据 + */ + downloadReportTrainingClass: (data: { month?: string; year: number }) => { + return defaultRequestClient.download('common/statistics/trainingClassInfoExport', { + data, + }); + }, + /** + * 下载VIP报表 + * @param data 请求参数 + * @param data.month 月份 + * @param data.year 年份 + * @returns VIP报表数据 + */ + downloadReportVip: (data: { month?: string; year: number }) => { + return defaultRequestClient.download('common/statistics/vipInfoExport', { + data, + }); + }, + /** + * 下载课程报表 + * @param data 请求参数 + * @param data.month 月份 + * @param data.year 年份 + * @returns 课程报表数据 + */ + downloadReportCourse: (data: { month?: string; year: number }) => { + return defaultRequestClient.download('common/statistics/courseInfoExport', { + data, }); }, }; diff --git a/apps/finance/src/views/posting/tianyibiOrders/index.vue b/apps/finance/src/views/posting/tianyibiOrders/index.vue index 67d6724..9d38b5f 100644 --- a/apps/finance/src/views/posting/tianyibiOrders/index.vue +++ b/apps/finance/src/views/posting/tianyibiOrders/index.vue @@ -2,7 +2,7 @@ import type { VbenFormProps } from '#/adapter/form'; import type { VxeTableGridOptions } from '#/adapter/vxe-table'; -import { Page } from '@vben/common-ui'; +import { Page, SubmitButton } from '@vben/common-ui'; import { Button, message, notification } from 'ant-design-vue'; @@ -172,11 +172,11 @@ const [Grid, gridApi] = useVbenVxeGrid({ }); async function onStartAutoMatch() { - const hide = message.loading('系统自动匹配消耗中...', 0); + const hide = message.loading('系统自动匹配天医币消耗中...', 0); await tianyibiApi.autoConsumeTianyibi(); hide(); notification.success({ - message: '自动匹配消耗成功', + message: '自动匹配天医币消耗成功', }); // 刷新表格数据 gridApi?.query(); @@ -198,7 +198,8 @@ async function onConsumption(row: RowType, code: number) {