增加导出

This commit is contained in:
zhx 2026-06-04 12:12:12 +08:00
parent 33db3e0ea2
commit 1995f9b078
5 changed files with 232 additions and 39 deletions

View File

@ -212,6 +212,17 @@ export async function getClsGoldRunningWater(params: Record<string, any>) {
});
}
export async function exportClsGoldRunningWater(
params: Record<string, any>,
filename = 'GmGoldRunningWater',
) {
return downloadLegacyExcel(
'/user-wallet/gold/running-water/cls/export',
params,
filename,
);
}
export async function getPurchaseTable(params: Record<string, any>) {
return requestClient.get<LegacyPageResult<Record<string, any>>>(
'/order/purchase/history/page',

View File

@ -43,12 +43,23 @@ export interface LegacyUser {
}>;
}
export interface LegacyBackUserOption {
id: number | string;
loginName?: string;
nickname?: string;
status?: number | string;
}
export async function pageUsers(params: Record<string, any>) {
return requestClient.get<LegacyPageResult<LegacyUser>>('/users', {
params,
});
}
export async function listBackUserOptions() {
return requestClient.get<LegacyBackUserOption[]>('/users/list/combo');
}
export async function switchUserStatus(
id: number | string,
status: number | string,

View File

@ -216,11 +216,14 @@ export async function pageFreightRunningWater(params: Record<string, any>) {
);
}
export async function exportFreightWaters(params: Record<string, any>) {
export async function exportFreightWaters(
params: Record<string, any>,
filename = 'ExportFreightWaters',
) {
return downloadLegacyExcel(
'/freight/running-water/export',
params,
'ExportFreightWaters',
filename,
);
}

View File

@ -21,9 +21,12 @@ import {
} from 'antdv-next';
import dayjs from 'dayjs';
import { submitGmGoldOperation } from '#/api/legacy/gm';
import { getClsGoldRunningWater } from '#/api/legacy/operate';
import { listMembers } from '#/api/legacy/team';
import { pageGmGoldOperation, submitGmGoldOperation } from '#/api/legacy/gm';
import {
exportClsGoldRunningWater,
getClsGoldRunningWater,
} from '#/api/legacy/operate';
import { listBackUserOptions } from '#/api/legacy/system';
import { getUserBaseInfoBySysOriginAccount } from '#/api/legacy/user';
import AccountInput from '#/components/account-input.vue';
import UserProfileLink from '#/views/operate/components/user-profile-link.vue';
@ -56,6 +59,8 @@ const DEFAULT_PAGE_SIZE = 100;
const open = ref(false);
const loading = ref(false);
const loadMoreLoading = ref(false);
const operatorsLoading = ref(false);
const exporting = ref(false);
const submitting = ref(false);
const list = ref<Array<Record<string, any>>>([]);
const notMore = ref(false);
@ -64,7 +69,7 @@ const rangeDate = ref<[string, string] | null>(null);
const operators = ref<Array<Record<string, any>>>([]);
const query = reactive<Record<string, any>>({
backOperationUser: undefined,
backOperationUsers: [],
context: '',
endTime: '',
lastId: '',
@ -103,10 +108,14 @@ const showUsdQuantity = computed(
);
const operatorOptions = computed(() =>
operators.value.map((item) => ({
label: `${item.nickname || item.loginName || item.id} / ${item.loginName || item.id}`,
value: item.id,
})),
operators.value.map((item) => {
const name = item.nickname || item.loginName || item.name || item.id;
const account = item.loginName && item.loginName !== name ? ` / ${item.loginName}` : '';
return {
label: `${name}${account}`,
value: item.id,
};
}),
);
const currentPageList = computed(() => {
@ -259,22 +268,81 @@ function filterOperatorOption(input: string, option: any) {
}
async function loadOperators() {
operators.value = (await listMembers()) || [];
operatorsLoading.value = true;
try {
let backUsers: Array<Record<string, any>> = [];
try {
const result = await listBackUserOptions();
backUsers = Array.isArray(result) ? result : [];
} catch {
backUsers = [];
}
operators.value =
backUsers.length > 0
? normalizeOperators(backUsers)
: await loadRecentGmOperators().catch(() => []);
} finally {
operatorsLoading.value = false;
}
}
async function loadData(reset = false) {
if (loading.value || loadMoreLoading.value) {
return;
}
function normalizeOperators(items: Array<Record<string, any>>) {
const operatorMap = new Map<string, Record<string, any>>();
items.forEach((item) => {
const id = item.id || item.applicantId;
if (!id) {
return;
}
operatorMap.set(String(id), {
id,
loginName: item.loginName,
name: item.name,
nickname: item.nickname || item.applicantName,
status: item.status,
});
});
return [...operatorMap.values()];
}
async function loadRecentGmOperators() {
const result = await pageGmGoldOperation({ cursor: 1, limit: 500 });
return normalizeOperators(result?.records || []);
}
function validateQueryTimeRange() {
if (!query.startTime || !query.endTime) {
message.warning('请选择时间范围');
return;
return false;
}
const startYear = new Date(Number(query.startTime)).getFullYear();
const endYear = new Date(Number(query.endTime)).getFullYear();
if (startYear !== endYear) {
message.warning('不允许跨年查询');
return false;
}
return true;
}
function buildRunningWaterParams() {
const backOperationUsers = Array.isArray(query.backOperationUsers)
? query.backOperationUsers.filter(Boolean).join(',')
: '';
return {
backOperationUsers: backOperationUsers || undefined,
endTime: query.endTime,
queryBackOperationUser: true,
startTime: query.startTime,
type: query.type,
userId: query.userId || undefined,
};
}
async function loadData(reset = false) {
if (loading.value || loadMoreLoading.value) {
return;
}
if (!validateQueryTimeRange()) {
return;
}
@ -294,15 +362,10 @@ async function loadData(reset = false) {
try {
const result = await getClsGoldRunningWater({
backOperationUser: query.backOperationUser || undefined,
...buildRunningWaterParams(),
context: query.context || undefined,
endTime: query.endTime,
lastId: query.lastId || undefined,
limit: query.limit,
queryBackOperationUser: true,
startTime: query.startTime,
type: query.type,
userId: query.userId || undefined,
});
const waters = result?.waters || [];
const nextList = reset ? waters : [...list.value, ...waters];
@ -352,6 +415,21 @@ async function handleSearch() {
await loadData(true);
}
async function handleExport() {
if (exporting.value || !validateQueryTimeRange()) {
return;
}
exporting.value = true;
try {
await exportClsGoldRunningWater(
buildRunningWaterParams(),
`GmGoldRunningWater_${dayjs(Number(query.startTime)).format('YYYYMMDD')}_${dayjs(Number(query.endTime)).format('YYYYMMDD')}`,
);
} finally {
exporting.value = false;
}
}
async function handleSubmit() {
if (!validateForm()) {
return;
@ -420,15 +498,19 @@ void loadData(true);
style="width: 240px"
/>
<Select
v-model:value="query.backOperationUser"
v-model:value="query.backOperationUsers"
allow-clear
mode="multiple"
show-search
max-tag-count="responsive"
placeholder="操作人"
style="width: 220px"
:filter-option="filterOperatorOption"
:loading="operatorsLoading"
:options="operatorOptions"
/>
<Button :loading="loading" type="primary" @click="handleSearch">查询</Button>
<Button :loading="exporting" @click="handleExport">导出Excel</Button>
</div>
<Table

View File

@ -1,9 +1,5 @@
<script lang="ts" setup>
import {
computed,
reactive,
ref,
watch } from 'vue';
import { computed, reactive, ref, watch } from 'vue';
import { Page } from '@vben/common-ui';
import { useAccessStore } from '@vben/stores';
@ -11,10 +7,10 @@ import { useAccessStore } from '@vben/stores';
import {
exportFreightWaters,
pageFreightRunningWater,
} from '#/api/legacy/user';
} from '#/api/legacy/user';
import { listBackUserOptions } from '#/api/legacy/system';
import AccountInput from '#/components/account-input.vue';
import { formatDate,
getAllowedSysOrigins } from '#/views/system/shared';
import { formatDate, getAllowedSysOrigins } from '#/views/system/shared';
import {
Button,
@ -23,7 +19,7 @@ import {
Pagination,
Select,
Table,
message
message,
} from 'antdv-next';
import UserProfileLink from './components/user-profile-link.vue';
@ -50,11 +46,14 @@ const loading = ref(false);
const total = ref(0);
const list = ref<Array<Record<string, any>>>([]);
const exporting = ref(false);
const operatorsLoading = ref(false);
const operators = ref<Array<Record<string, any>>>([]);
const rangeDate = ref<[string, string] | null>(null);
const query = reactive<Record<string, any>>({
acceptUserId: '',
cursor: 1,
createUsers: [],
endTime: '',
limit: 20,
origin: undefined,
@ -76,6 +75,17 @@ const columns = [
{ dataIndex: 'createTime', key: 'createTime', title: '创建时间', width: 180 },
];
const operatorOptions = computed(() =>
operators.value.map((item) => {
const name = item.nickname || item.loginName || item.name || item.id;
const account = item.loginName && item.loginName !== name ? ` / ${item.loginName}` : '';
return {
label: `${name}${account}`,
value: item.id,
};
}),
);
watch(
sysOriginOptions,
(options) => {
@ -103,6 +113,63 @@ watch(
{ immediate: true },
);
function normalizeOperators(items: Array<Record<string, any>>) {
const operatorMap = new Map<string, Record<string, any>>();
items.forEach((item) => {
const id = item.id || item.applicantId;
if (!id) {
return;
}
operatorMap.set(String(id), {
id,
loginName: item.loginName,
name: item.name,
nickname: item.nickname || item.applicantName,
status: item.status,
});
});
return [...operatorMap.values()];
}
function filterOperatorOption(input: string, option: any) {
return String(option?.label || '')
.toLowerCase()
.includes(input.toLowerCase());
}
async function loadOperators() {
operatorsLoading.value = true;
try {
const result = await listBackUserOptions();
operators.value = normalizeOperators(Array.isArray(result) ? result : []);
} catch {
operators.value = [];
} finally {
operatorsLoading.value = false;
}
}
function buildFreightRunningWaterParams(withPage = true) {
const createUsers = Array.isArray(query.createUsers)
? query.createUsers.filter(Boolean).join(',')
: '';
const params: Record<string, any> = {
acceptUserId: query.acceptUserId || undefined,
createUsers: createUsers || undefined,
endTime: query.endTime || undefined,
origin: query.origin || undefined,
queryBackOperationUser: query.queryBackOperationUser,
startTime: query.startTime || undefined,
sysOrigin: query.sysOrigin,
userId: query.userId || undefined,
};
if (withPage) {
params.cursor = query.cursor;
params.limit = query.limit;
}
return params;
}
async function loadData(reset = false) {
if (!query.sysOrigin) {
return;
@ -112,7 +179,7 @@ async function loadData(reset = false) {
}
loading.value = true;
try {
const result = await pageFreightRunningWater({ ...query });
const result = await pageFreightRunningWater(buildFreightRunningWaterParams());
list.value = result.records || [];
total.value = result.total || 0;
} finally {
@ -137,19 +204,26 @@ async function handleExport() {
}
exporting.value = true;
try {
await exportFreightWaters({ ...query });
await exportFreightWaters(
buildFreightRunningWaterParams(false),
`ExportFreightWaters_${query.startTime || 'all'}_${query.endTime || 'all'}`,
);
message.success('导出成功');
} finally {
exporting.value = false;
}
}
void loadOperators();
void loadData(true);
</script>
<template>
<Page v-if="!queryBackOperation" title="货运代理流水">
<Card>
<component
:is="queryBackOperation ? 'div' : Page"
:title="queryBackOperation ? undefined : '货运代理流水'"
>
<component :is="queryBackOperation ? 'div' : Card">
<div class="toolbar">
<SysOriginSelect
v-model:value="query.sysOrigin"
@ -175,9 +249,21 @@ void loadData(true);
allow-clear
placeholder="来源"
style="width: 140px"
:options="FREIGHT_BALANCE_ORIGIN_OPTIONS.map((item) => ({ label: `${item.name}`, value: item.value as any }))"
/>
<Select
v-model:value="query.createUsers"
allow-clear
mode="multiple"
show-search
max-tag-count="responsive"
option-label-prop="label"
placeholder="操作人"
style="width: 220px"
:filter-option="filterOperatorOption"
:loading="operatorsLoading"
:options="operatorOptions"
/>
<DatePicker.RangePicker
v-model:value="rangeDate"
show-time
@ -234,8 +320,8 @@ void loadData(true);
@showSizeChange="handlePageChange"
/>
</div>
</Card>
</Page>
</component>
</component>
</template>
<style scoped>