feat: 接入版本检查并适配 vxe-table 4.7

- 非开发环境每 5 分钟轮询版本,构建时输出版本号文件
- 表格依赖升级到 vxe-table 4.21,组件与类型改用 vxe-pc-ui
- 演示页按 4.7 写法重写列与表尾配置,移除旧版变量覆写
This commit is contained in:
Ray.Hao
2026-09-28 09:49:50 +08:00
8 changed files with 776 additions and 405 deletions

View File

@@ -15,6 +15,7 @@
import { useAppStore, useSettingsStore } from "@/stores";
import { appConfig } from "@/settings";
import { ThemeMode, ComponentSize } from "@/enums";
import { useVersionCheck } from "@/composables/useVersionCheck";
const appStore = useAppStore();
const settingsStore = useSettingsStore();
@@ -30,4 +31,9 @@ const fontColor = computed(() => {
? "rgba(255, 255, 255, .15)"
: "rgba(0, 0, 0, .15)";
});
// 初始化版本检查
if (!import.meta.env.DEV) {
useVersionCheck(5 * 60_000);
}
</script>

View File

@@ -0,0 +1,66 @@
import { ElNotification } from "element-plus";
import { onMounted, onUnmounted, ref } from "vue";
/** 版本检查 */
export function useVersionCheck(interval = 60_000) {
const hasNewVersion = ref(false);
let notified = false;
const safeInterval = Math.max(10_000, interval);
const checkVersion = async () => {
try {
const base = import.meta.env.BASE_URL;
const baseUrl = base.endsWith("/") ? base : `${base}/`;
// 时间戳防 CDN/代理缓存,no-cache 防浏览器磁盘缓存
const res = await fetch(`${baseUrl}version.json?t=${Date.now()}`, {
cache: "no-cache",
});
if (!res.ok) return; // 非核心功能,网络异常不影响正常使用
const data = await res.json();
if (data.version && data.version !== __APP_INFO__.buildTimestamp) {
hasNewVersion.value = true;
showUpdateNotice();
}
} catch (e) {
console.warn("版本检测失败", e);
}
};
const showUpdateNotice = () => {
if (notified) return;
notified = true;
// 使用 Notification 而非 Modal,不打断用户操作
ElNotification({
title: "🎉 发现新版本",
message: "系统已更新,点击刷新以获取最新功能",
duration: 0, // 不自动关闭
position: "bottom-right",
onClick: () => window.location.reload(),
onClose: () => {
notified = false;
},
customClass: "version-update-notice",
});
};
let timer: ReturnType<typeof setInterval>;
// 用户从其他标签页切回时立即检测,无需等待下一次轮询
const handleVisibilityChange = () => {
if (!document.hidden) checkVersion();
};
onMounted(() => {
checkVersion();
timer = setInterval(checkVersion, safeInterval);
document.addEventListener("visibilitychange", handleVisibilityChange);
});
onUnmounted(() => {
clearInterval(timer);
document.removeEventListener("visibilitychange", handleVisibilityChange);
});
return { hasNewVersion };
}

View File

@@ -1,35 +1,76 @@
// VxeTable 全局配置
// 参考:https://vxetable.cn/v4.6/#/table/start/install
// 引入样式
import "vxe-pc-ui/lib/style.css";
import "vxe-table/lib/style.css";
// 导入主题变量,也可以重写主题变量
import "vxe-pc-ui/styles/cssvar.scss";
import "vxe-table/styles/cssvar.scss";
// 导入默认的语言
import enUS from "vxe-pc-ui/lib/language/en-US";
import zhCN from "vxe-pc-ui/lib/language/zh-CN";
import VxeUIPluginExportXLSX from "@vxe-ui/plugin-export-xlsx";
import ExcelJS from "exceljs";
import { VxeUI } from "vxe-pc-ui";
import VXETable from "vxe-table";
import { useAppStore } from "@/stores/app";
import { DeviceEnum } from "@/enums";
/**
* 配置 vxe-table 的默认参数
*/
export function configureVxeTable() {
VXETable.setConfig({
export function configureVxeUI() {
const appStore = useAppStore();
const isMobile = appStore.device === DeviceEnum.MOBILE;
// 导入导出xlsx插件 https://vxetable.cn/other4/#/table/plugin/exportXLSX
VxeUI.use(VxeUIPluginExportXLSX, {
ExcelJS,
});
// 注册语言
VxeUI.setI18n("zh-CN", zhCN);
VxeUI.setI18n("en-US", enUS);
// 切换指定语言
VxeUI.setLanguage("zh-CN");
// 全局默认参数
VxeUI.setConfig({
// 全局尺寸
size: "medium",
// 全局 zIndex 起始值,默认是 999,如果项目的的 z-index 样式值过大时就需要跟随设置更大,避免被遮挡
zIndex: 9999,
// 版本号,对于某些带数据缓存的功能有用到,上升版本号可以用于重置数据
version: 0,
// 全局 loading 提示内容,如果为 null 则不显示文本
loading: {
showText: false,
text: "",
},
table: {
minHeight: 46,
showHeader: true,
showOverflow: "tooltip",
showHeaderOverflow: "tooltip",
showHeaderOverflow: isMobile ? false : "tooltip",
autoResize: true,
// stripe: false,
border: "inner",
// round: false,
emptyText: "暂无数据",
rowConfig: {
isHover: true,
isCurrent: true,
// 行数据的唯一主键字段名
keyField: "_VXE_ID",
},
columnConfig: {
resizable: false,
minWidth: isMobile ? "auto" : undefined,
},
align: "center",
headerAlign: "center",
validConfig: {
theme: "normal",
},
},
pager: {
// size: "medium",
// 配套的样式
perfect: false,
pageSize: 10,
pagerCount: 7,
@@ -45,11 +86,22 @@ export function configureVxeTable() {
"FullJump",
],
},
form: {
span: isMobile ? 24 : 6,
validConfig: {
theme: "normal",
},
},
modal: {
minWidth: 500,
minHeight: 400,
fullscreen: isMobile,
remember: isMobile,
width: isMobile ? "95%" : undefined,
// minWidth: 500,
// minHeight: 400,
lockView: true,
mask: true,
// duration: 3000,
// marginSize: 20,
dblclickZoom: false,
showTitleOverflow: true,
transfer: true,

View File

@@ -7,96 +7,6 @@
background-color: var(--el-color-primary);
}
// VxeTable 变量覆写
:root {
--vxe-font-color: var(--el-text-color-regular);
--vxe-primary-color: var(--el-color-primary);
--vxe-success-color: var(--el-color-success);
--vxe-info-color: var(--el-color-info);
--vxe-warning-color: var(--el-color-warning);
--vxe-danger-color: var(--el-color-danger);
--vxe-font-lighten-color: var(--el-text-color-primary);
--vxe-primary-lighten-color: var(--el-color-primary-light-3);
--vxe-success-lighten-color: var(--el-color-success-light-3);
--vxe-info-lighten-color: var(--el-color-info-light-3);
--vxe-warning-lighten-color: var(--el-color-warning-light-3);
--vxe-danger-lighten-color: var(--el-color-danger-light-3);
--vxe-font-darken-color: var(--el-text-color-secondary);
--vxe-primary-darken-color: var(--el-color-primary-dark-2);
--vxe-success-darken-color: var(--el-color-success-dark-2);
--vxe-info-darken-color: var(--el-color-info-dark-2);
--vxe-warning-darken-color: var(--el-color-warning-dark-2);
--vxe-danger-darken-color: var(--el-color-danger-dark-2);
--vxe-font-disabled-color: var(--el-text-color-disabled);
--vxe-primary-disabled-color: var(--el-color-primary-light-5);
--vxe-success-disabled-color: var(--el-color-success-light-5);
--vxe-info-disabled-color: var(--el-color-info-light-5);
--vxe-warning-disabled-color: var(--el-color-warning-light-5);
--vxe-danger-disabled-color: var(--el-color-danger-light-5);
--vxe-input-border-color: var(--el-border-color);
--vxe-input-disabled-color: var(--el-text-color-disabled);
--vxe-input-disabled-background-color: var(--el-fill-color-light);
--vxe-input-placeholder-color: var(--el-text-color-placeholder);
--vxe-table-popup-border-color: var(--el-border-color);
--vxe-table-header-font-color: var(--el-text-color-regular);
--vxe-table-footer-font-color: var(--el-text-color-regular);
--vxe-table-border-color: var(--el-border-color-lighter);
--vxe-table-header-background-color: var(--el-bg-color);
--vxe-table-body-background-color: var(--el-bg-color);
--vxe-table-footer-background-color: var(--el-bg-color);
--vxe-table-row-hover-background-color: var(--el-fill-color-light);
--vxe-table-row-current-background-color: var(--el-fill-color-light);
--vxe-table-row-hover-current-background-color: var(--el-fill-color-light);
--vxe-table-checkbox-range-background-color: var(--el-fill-color-light);
--vxe-table-menu-background-color: var(--el-bg-color-overlay);
--vxe-loading-color: var(--el-color-primary);
--vxe-loading-background-color: var(--el-mask-color);
--vxe-table-validate-error-color: var(--el-color-danger);
--vxe-toolbar-background-color: var(--el-bg-color);
--vxe-toolbar-custom-active-background-color: var(--el-bg-color-overlay);
--vxe-toolbar-panel-background-color: var(--el-bg-color-overlay);
--vxe-pager-background-color: var(--el-bg-color);
--vxe-modal-header-background-color: var(--el-bg-color);
--vxe-modal-body-background-color: var(--el-bg-color);
--vxe-modal-border-color: var(--el-border-color);
--vxe-button-default-background-color: var(--el-bg-color-overlay);
--vxe-input-background-color: var(--el-fill-color-blank);
--vxe-input-panel-background-color: var(--el-fill-color-blank);
--vxe-form-background-color: var(--el-bg-color);
--vxe-form-validate-error-color: var(--el-color-danger);
--vxe-select-option-hover-background-color: var(--el-bg-color-overlay);
--vxe-select-panel-background-color: var(--el-bg-color);
}
// VxeTable 自定义样式
.vxe-grid {
&--form-wrapper .vxe-form {
padding: 10px 20px;
margin-bottom: 20px;
}
&--toolbar-wrapper .vxe-toolbar {
padding: 20px;
}
&--pager-wrapper .vxe-pager {
height: 70px;
padding: 0 20px;
&--wrapper {
@media screen and (width <= 768px) {
.vxe-pager--total,
.vxe-pager--sizes,
.vxe-pager--jump,
.vxe-pager--jump-prev,
.vxe-pager--jump-next {
display: none;
}
}
}
}
}
// WangEditor 暗黑模式
html.dark {
--w-e-textarea-bg-color: var(--el-bg-color);

File diff suppressed because it is too large Load Diff