no message
							parent
							
								
									ba2c7f819b
								
							
						
					
					
						commit
						316d40908d
					
				| 
						 | 
					@ -62,8 +62,8 @@ export const itemApi = {
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 导出  @author  hj
 | 
					     * 导出  @author  hj
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    exportItems: () => {
 | 
					    exportItems: (taskId: string) => {
 | 
				
			||||||
        return getDownload('/item/exportItems',{});
 | 
					        return getDownload(`/item/exportItems/${taskId}`,{});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,6 +56,7 @@
 | 
				
			||||||
          </template>
 | 
					          </template>
 | 
				
			||||||
          导入
 | 
					          导入
 | 
				
			||||||
        </a-button>
 | 
					        </a-button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <a-modal
 | 
					        <a-modal
 | 
				
			||||||
            v-model:open="open"
 | 
					            v-model:open="open"
 | 
				
			||||||
            @cancel="onClose"
 | 
					            @cancel="onClose"
 | 
				
			||||||
| 
						 | 
					@ -69,7 +70,7 @@
 | 
				
			||||||
          <template #title>
 | 
					          <template #title>
 | 
				
			||||||
            <span style="display: inline-flex; align-items: center">
 | 
					            <span style="display: inline-flex; align-items: center">
 | 
				
			||||||
            <LoadingOutlined style="margin-right: 8px"/>
 | 
					            <LoadingOutlined style="margin-right: 8px"/>
 | 
				
			||||||
            {{progressTitle}}
 | 
					            {{ progressTitle }}
 | 
				
			||||||
            </span>
 | 
					            </span>
 | 
				
			||||||
          </template>
 | 
					          </template>
 | 
				
			||||||
          <template #footer>
 | 
					          <template #footer>
 | 
				
			||||||
| 
						 | 
					@ -193,7 +194,7 @@
 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import {reactive, ref, onMounted} from 'vue';
 | 
					import {reactive, ref, onMounted} from 'vue';
 | 
				
			||||||
import {message, Modal, UploadFile} from 'ant-design-vue';
 | 
					import {message, Modal, UploadFile} from 'ant-design-vue';
 | 
				
			||||||
import { LoadingOutlined  } from '@ant-design/icons-vue';
 | 
					import {LoadingOutlined} from '@ant-design/icons-vue';
 | 
				
			||||||
import {SmartLoading} from '/@/components/framework/smart-loading';
 | 
					import {SmartLoading} from '/@/components/framework/smart-loading';
 | 
				
			||||||
import {addressApi} from '/@/api/business/wms/base/address/address-api';
 | 
					import {addressApi} from '/@/api/business/wms/base/address/address-api';
 | 
				
			||||||
import {PAGE_SIZE_OPTIONS} from '/@/constants/common-const';
 | 
					import {PAGE_SIZE_OPTIONS} from '/@/constants/common-const';
 | 
				
			||||||
| 
						 | 
					@ -449,6 +450,7 @@ const currentTaskId = ref('');//当前任务ID
 | 
				
			||||||
const open = ref<boolean>(false);//显示模态框
 | 
					const open = ref<boolean>(false);//显示模态框
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const onExportAddress = async () => {
 | 
					const onExportAddress = async () => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    open.value = true;
 | 
					    open.value = true;
 | 
				
			||||||
    //获取导出任务ID
 | 
					    //获取导出任务ID
 | 
				
			||||||
| 
						 | 
					@ -456,17 +458,12 @@ const onExportAddress = async () => {
 | 
				
			||||||
    currentTaskId.value = taskId;
 | 
					    currentTaskId.value = taskId;
 | 
				
			||||||
    progressStatus.value = 'active';
 | 
					    progressStatus.value = 'active';
 | 
				
			||||||
    //导出
 | 
					    //导出
 | 
				
			||||||
    addressApi.exportAddress(currentTaskId.value);
 | 
					    await addressApi.exportAddress(currentTaskId.value);
 | 
				
			||||||
    // 启动轮询
 | 
					    // 启动轮询
 | 
				
			||||||
    const timer = setInterval(async () => {
 | 
					    const timer = setInterval(async () => {
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
        //获取当前任务的进度条
 | 
					        //获取当前任务的进度条
 | 
				
			||||||
        const {data: progress} = await addressApi.getExportProgress(currentTaskId.value);
 | 
					        const {data: progress} = await addressApi.getExportProgress(currentTaskId.value);
 | 
				
			||||||
        if (progress === -1) {
 | 
					 | 
				
			||||||
          clearInterval(timer);
 | 
					 | 
				
			||||||
          progressStatus.value = 'exception';
 | 
					 | 
				
			||||||
          return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        progressPercent.value = progress;
 | 
					        progressPercent.value = progress;
 | 
				
			||||||
        if (progress >= 100) {
 | 
					        if (progress >= 100) {
 | 
				
			||||||
          clearInterval(timer);
 | 
					          clearInterval(timer);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,8 @@
 | 
				
			||||||
        <ItemSelect v-model:value="queryForm.itemId" :disabledFlag="true" @change="onSearch"/>
 | 
					        <ItemSelect v-model:value="queryForm.itemId" :disabledFlag="true" @change="onSearch"/>
 | 
				
			||||||
      </a-form-item>
 | 
					      </a-form-item>
 | 
				
			||||||
      <a-form-item label="是否启用" class="smart-query-form-item">
 | 
					      <a-form-item label="是否启用" class="smart-query-form-item">
 | 
				
			||||||
        <a-select style="width: 200px" v-model:value="queryForm.disabledFlag" allowClear placeholder="请选择" @change="onSearch">
 | 
					        <a-select style="width: 200px" v-model:value="queryForm.disabledFlag" allowClear placeholder="请选择"
 | 
				
			||||||
 | 
					                  @change="onSearch">
 | 
				
			||||||
          <a-select-option :value="true">启用</a-select-option>
 | 
					          <a-select-option :value="true">启用</a-select-option>
 | 
				
			||||||
          <a-select-option :value="false">禁用</a-select-option>
 | 
					          <a-select-option :value="false">禁用</a-select-option>
 | 
				
			||||||
        </a-select>
 | 
					        </a-select>
 | 
				
			||||||
| 
						 | 
					@ -62,6 +63,28 @@
 | 
				
			||||||
          导入
 | 
					          导入
 | 
				
			||||||
        </a-button>
 | 
					        </a-button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <a-modal
 | 
				
			||||||
 | 
					            v-model:open="open"
 | 
				
			||||||
 | 
					            @cancel="onClose"
 | 
				
			||||||
 | 
					            :closable="false"
 | 
				
			||||||
 | 
					            :maskClosable="false"
 | 
				
			||||||
 | 
					            :destroyOnClose="true">
 | 
				
			||||||
 | 
					          <a-progress
 | 
				
			||||||
 | 
					              :percent="progressPercent"
 | 
				
			||||||
 | 
					              :status="progressStatus"
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					          <template #title>
 | 
				
			||||||
 | 
					            <span style="display: inline-flex; align-items: center">
 | 
				
			||||||
 | 
					            <LoadingOutlined style="margin-right: 8px"/>
 | 
				
			||||||
 | 
					            {{ progressTitle }}
 | 
				
			||||||
 | 
					            </span>
 | 
				
			||||||
 | 
					          </template>
 | 
				
			||||||
 | 
					          <template #footer>
 | 
				
			||||||
 | 
					            <a-space>
 | 
				
			||||||
 | 
					              <a-button @click="onClose">关闭</a-button>
 | 
				
			||||||
 | 
					            </a-space>
 | 
				
			||||||
 | 
					          </template>
 | 
				
			||||||
 | 
					        </a-modal>
 | 
				
			||||||
        <a-button @click="onExportItems" type="primary" v-privilege="'item:exportItems'">
 | 
					        <a-button @click="onExportItems" type="primary" v-privilege="'item:exportItems'">
 | 
				
			||||||
          <template #icon>
 | 
					          <template #icon>
 | 
				
			||||||
            <ExportOutlined/>
 | 
					            <ExportOutlined/>
 | 
				
			||||||
| 
						 | 
					@ -190,6 +213,8 @@ import ItemSelect from "/@/views/business/wms/base/item/item-select.vue";
 | 
				
			||||||
import {UploadFile} from 'ant-design-vue';
 | 
					import {UploadFile} from 'ant-design-vue';
 | 
				
			||||||
import {fileApi} from "/@/api/support/file-api";
 | 
					import {fileApi} from "/@/api/support/file-api";
 | 
				
			||||||
import DictLabel from "/@/components/support/dict-label/index.vue";
 | 
					import DictLabel from "/@/components/support/dict-label/index.vue";
 | 
				
			||||||
 | 
					import {addressApi} from "/@/api/business/wms/base/address/address-api";
 | 
				
			||||||
 | 
					import {LoadingOutlined} from "@ant-design/icons-vue";
 | 
				
			||||||
// ---------------------------- 表格列 ----------------------------
 | 
					// ---------------------------- 表格列 ----------------------------
 | 
				
			||||||
let columns = ref([
 | 
					let columns = ref([
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
| 
						 | 
					@ -473,9 +498,97 @@ async function onImportItems() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//导出
 | 
					//导出
 | 
				
			||||||
function onExportItems() {
 | 
					const progressTitle = ref('文件下载中,请稍等...');
 | 
				
			||||||
  itemApi.exportItems();
 | 
					const progressPercent = ref(0);
 | 
				
			||||||
}
 | 
					const progressStatus = ref('active');
 | 
				
			||||||
 | 
					const currentTaskId = ref('');
 | 
				
			||||||
 | 
					const open = ref(false);
 | 
				
			||||||
 | 
					const pollTimer = ref<NodeJS.Timeout>(); // 使用ref保存定时器引用
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 重置所有进度状态
 | 
				
			||||||
 | 
					const resetProgress = () => {
 | 
				
			||||||
 | 
					  progressPercent.value = 0;
 | 
				
			||||||
 | 
					  progressStatus.value = 'active';
 | 
				
			||||||
 | 
					  progressTitle.value = '文件下载中,请稍等...';
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 轮询检查进度
 | 
				
			||||||
 | 
					const startProgressPolling = async (taskId: string) => {
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    // 启动轮询(调整为更合理的1秒间隔)
 | 
				
			||||||
 | 
					    pollTimer.value = setInterval(async () => {
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        const { data: progress } = await addressApi.getExportProgress(taskId);
 | 
				
			||||||
 | 
					        progressPercent.value = progress;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (progress >= 100) {
 | 
				
			||||||
 | 
					          handleComplete();
 | 
				
			||||||
 | 
					          clearInterval(pollTimer.value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } catch (error) {
 | 
				
			||||||
 | 
					        handlePollingError();
 | 
				
			||||||
 | 
					        clearInterval(pollTimer.value);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }, 200); // 调整为1秒减少请求压力
 | 
				
			||||||
 | 
					  } catch (error) {
 | 
				
			||||||
 | 
					    handlePollingError();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 处理完成状态
 | 
				
			||||||
 | 
					const handleComplete = () => {
 | 
				
			||||||
 | 
					  progressStatus.value = 'success';
 | 
				
			||||||
 | 
					  progressTitle.value = '文件下载完成';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // 立即关闭模态框,使用提示告知用户
 | 
				
			||||||
 | 
					  open.value = false;
 | 
				
			||||||
 | 
					  resetProgress();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 处理轮询错误
 | 
				
			||||||
 | 
					const handlePollingError = () => {
 | 
				
			||||||
 | 
					  progressStatus.value = 'exception';
 | 
				
			||||||
 | 
					  progressPercent.value = 0;
 | 
				
			||||||
 | 
					  progressTitle.value = '获取进度失败';
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const onExportItems = async () => {
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    // 清除已有定时器防止重复请求
 | 
				
			||||||
 | 
					    if (pollTimer.value) clearInterval(pollTimer.value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 重置状态(包括清除旧任务ID)
 | 
				
			||||||
 | 
					    resetProgress();
 | 
				
			||||||
 | 
					    currentTaskId.value = '';
 | 
				
			||||||
 | 
					    open.value = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 获取任务ID
 | 
				
			||||||
 | 
					    const { data: taskId } = await addressApi.createExportTask();
 | 
				
			||||||
 | 
					    currentTaskId.value = taskId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 启动导出(添加超时处理)
 | 
				
			||||||
 | 
					    await Promise.race([
 | 
				
			||||||
 | 
					      itemApi.exportItems(taskId),
 | 
				
			||||||
 | 
					      new Promise((_, reject) =>
 | 
				
			||||||
 | 
					          setTimeout(() => reject(new Error('导出超时')), 30_000)
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 开始轮询进度
 | 
				
			||||||
 | 
					    await startProgressPolling(taskId);
 | 
				
			||||||
 | 
					  } catch (error: any) {
 | 
				
			||||||
 | 
					    open.value = false;
 | 
				
			||||||
 | 
					    message.error('导出失败: ' + error.message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 异常时清除定时器
 | 
				
			||||||
 | 
					    if (pollTimer.value) clearInterval(pollTimer.value);
 | 
				
			||||||
 | 
					    resetProgress();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const onClose = () => {
 | 
				
			||||||
 | 
					  resetProgress();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(queryData);
 | 
					onMounted(queryData);
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue