当前位置: 首页 > news >正文

【行业树选择器组件:基于Vue3与Element Plus的高性能树形选择组件优化与重构】

行业树选择器组件:基于Vue3与Element Plus的高性能树形选择组件优化与重构

组件概述与背景

行业树选择器是一个基于Element Plus的ElTreeSelect封装的业务组件,主要应用于能源管理系统中,用于展示和选择国标行业分类体系的四级层级结构。该组件位于项目的/src/views/energy-saving-management/key-energy-using/目录中,由多个文件协同工作实现。

功能定位与使用场景

该组件主要用于:

  • 重点用能单位表单中的行业分类选择
  • 能源管理档案中的行业数据展示与编辑
  • 企业分类统计与筛选

开发背景

在能源管理系统中,行业分类是重要的基础数据。国标行业分类采用四级结构(如A-农林牧渔业->A01-农业->A011-谷物种植->A0111-稻谷种植),系统需要一个能清晰展示此层级结构并支持各级选择的组件。

现有实现的不足

  1. 行业树展开问题 - 选择三级行业代码时不能自动展开到正确的层级结构
  2. 代码冗余 - 现有代码中存在大量重复逻辑和条件判断
  3. 错误处理不足 - 在数据加载失败或节点查找失败时缺乏有效的降级策略

技术定位

该组件属于业务组件,基于Element Plus的ElTreeSelect进行封装,并与系统中的行业数据API集成。

设计目标与原则

功能目标

  1. 支持四级行业分类树的展示与选择
  2. 实现行业代码输入与节点自动匹配
  3. 优化展开逻辑,确保选择任一级别的行业代码时都能正确展开其层级结构

性能目标

  1. 减少API调用次数,避免重复加载数据
  2. 优化树节点查找算法
  3. 使用缓存机制提高响应速度

可维护性目标

  1. 减少代码冗余,提高代码质量
  2. 增强错误处理能力
  3. 优化函数结构,明确职责分工

组件设计与API

在表单中的使用

组件在add-modal.vue中的使用方式:

<el-tree-selectv-else-if="item.type === 'tree-select' && item.prop === 'industry'":placeholder="item.rules[0].message"v-model="formData[item.prop]":data="industryTreeData":props="industryTreeProps"node-key="code"check-strictlyvalue-key="code"filterableclearable:default-expanded-keys="expandedKeys":render-after-expand="false"@visible-change="handleTreeVisibleChange"@change="handleIndustryChange"@node-click="handleIndustryNodeClick"
/>

核心数据结构

// 行业树节点数据结构
interface IndustryTreeNode {name: string;       // 行业名称code: string;       // 行业代码value: string;      // 选择值,通常与code相同isLeaf: boolean;    // 是否叶节点children?: IndustryTreeNode[]; // 子节点
}// 树属性定义
const industryTreeProps = {label: 'name',value: 'code',children: 'children',isLeaf: 'isLeaf'
};

组件内部状态

// 行业树数据
const industryTreeData = ref<any[]>([]);
// 当前选中节点
const industrySelectedNode = ref<any>(null);
// 展开的节点键值
const expandedKeys = ref<string[]>([]);
// 树数据缓存
const treeDataCache = ref<any[]>([]);

实现细节与优化对比

1. 行业树初始化

优化前:

// 初始化行业树
async function initIndustryTree() {try {const selectedIndustryCode = formData.value.industry;// 如果已有缓存数据,直接使用if (treeDataCache.value.length > 0) {industryTreeData.value = treeDataCache.value;if (selectedIndustryCode && typeof selectedIndustryCode === 'string') {// 更新展开路径和选中节点updateTreeSelection(selectedIndustryCode);}return;}// 无缓存则加载数据if (selectedIndustryCode && typeof selectedIndustryCode === 'string') {await loadTreeForCode(selectedIndustryCode);return;}const treeData = await loadFullIndustryTree();industryTreeData.value = treeData;treeDataCache.value = treeData; // 缓存数据} catch (error) {console.error('初始化行业树失败', error);industryTreeData.value = [];}
}

优化思路:
此函数主要逻辑是处理行业树的初始化和缓存,不需要进行大幅度修改,但可以抽取重复的数据加载和缓存逻辑到单独的函数中,提高代码可读性。

优化后:

// 加载并缓存树数据
const loadAndCacheTree = async () => {const treeData = await loadFullIndustryTree();industryTreeData.value = treeData;treeDataCache.value = treeData;
};// 初始化行业树
const initIndustryTree = async () => {try {const selectedCode = formData.value.industry;// 有缓存数据时直接使用if (treeDataCache.value.length > 0) {industryTreeData.value = treeDataCache.value;selectedCode && typeof selectedCode === 'string' && updateTreeSelection(selectedCode);return;}// 无缓存时加载数据selectedCode && typeof selectedCode === 'string' ? await initLoadTree(selectedCode) : loadAndCacheTree();} catch (error) {console.error('初始化行业树失败', error);industryTreeData.value = [];}
};

2. 更新树选择状态

优化前:

// 更新树的选中状态和展开路径
function updateTreeSelection(industryCode: string) {if (!industryCode || !treeDataCache.value.length) return;// 获取展开路径const nodePath = getNodePath(treeDataCache.value, industryCode);expandedKeys.value = nodePath;// 更新选中节点updateSelectedIndustryNode(treeDataCache.value, industryCode);
}

优化思路:
该函数逻辑简洁明了,主要关注点应该是getNodePath函数的实现。可以通过添加日志输出增强代码可调试性。

优化后:

// 更新树的选中状态和展开路径
function updateTreeSelection(industryCode: string) {if (!industryCode || !treeDataCache.value.length) return;console.log('更新树选择状态,行业代码:', industryCode);// 获取展开路径const nodePath = getNodePath(treeDataCache.value, industryCode);console.log('获取展开路径结果:', nodePath);if (nodePath && nodePath.length > 0) {// 确保展开路径中的代码都是字符串expandedKeys.value = nodePath.map(code => String(code));console.log('设置展开键值:', expandedKeys.value);} else {console.warn('未能获取展开路径,可能无法正确展示树形结构');}// 更新选中节点updateSelectedIndustryNode(treeDataCache.value, industryCode);
}

3. 加载特定行业代码的树

优化前:

// 加载指定行业代码的节点并设置展开路径
async function loadTreeForCode(industryCode: string) {if (!industryCode) return;try {// 加载完整树数据const treeData = await loadFullIndustryTree();industryTreeData.value = treeData;treeDataCache.value = treeData; // 缓存数据// 更新展开路径和选中节点updateTreeSelection(industryCode);} catch (error) {console.error('加载行业树数据失败:', error);formData.value.industry = industryCode;}
}

优化思路:
此函数可以重用刚才定义的loadAndCacheTree函数,减少代码重复。

优化后:

// 加载指定行业代码的树
const initLoadTree = async (industryCode: string) => {if (!industryCode) return;try {console.log('加载行业树数据,代码:', industryCode);await loadAndCacheTree();updateTreeSelection(industryCode);} catch (error) {console.error('加载行业树数据失败:', error);formData.value.industry = industryCode;}
};

4. 节点路径查找算法

优化前:

// 获取节点的路径,返回节点code数组
export const getNodePath = (tree: any[], code: string): string[] => {if (!code || !tree || !Array.isArray(tree) || tree.length === 0) return [];// 进行前处理,确定行业代码的层级let targetLevel = 0;// 分析行业代码的层级结构if (code.length === 1) {// 一级行业代码,如 'A','B'targetLevel = 1;} else if (code.length === 3) {// 二级行业代码,如 'A01', 'B06'targetLevel = 2;} else if (code.length === 4) {// 三级行业代码,如 'A011', 'C171'targetLevel = 3;} else if (code.length === 5) {// 四级行业代码,如 'C1711'targetLevel = 4;}console.log('目标代码层级:', targetLevel, '代码:', code);// 用于存储路径的数组const path: string[] = [];// 如果是多级代码,先尝试找到父级节点if (targetLevel > 1) {// 获取一级行业代码const firstLevelCode = code.charAt(0);// 查找一级节点const firstLevelNode = tree.find((node) => node.code === firstLevelCode);if (firstLevelNode) {// 添加一级节点到路径path.push(firstLevelCode);if (targetLevel > 2 && firstLevelNode.children) {  // 这里有问题// 获取二级行业代码const secondLevelCode = code.substring(0, 3);// 查找二级节点const secondLevelNode = firstLevelNode.children.find((node) => node.code === secondLevelCode);if (secondLevelNode) {// 添加二级节点到路径path.push(secondLevelCode);if (targetLevel > 3 && secondLevelNode.children) {// 获取三级行业代码const thirdLevelCode = code.substring(0, 4);// 查找三级节点const thirdLevelNode = secondLevelNode.children.find((node) => node.code === thirdLevelCode);if (thirdLevelNode) {// 添加三级节点到路径path.push(thirdLevelCode);// 如果是四级代码,则添加完整代码if (targetLevel === 4) {path.push(code);}}}}}}}// 如果通过层级分析没有找到路径,再尝试递归查找if (path.length === 0) {// 尝试精确匹配查找路径const resultPath: string[] = [];const foundExact = findPathRecursive(tree, code, [], resultPath, true);if (foundExact) {console.log('通过递归找到精确匹配的节点路径:', resultPath);return resultPath;}// 如果精确匹配失败,尝试模糊匹配const fuzzyResultPath: string[] = [];const foundFuzzy = findPathRecursive(tree, code, [], fuzzyResultPath, false);if (foundFuzzy) {console.log('通过递归找到模糊匹配的节点路径:', fuzzyResultPath);return fuzzyResultPath;}} else {console.log('通过层级分析找到节点路径:', path);}// 如果仍然没有找到路径,尝试从目标代码本身构建路径if (path.length === 0 && targetLevel > 1) {console.log('尝试从目标代码本身构建路径');// 一级代码const level1Code = code.charAt(0);path.push(level1Code);// 如果是二级以上代码if (targetLevel >= 2) {const level2Code = code.substring(0, 3);path.push(level2Code);}// 如果是三级以上代码if (targetLevel >= 3) {const level3Code = code.substring(0, 4);path.push(level3Code);}// 如果是四级代码if (targetLevel === 4) {path.push(code);}console.log('从代码本身构建的路径:', path);}return path;
};

优化思路:
这个函数是整个组件的核心,包含了多种查找策略。注意到这里存在一个逻辑错误:对于二级行业代码,条件判断 targetLevel > 2 导致无法进入处理二级代码的分支。我们需要修改条件判断,并将函数重构为更小、更专注的部分。

优化后:

// 获取节点的路径,返回节点code数组
export const getNodePath = (tree: any[], code: string): string[] => {if (!code || !tree?.length) return [];// 确定行业代码的层级const targetLevel = getCodeLevel(code);console.log('目标代码层级:', targetLevel, '代码:', code);// 通过层级分析构建路径const path = buildPathByLevel(tree, code, targetLevel);// 如果层级分析成功找到路径if (path.length > 0) {console.log('通过层级分析找到节点路径:', path);return path;}// 尝试精确匹配查找路径const resultPath: string[] = [];if (findPathRecursive(tree, code, [], resultPath, true)) {console.log('通过递归找到精确匹配的节点路径:', resultPath);return resultPath;}// 如果精确匹配失败,尝试模糊匹配const fuzzyResultPath: string[] = [];if (findPathRecursive(tree, code, [], fuzzyResultPath, false)) {console.log('通过递归找到模糊匹配的节点路径:', fuzzyResultPath);return fuzzyResultPath;}// 所有方法都失败,从代码本身构建路径if (targetLevel > 1) {const fallbackPath = buildFallbackPath(code, targetLevel);console.log('从代码本身构建的路径:', fallbackPath);return fallbackPath;}return [];
};// 根据代码长度确定层级
function getCodeLevel(code: string): number {const codeLength = code.length;if (codeLength === 1) return 1;       // 一级行业代码,如 'A','B'if (codeLength === 3) return 2;       // 二级行业代码,如 'A01', 'B06'if (codeLength === 4) return 3;       // 三级行业代码,如 'A011', 'C171'if (codeLength === 5) return 4;       // 四级行业代码,如 'C1711'return 0;
}// 根据代码层级构建路径
function buildPathByLevel(tree: any[], code: string, targetLevel: number): string[] {const path: string[] = [];if (targetLevel <= 1) return path;// 一级代码const firstLevelCode = code.charAt(0);const firstLevelNode = tree.find(node => node.code === firstLevelCode);if (!firstLevelNode) return path;path.push(firstLevelCode);// 二级代码 - 关键修改if (targetLevel > 1 && firstLevelNode.children?.length) {  // 修改条件判断const secondLevelCode = code.substring(0, 3);const secondLevelNode = firstLevelNode.children.find(node => node.code === secondLevelCode);if (!secondLevelNode) return path;path.push(secondLevelCode);// 三级代码if (targetLevel > 2 && secondLevelNode.children?.length) {const thirdLevelCode = code.substring(0, 4);const thirdLevelNode = secondLevelNode.children.find(node => node.code === thirdLevelCode);if (!thirdLevelNode) return path;path.push(thirdLevelCode);// 四级代码if (targetLevel > 3) {path.push(code);}}}return path;
}// 构建后备路径(当树中找不到节点时)
function buildFallbackPath(code: string, targetLevel: number): string[] {const path: string[] = [];// 一级代码path.push(code.charAt(0));// 二级及以上代码if (targetLevel >= 2) path.push(code.substring(0, 3));// 三级及以上代码if (targetLevel >= 3) path.push(code.substring(0, 4));// 四级代码if (targetLevel === 4) path.push(code);return path;
}

5. 递归查找路径

优化前:

// 递归查找节点路径的辅助函数
const findPathRecursive = (nodes: any[],targetCode: string,currentPath: string[],resultPath: string[],exactMatch: boolean
): boolean => {if (!nodes || !Array.isArray(nodes)) return false;for (const node of nodes) {// 复制当前路径,添加当前节点const tempPath = [...currentPath, node.code];// 检查是否找到目标节点let isTarget = false;if (exactMatch) {// 精确匹配isTarget = node.code === targetCode;} else {// 模糊匹配isTarget =(node.code && targetCode.includes(node.code)) ||(node.code && node.code.includes(targetCode));}// 如果找到目标节点,保存路径并返回成功if (isTarget) {resultPath.push(...tempPath);return true;}// 如果有子节点,递归查找if (node.children && Array.isArray(node.children) && node.children.length > 0) {if (findPathRecursive(node.children, targetCode, tempPath, resultPath, exactMatch)) {return true;}}}return false;
};

优化思路:
简化条件判断,使用更简洁的代码风格。

优化后:

// 递归查找节点路径的辅助函数
const findPathRecursive = (nodes: any[],targetCode: string,currentPath: string[],resultPath: string[],exactMatch: boolean
): boolean => {if (!nodes?.length) return false;for (const node of nodes) {// 添加当前节点到路径const tempPath = [...currentPath, node.code];// 检查是否找到目标节点const isTarget = exactMatch ? node.code === targetCode  // 精确匹配: (node.code && targetCode.includes(node.code)) || (node.code && node.code.includes(targetCode)); // 模糊匹配// 找到目标节点,保存路径并返回成功if (isTarget) {resultPath.push(...tempPath);return true;}// 递归查找子节点if (node.children?.length && findPathRecursive(node.children, targetCode, tempPath, resultPath, exactMatch)) {return true;}}return false;
};

6. 处理树选择器可见性变化

优化前:

// 处理树选择器可见性变化
function handleTreeVisibleChange(visible: boolean) {if (visible && industryTreeData.value.length === 0) {// 仅在首次显示且无数据时加载initIndustryTree();}
}

优化思路:
使用短路求值简化代码。

优化后:

// 处理树选择器可见性变化
const handleTreeVisibleChange = (visible: boolean) => {visible && industryTreeData.value.length === 0 && initIndustryTree();
};

7. 处理行业选择变更

优化前:

// 处理行业树选择变更
function handleIndustryChange(val: any) {console.log('行业选择变更:', val);if (val && typeof val === 'object') {formData.value.industry = val.code || '';industrySelectedNode.value = val;} else if (typeof val === 'string' && val) {formData.value.industry = val;updateIndustrySelectedNodeByCode(val);} else {formData.value.industry = '';industrySelectedNode.value = null;console.log('清空行业选择');}
}

优化思路:
添加自动更新树选择状态的逻辑,确保选择后能正确展开节点。

优化后:

// 处理行业树选择变更
const handleIndustryChange = (val: any) => {console.log('行业选择变更:', val);if (val && typeof val === 'object') {formData.value.industry = val.code || '';industrySelectedNode.value = val;// 如果选择了节点,确保展开到该节点if (val.code) {updateTreeSelection(val.code);}} else if (typeof val === 'string' && val) {formData.value.industry = val;updateIndustrySelectedNodeByCode(val);// 确保展开到该节点updateTreeSelection(val);} else {formData.value.industry = '';industrySelectedNode.value = null;expandedKeys.value = [];}
};

8. 根据行业代码更新选中节点

优化前:

// 根据行业代码更新选中节点
function updateIndustrySelectedNodeByCode(industryCode: string) {if (industryTreeData.value && industryTreeData.value.length > 0) {const node = findNodeByCode(industryTreeData.value, industryCode);if (node) {industrySelectedNode.value = node;console.log('根据代码找到并选中节点:', node);} else {industrySelectedNode.value = { code: industryCode };console.log('未找到节点,保存代码:', industryCode);}} else {industrySelectedNode.value = { code: industryCode };}
}

优化思路:
简化逻辑,减少条件判断和重复代码。

优化后:

// 根据行业代码更新选中节点
const updateIndustrySelectedNodeByCode = (industryCode: string) => {if (!industryTreeData.value?.length) {industrySelectedNode.value = { code: industryCode };return;}const node = findNodeByCode(industryTreeData.value, industryCode);industrySelectedNode.value = node || { code: industryCode };
};

9. 处理行业节点点击事件

优化前:

// 处理行业节点点击事件
function handleIndustryNodeClick(data: any, node: any) {console.log('行业节点点击:', data, node);if (data && data.code) {industrySelectedNode.value = data;}
}

优化思路:
使用可选链和短路求值简化代码。

优化后:

// 处理行业节点点击事件
const handleIndustryNodeClick = (data: any) => {data?.code && (industrySelectedNode.value = data);
};

核心问题修复

整个优化过程中,解决的最关键问题是修正了getNodePath函数中的条件判断错误:

优化前:

if (targetLevel > 2 && firstLevelNode.children) {// 获取二级行业代码// ...
}

优化后:

if (targetLevel > 1 && firstLevelNode.children?.length) {// 获取二级行业代码// ...
}

这个看似微小的修改解决了选择三级行业代码不能自动展开到正确层级结构的问题。原来的条件targetLevel > 2意味着只有当目标是三级或四级代码时才会处理二级代码的查找,这导致对于二级代码自身无法正确构建路径。

修改为targetLevel > 1后,只要目标是二级及以上代码,就会尝试查找和构建二级路径,从而正确展开树形结构。

优化与性能

主要优化点

  1. 缓存机制:使用treeDataCache缓存树数据,避免重复加载

    // 如果已有缓存数据,直接使用
    if (treeDataCache.value.length > 0) {industryTreeData.value = treeDataCache.value;// ...return;
    }
    
  2. 懒加载策略:只在实际需要时才加载行业树数据

    // 仅在首次显示且无数据时加载
    if (visible && industryTreeData.value.length === 0) {initIndustryTree();
    }
    
  3. 多策略路径查找:采用层级分析、精确匹配、模糊匹配和后备构建等多种策略查找节点路径

  4. 展开路径优化:修复了选择三级行业代码不能自动展开的问题

问题解决

对于选择三级行业代码不能自动展开的问题,主要通过以下改进解决:

  1. 修正了路径查找逻辑中的条件判断:

    // 原代码
    if (targetLevel > 2 && firstLevelNode.children) {// ...
    }// 修改为
    if (targetLevel > 1 && firstLevelNode.children) {// ...
    }
    
  2. 增强了路径查找失败时的后备策略,确保总能生成合理的展开路径

应用案例

在表单中的应用

在重点用能单位表单(add-modal.vue)中,该组件用于选择企业所属行业:

<el-form-item :label="item.label" :prop="item.prop" :rules="item.rules"><!-- 行业树形选择器 --><el-tree-selectv-else-if="item.type === 'tree-select' && item.prop === 'industry'":placeholder="item.rules[0].message"v-model="formData[item.prop]":data="industryTreeData":props="industryTreeProps"node-key="code"check-strictlyvalue-key="code"filterableclearable:default-expanded-keys="expandedKeys":render-after-expand="false"@visible-change="handleTreeVisibleChange"@change="handleIndustryChange"@node-click="handleIndustryNodeClick"/>
</el-form-item>

详情查看模式

在详情查看模式下,组件以只读方式展示所选行业:

// 加载行业数据(用于详情)
const loadIndustryDataForDetail = async () => {if ((props.type === viewType.EDIT || props.type === viewType.DETAIL) &&formData.value.industry &&typeof formData.value.industry === 'string') {try {await initLoadTree(formData.value.industry);} catch (error) {console.error('加载行业节点失败', error);}}
};

学习与收获

技术决策考量

  1. 多策略路径查找:在节点查找中采用多种策略,从精确到模糊,再到后备构建,确保总能生成合理的展开路径
  2. 缓存数据提升性能:通过缓存树数据,减少不必要的API调用,提升响应速度
  3. 逐层降级策略:在处理节点查找失败时,采用逐层降级策略,确保系统稳健运行

遇到的挑战与解决方法

  1. 节点路径查找复杂性:行业代码具有特定的层级结构,需要根据代码长度和内容进行不同的处理

    • 解决方法:根据代码长度确定层级,采用多种查找策略并提供后备方案
  2. 条件判断繁杂:路径查找涉及多层嵌套条件

    • 解决方法:优化条件判断逻辑,确保关键条件判断准确无误

设计模式应用

  1. 策略模式:在节点路径查找中采用多种策略(层级分析、精确匹配、模糊匹配、后备构建)
  2. 缓存模式:使用树数据缓存提升性能
  3. 降级策略:在高精度策略失效时逐步采用低精度策略,确保系统稳定性

未来规划

待解决的问题

  1. 代码冗余:路径查找算法仍然包含较多嵌套逻辑,可进一步优化
  2. 类型定义不足:部分函数参数和返回值缺乏精确的TypeScript类型定义
  3. 错误提示不足:在节点查找失败时缺乏对用户的友好提示

计划中的优化

  1. 重构路径查找算法:进一步简化路径查找算法,提取重复逻辑
  2. 增强类型定义:完善TypeScript类型定义,提高代码质量
  3. 用户体验优化:添加节点查找失败时的友好提示

总结

行业树选择器组件的优化重构展示了如何通过细致的代码分析找出潜在问题,并通过精确的修改和重构提高代码质量。这个案例也说明了在前端开发中,有时微小的条件判断错误可能导致功能异常,而细心的分析和优化是解决复杂问题的关键。

我们通过以下几个方面改进了组件:

  1. 功能修复 - 解决了选择三级行业代码不能自动展开的问题
  2. 代码优化 - 简化了条件判断、抽取公共逻辑、减少代码冗余
  3. 性能提升 - 通过缓存和懒加载策略减少API调用和不必要的计算
  4. 健壮性增强 - 增加了多种降级策略,确保在各种情况下都能正常工作
  5. 可读性提高 - 重构复杂函数,使代码更加清晰易读

这次优化不仅解决了具体的功能问题,也展示了如何在实际项目中运用代码重构技术来提高组件质量。通过这个案例,我们可以看到,即使是看似微小的修改,也可能对功能产生重大影响,因此在开发和重构过程中,需要深入理解代码逻辑,仔细分析潜在影响。

最终,经过优化的行业树选择器组件不仅功能更加完善,也更易于维护和扩展,为系统提供了更好的用户体验。

相关文章:

  • 微服务1--服务架构
  • 计算机视觉算法实现——疲劳驾驶检测
  • Windows 下实现 PHP 多版本动态切换管理(适配 phpStudy)+ 一键切换工具源码分享
  • 基于JSP+MySQL实现用户注册登录及短信发送功能
  • Swift —— delegate 设计模式
  • 宝塔面板面试内容整理-Web服务器优化
  • Google最新《Prompt Engineering》白皮书全解析
  • 多线程、JUC——面试问题自我总结
  • 住宅代理是什么?2025详细指南
  • 基于前端技术的QR码API开发实战:从原理到部署
  • Handsontable 表格组件的使用
  • 自己总结的选型
  • WebSocket 技术详解
  • Flink Hive Catalog最佳实践
  • 从零实现富文本编辑器#2-基于MVC模式的编辑器架构设计
  • 大模型量化实战:GPTQ与AWQ量化方案对比与部署优化
  • 大数据学习(106)-hivesql函数
  • Maven相关名词及相关配置
  • Ubuntu卸载小皮面板
  • 记一次springboot集成海康威视SDK过程
  • 李在明回应韩国大法院判决:与自己所想截然不同,将顺从民意
  • 永辉超市回应顾客结算时被“反向抹零”:整改并补偿
  • 光明日报社论:用你我的匠心,托举起繁盛的中国
  • AI世界的年轻人,如何作答未来
  • 李铁案二审驳回上诉,维持一审有期徒刑20年的判决
  • 普京与卢卡申科举行会晤,将扩大在飞机制造等领域合作