|
|
@@ -0,0 +1,421 @@
|
|
|
+/**
|
|
|
+ * 生命周期管理器
|
|
|
+ * @fileoverview 处理跨页选择的生命周期管理和状态同步
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * 生命周期管理器类
|
|
|
+ * 负责管理组件生命周期中的选择状态保存和恢复
|
|
|
+ */
|
|
|
+class LifecycleManager {
|
|
|
+ constructor(selectionManager, componentInstance) {
|
|
|
+ this.selectionManager = selectionManager;
|
|
|
+ this.component = componentInstance;
|
|
|
+
|
|
|
+ // 生命周期状态跟踪
|
|
|
+ this.currentState = 'idle'; // idle, page-changing, loading, exporting
|
|
|
+ this.lastPageNumber = 1;
|
|
|
+
|
|
|
+ // 性能优化
|
|
|
+ this.debounceTimers = new Map();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 页面变化前的处理
|
|
|
+ * @param {number} newPage 新页码
|
|
|
+ */
|
|
|
+ onPageChange(newPage) {
|
|
|
+ if (this.currentState === 'page-changing') {
|
|
|
+ console.warn('LifecycleManager: 页面正在切换中,忽略重复操作');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ this.currentState = 'page-changing';
|
|
|
+
|
|
|
+ // 1. 保存当前页的选择状态
|
|
|
+ this.saveCurrentPageSelection();
|
|
|
+
|
|
|
+ // 2. 更新选择元数据(记录在哪一页选择的)
|
|
|
+ this.updateSelectionPageInfo(newPage);
|
|
|
+
|
|
|
+ // 3. 清理过期数据
|
|
|
+ this.cleanupExpiredData();
|
|
|
+
|
|
|
+ console.log(`LifecycleManager: 页面切换准备完成 ${this.lastPageNumber} -> ${newPage}`);
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('LifecycleManager: 页面切换处理失败', error);
|
|
|
+ } finally {
|
|
|
+ this.lastPageNumber = newPage;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 页面数据加载完成后的处理
|
|
|
+ * @param {Array} pageData 页面数据
|
|
|
+ */
|
|
|
+ onPageDataLoaded(pageData) {
|
|
|
+ if (this.currentState !== 'page-changing' && this.currentState !== 'loading') {
|
|
|
+ console.warn('LifecycleManager: 非预期状态下调用页面数据加载处理');
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ this.currentState = 'loading';
|
|
|
+
|
|
|
+ // 1. 延迟恢复选择状态,确保DOM渲染完成
|
|
|
+ this.debounceAction('restoreSelection', () => {
|
|
|
+ this.restoreSelectionState(pageData);
|
|
|
+ }, 100);
|
|
|
+
|
|
|
+ // 2. 更新组件UI状态
|
|
|
+ this.updateComponentUI();
|
|
|
+
|
|
|
+ console.log(`LifecycleManager: 页面数据加载处理完成,共 ${pageData.length} 条数据`);
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('LifecycleManager: 页面数据加载处理失败', error);
|
|
|
+ } finally {
|
|
|
+ // 延迟重置状态,确保恢复操作完成
|
|
|
+ setTimeout(() => {
|
|
|
+ this.currentState = 'idle';
|
|
|
+ }, 200);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 导出前的处理
|
|
|
+ */
|
|
|
+ beforeExport() {
|
|
|
+ if (this.currentState === 'exporting') {
|
|
|
+ console.warn('LifecycleManager: 正在导出中,忽略重复操作');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ this.currentState = 'exporting';
|
|
|
+
|
|
|
+ // 1. 验证选择数据
|
|
|
+ const validation = this.selectionManager.validateSelections();
|
|
|
+ if (!validation.isValid) {
|
|
|
+ console.warn('LifecycleManager: 选择数据验证失败', validation.issues);
|
|
|
+ // 继续执行,但记录警告
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 获取导出数据
|
|
|
+ const exportData = this.selectionManager.getAllSelections();
|
|
|
+
|
|
|
+ if (exportData.length === 0) {
|
|
|
+ console.warn('LifecycleManager: 没有选中任何订单');
|
|
|
+ this.currentState = 'idle';
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 检查数据量限制
|
|
|
+ if (exportData.length > this.selectionManager.MAX_SELECTIONS) {
|
|
|
+ console.error(`LifecycleManager: 选择数量超出限制 ${exportData.length} > ${this.selectionManager.MAX_SELECTIONS}`);
|
|
|
+ this.currentState = 'idle';
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log(`LifecycleManager: 导出准备完成,将导出 ${exportData.length} 个订单`);
|
|
|
+ return exportData;
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('LifecycleManager: 导出前处理失败', error);
|
|
|
+ this.currentState = 'idle';
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 导出完成后的处理
|
|
|
+ * @param {boolean} success 导出是否成功
|
|
|
+ */
|
|
|
+ afterExport(success) {
|
|
|
+ try {
|
|
|
+ if (success) {
|
|
|
+ // 1. 清空所有选择
|
|
|
+ const clearedCount = this.selectionManager.clearAllSelections();
|
|
|
+ console.log(`LifecycleManager: 导出成功,已清理 ${clearedCount} 个选择`);
|
|
|
+
|
|
|
+ // 2. 重置组件状态
|
|
|
+ this.resetComponentState();
|
|
|
+
|
|
|
+ // 3. 显示成功提示
|
|
|
+ this.showSuccessMessage(clearedCount);
|
|
|
+ } else {
|
|
|
+ console.warn('LifecycleManager: 导出失败,保持选择状态');
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('LifecycleManager: 导出后处理失败', error);
|
|
|
+ } finally {
|
|
|
+ this.currentState = 'idle';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 组件销毁时的处理
|
|
|
+ */
|
|
|
+ onComponentDestroy() {
|
|
|
+ try {
|
|
|
+ // 1. 清理所有定时器
|
|
|
+ this.clearAllDebounceTimers();
|
|
|
+
|
|
|
+ // 2. 保存当前选择状态(可选,根据需求决定)
|
|
|
+ // this.saveCurrentPageSelection();
|
|
|
+
|
|
|
+ // 3. 清理选择管理器数据
|
|
|
+ this.selectionManager.clearAllSelections();
|
|
|
+
|
|
|
+ // 4. 清理组件引用
|
|
|
+ this.component = null;
|
|
|
+
|
|
|
+ console.log('LifecycleManager: 组件销毁处理完成');
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('LifecycleManager: 组件销毁处理失败', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存当前页选择状态
|
|
|
+ */
|
|
|
+ saveCurrentPageSelection() {
|
|
|
+ if (!this.component || !this.component.selectionList) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const currentSelection = this.component.selectionList;
|
|
|
+ this.selectionManager.mergeWithCurrentPage(currentSelection);
|
|
|
+
|
|
|
+ console.log(`LifecycleManager: 已保存当前页 ${currentSelection.length} 个选择`);
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('LifecycleManager: 保存当前页选择失败', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新选择页面信息
|
|
|
+ * @param {number} pageNumber 页码
|
|
|
+ */
|
|
|
+ updateSelectionPageInfo(pageNumber) {
|
|
|
+ try {
|
|
|
+ const currentPageIds = this.selectionManager.currentPageSelections;
|
|
|
+
|
|
|
+ currentPageIds.forEach(orderId => {
|
|
|
+ this.selectionManager.updateSelectionMeta(orderId, {
|
|
|
+ selectedPage: pageNumber
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('LifecycleManager: 更新选择页面信息失败', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 恢复选择状态
|
|
|
+ * @param {Array} pageData 页面数据
|
|
|
+ */
|
|
|
+ restoreSelectionState(pageData) {
|
|
|
+ if (!this.component || !this.component.$refs || !this.component.$refs.crud) {
|
|
|
+ console.warn('LifecycleManager: 组件引用不完整,无法恢复选择状态');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 1. 找出当前页面中被选中的订单
|
|
|
+ const selectedInPage = this.selectionManager.restorePageSelection(pageData);
|
|
|
+
|
|
|
+ if (selectedInPage.length === 0) {
|
|
|
+ console.log('LifecycleManager: 当前页面没有需要恢复的选择');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 通过avue-crud设置选择状态
|
|
|
+ this.component.$nextTick(() => {
|
|
|
+ try {
|
|
|
+ const crudRef = this.component.$refs.crud;
|
|
|
+
|
|
|
+ // 查找对应的数据行
|
|
|
+ const selectedRows = pageData.filter(row => selectedInPage.includes(row.id));
|
|
|
+
|
|
|
+ // 设置选择状态
|
|
|
+ selectedRows.forEach(row => {
|
|
|
+ crudRef.toggleRowSelection(row, true);
|
|
|
+ });
|
|
|
+
|
|
|
+ console.log(`LifecycleManager: 已恢复 ${selectedRows.length} 个选择状态`);
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('LifecycleManager: 设置avue-crud选择状态失败', error);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('LifecycleManager: 恢复选择状态失败', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新组件UI状态
|
|
|
+ */
|
|
|
+ updateComponentUI() {
|
|
|
+ if (!this.component) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 更新选择计数
|
|
|
+ this.component.selectionCount = this.selectionManager.getSelectionCount();
|
|
|
+
|
|
|
+ // 更新清空按钮显示状态
|
|
|
+ this.component.showClearButton = this.component.selectionCount > 0;
|
|
|
+
|
|
|
+ // 触发组件重新渲染
|
|
|
+ this.component.$forceUpdate();
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('LifecycleManager: 更新组件UI失败', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 重置组件状态
|
|
|
+ */
|
|
|
+ resetComponentState() {
|
|
|
+ if (!this.component) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 重置选择相关数据
|
|
|
+ this.component.selectionList = [];
|
|
|
+ this.component.selectionCount = 0;
|
|
|
+ this.component.showClearButton = false;
|
|
|
+
|
|
|
+ // 清除avue-crud的选择状态
|
|
|
+ if (this.component.$refs && this.component.$refs.crud) {
|
|
|
+ this.component.$refs.crud.clearSelection();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 触发重新渲染
|
|
|
+ this.component.$forceUpdate();
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('LifecycleManager: 重置组件状态失败', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清理过期数据
|
|
|
+ */
|
|
|
+ cleanupExpiredData() {
|
|
|
+ try {
|
|
|
+ const cleanedCount = this.selectionManager.autoCleanup();
|
|
|
+ if (cleanedCount > 0) {
|
|
|
+ console.log(`LifecycleManager: 已清理 ${cleanedCount} 个过期选择`);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('LifecycleManager: 清理过期数据失败', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 显示成功提示
|
|
|
+ * @param {number} count 导出数量
|
|
|
+ */
|
|
|
+ showSuccessMessage(count) {
|
|
|
+ if (this.component && this.component.$message) {
|
|
|
+ this.component.$message.success(`成功导出 ${count} 个订单,已清空选择状态`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 防抖操作
|
|
|
+ * @param {string} key 操作键
|
|
|
+ * @param {Function} action 操作函数
|
|
|
+ * @param {number} delay 延迟时间(毫秒)
|
|
|
+ */
|
|
|
+ debounceAction(key, action, delay = 100) {
|
|
|
+ // 清除之前的定时器
|
|
|
+ if (this.debounceTimers.has(key)) {
|
|
|
+ clearTimeout(this.debounceTimers.get(key));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置新的定时器
|
|
|
+ const timer = setTimeout(() => {
|
|
|
+ try {
|
|
|
+ action();
|
|
|
+ } catch (error) {
|
|
|
+ console.error(`LifecycleManager: 防抖操作 ${key} 执行失败`, error);
|
|
|
+ } finally {
|
|
|
+ this.debounceTimers.delete(key);
|
|
|
+ }
|
|
|
+ }, delay);
|
|
|
+
|
|
|
+ this.debounceTimers.set(key, timer);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清理所有防抖定时器
|
|
|
+ */
|
|
|
+ clearAllDebounceTimers() {
|
|
|
+ this.debounceTimers.forEach((timer, key) => {
|
|
|
+ clearTimeout(timer);
|
|
|
+ });
|
|
|
+ this.debounceTimers.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前状态
|
|
|
+ */
|
|
|
+ getCurrentState() {
|
|
|
+ return {
|
|
|
+ currentState: this.currentState,
|
|
|
+ lastPageNumber: this.lastPageNumber,
|
|
|
+ selectionCount: this.selectionManager.getSelectionCount(),
|
|
|
+ activeTimers: this.debounceTimers.size
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 健康检查
|
|
|
+ */
|
|
|
+ healthCheck() {
|
|
|
+ const issues = [];
|
|
|
+
|
|
|
+ // 检查选择管理器
|
|
|
+ if (!this.selectionManager) {
|
|
|
+ issues.push('缺少选择管理器引用');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查组件引用
|
|
|
+ if (!this.component) {
|
|
|
+ issues.push('缺少组件引用');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查状态
|
|
|
+ if (!['idle', 'page-changing', 'loading', 'exporting'].includes(this.currentState)) {
|
|
|
+ issues.push(`无效的当前状态: ${this.currentState}`);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查定时器数量
|
|
|
+ if (this.debounceTimers.size > 5) {
|
|
|
+ issues.push(`活跃定时器过多: ${this.debounceTimers.size}`);
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ isHealthy: issues.length === 0,
|
|
|
+ issues: issues,
|
|
|
+ state: this.getCurrentState()
|
|
|
+ };
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 导出类
|
|
|
+export default LifecycleManager;
|