实现 下拉滚动加载分页数据、导出动态加载进度条显示
parent
9b61dab6c6
commit
ffdf0aaf71
|
|
@ -59,11 +59,20 @@ export const addressApi = {
|
||||||
return postRequest('/address/importAddress', file);
|
return postRequest('/address/importAddress', file);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
createExportTask: () => {
|
||||||
|
return postRequest('/address/createExportTask', {});
|
||||||
|
},
|
||||||
|
|
||||||
|
getExportProgress: (taskId: string) => {
|
||||||
|
return getRequest(`/address/progress/${taskId}`, {});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出 @author hj
|
* 导出 @author hj
|
||||||
*/
|
*/
|
||||||
exportAddress: () => {
|
exportAddress: (taskId: string) => {
|
||||||
return getDownload('/address/exportAddress', {});
|
return getDownload(`/address/exportAddress/${taskId}`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,12 @@
|
||||||
</template>
|
</template>
|
||||||
导入
|
导入
|
||||||
</a-button>
|
</a-button>
|
||||||
|
<a-modal v-model:open="open" :title="progressTitle" :maskClosable="false" :footer="null">
|
||||||
|
<a-progress
|
||||||
|
:percent="progressPercent"
|
||||||
|
:status="progressStatus"
|
||||||
|
/>
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
<a-button @click="onExportAddress" type="primary" v-privilege="'address:exportAddress'">
|
<a-button @click="onExportAddress" type="primary" v-privilege="'address:exportAddress'">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
|
|
@ -79,6 +85,7 @@
|
||||||
bordered
|
bordered
|
||||||
:loading="tableLoading"
|
:loading="tableLoading"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
|
:scroll="{ x: 1500, y: 350 }"
|
||||||
:row-selection="{ selectedRowKeys: selectedRowKeyList, onChange: onSelectChange }"
|
:row-selection="{ selectedRowKeys: selectedRowKeyList, onChange: onSelectChange }"
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ text, record, column }">
|
<template #bodyCell="{ text, record, column }">
|
||||||
|
|
@ -180,7 +187,6 @@ import AddressForm from '/@/views/business/wms/base/address/address-form.vue';
|
||||||
import {TABLE_ID_CONST} from "/@/constants/support/table-id-const";
|
import {TABLE_ID_CONST} from "/@/constants/support/table-id-const";
|
||||||
import AddressSelect from "/@/views/business/wms/base/address/address-select.vue";
|
import AddressSelect from "/@/views/business/wms/base/address/address-select.vue";
|
||||||
import {fileApi} from "/@/api/support/file-api";
|
import {fileApi} from "/@/api/support/file-api";
|
||||||
|
|
||||||
// ---------------------------- 表格配置 ----------------------------
|
// ---------------------------- 表格配置 ----------------------------
|
||||||
// 表格加载loading
|
// 表格加载loading
|
||||||
const tableLoading = ref(false);
|
const tableLoading = ref(false);
|
||||||
|
|
@ -420,9 +426,56 @@ async function onImportAddress() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//导出
|
//导出
|
||||||
function onExportAddress() {
|
const progressTitle = ref('文件导出中,请稍等...');
|
||||||
addressApi.exportAddress();
|
const progressPercent = ref(0);//进度条初始值
|
||||||
|
const progressStatus = ref('active');//进度条状态
|
||||||
|
const currentTaskId = ref('');//当前任务ID
|
||||||
|
const open = ref<boolean>(false);//显示模态框
|
||||||
|
|
||||||
|
const onExportAddress = async () => {
|
||||||
|
try {
|
||||||
|
open.value = true;
|
||||||
|
//获取导出任务ID
|
||||||
|
const {data: taskId} = await addressApi.createExportTask();
|
||||||
|
currentTaskId.value = taskId;
|
||||||
|
progressStatus.value = 'active';
|
||||||
|
//导出
|
||||||
|
addressApi.exportAddress(currentTaskId.value);
|
||||||
|
// 启动轮询
|
||||||
|
const timer = setInterval(async () => {
|
||||||
|
try {
|
||||||
|
//获取当前任务的进度条
|
||||||
|
const {data: progress} = await addressApi.getExportProgress(currentTaskId.value);
|
||||||
|
if (progress === -1) {
|
||||||
|
clearInterval(timer);
|
||||||
|
progressStatus.value = 'exception';
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
progressPercent.value = progress;
|
||||||
|
if (progress >= 100) {
|
||||||
|
clearInterval(timer);
|
||||||
|
progressStatus.value = 'success';
|
||||||
|
progressTitle.value = '文件导出完成';
|
||||||
|
// 1秒后重置状态
|
||||||
|
setTimeout(() => {
|
||||||
|
open.value = false;
|
||||||
|
progressPercent.value = 0;
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
clearInterval(timer);
|
||||||
|
progressStatus.value = 'exception';
|
||||||
|
progressPercent.value = 0;
|
||||||
|
}
|
||||||
|
}, 1000); // 每秒轮询一次
|
||||||
|
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
message.error('导出失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
onMounted(queryData);
|
onMounted(queryData);
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,19 @@
|
||||||
<a-select
|
<a-select
|
||||||
v-model:value="selectValue"
|
v-model:value="selectValue"
|
||||||
:style="`width: ${width}`"
|
:style="`width: ${width}`"
|
||||||
:placeholder="placeholder"
|
:placeholder="props.placeholder"
|
||||||
:showSearch="true"
|
:showSearch="true"
|
||||||
:allowClear="true"
|
:allowClear="true"
|
||||||
:size="size"
|
:size="size"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
|
@search="handleSearch"
|
||||||
|
@popupScroll="handleScroll"
|
||||||
|
@blur="handleBlur"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:mode="multiple ? 'multiple' : undefined"
|
:mode="multiple ? 'multiple' : ''"
|
||||||
optionFilterProp="label"
|
optionFilterProp="label"
|
||||||
|
:loading="loading"
|
||||||
|
>
|
||||||
>
|
>
|
||||||
<a-select-option v-for="address in addressList" :key="address.addressId" :label="address.name">
|
<a-select-option v-for="address in addressList" :key="address.addressId" :label="address.name">
|
||||||
{{ address.name }}
|
{{ address.name }}
|
||||||
|
|
@ -25,7 +30,18 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {onMounted, ref, watch} from 'vue';
|
import {onMounted, ref, watch} from 'vue';
|
||||||
import {addressApi} from "/@/api/business/wms/base/address/address-api";
|
import {addressApi} from "/@/api/business/wms/base/address/address-api";
|
||||||
import {smartSentry} from '/@/lib/smart-sentry';
|
import {debounce} from "lodash";
|
||||||
|
import {smartSentry} from "/@/lib/smart-sentry";
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const page = ref({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
name: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
interface Address {
|
interface Address {
|
||||||
addressId: number;
|
addressId: number;
|
||||||
|
|
@ -33,10 +49,7 @@ interface Address {
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
value: [Number, String, Object, Array],
|
||||||
type: [Number, String, Object, Array],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
width: {
|
width: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '200px',
|
default: '200px',
|
||||||
|
|
@ -57,18 +70,39 @@ const props = defineProps({
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
status: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
disabledFlag: {
|
||||||
|
type: Boolean,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const addressList = ref<Address[]>([]);
|
const addressList = ref<Address[]>([]);
|
||||||
const selectValue = ref(props.modelValue);
|
const selectValue = ref(props.value);
|
||||||
|
|
||||||
async function queryData() {
|
async function queryData(append = false) {
|
||||||
try {
|
try {
|
||||||
const res = await addressApi.queryAddress({});
|
loading.value = true;
|
||||||
addressList.value = res.data;
|
let res = await addressApi.queryAddress({
|
||||||
|
pageNum: page.value.pageNum,
|
||||||
|
pageSize: page.value.pageSize,
|
||||||
|
name: page.value.name
|
||||||
|
});
|
||||||
|
if (append) {
|
||||||
|
addressList.value = [...addressList.value, ...res.data.list];
|
||||||
|
} else {
|
||||||
|
addressList.value = res.data.list;
|
||||||
|
}
|
||||||
|
page.value.total = res.data.total;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
smartSentry.captureError(e);
|
smartSentry.captureError(e);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function querySelectedAddress(value: any) {
|
function querySelectedAddress(value: any) {
|
||||||
|
|
@ -89,9 +123,33 @@ function handleChange(value: any) {
|
||||||
emit('change', selectedAddress);
|
emit('change', selectedAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听modelValue变化
|
//搜索
|
||||||
|
const handleSearch = debounce(async (value: string) => {
|
||||||
|
page.value.name = value;
|
||||||
|
page.value.pageNum = 1;
|
||||||
|
await queryData();
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
//滚动
|
||||||
|
const handleScroll = async (e: Event) => {
|
||||||
|
const {scrollTop, clientHeight, scrollHeight} = e.target as HTMLElement;
|
||||||
|
if (scrollHeight - (scrollTop + clientHeight) < 10 && !loading.value) {
|
||||||
|
if (addressList.value.length < page.value.total) {
|
||||||
|
page.value.pageNum++;
|
||||||
|
await queryData(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//取消焦点重置查询
|
||||||
|
const handleBlur = async () => {
|
||||||
|
page.value.pageNum = 1;
|
||||||
|
await queryData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 箭头value变化
|
||||||
watch(
|
watch(
|
||||||
() => props.modelValue,
|
() => props.value,
|
||||||
(newValue) => {
|
(newValue) => {
|
||||||
selectValue.value = newValue;
|
selectValue.value = newValue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue