diff --git a/frontend/web/.github/workflows/ci.yml b/frontend/web/.github/workflows/ci.yml new file mode 100644 index 00000000..315a2e9d --- /dev/null +++ b/frontend/web/.github/workflows/ci.yml @@ -0,0 +1,59 @@ +name: CI + +on: + push: + branches: [master, dev] + pull_request: + branches: [master] + +jobs: + lint: + runs-on: ubuntu-latest + defaults: + run: + working-directory: frontend/web + + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 9 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + cache-dependency-path: frontend/web/pnpm-lock.yaml + + - run: pnpm install --frozen-lockfile + + - name: Type Check + run: pnpm type-check + + - name: Lint + run: pnpm lint + + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: frontend/web + + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 9 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + cache-dependency-path: frontend/web/pnpm-lock.yaml + + - run: pnpm install --frozen-lockfile + + - name: Build + run: pnpm build:dev diff --git a/frontend/web/README.md b/frontend/web/README.md index de234730..f0fd204b 100755 --- a/frontend/web/README.md +++ b/frontend/web/README.md @@ -2,6 +2,24 @@ 基于 **Vue 3 + Vite + TypeScript + Element Plus** 的后台管理前端,与 FastAPI Admin 后端配套使用。状态管理为 **Pinia**,样式以 **Tailwind CSS 4** 与 **SCSS** 为主,接口请求使用 **Axios**。 +## 架构概览 + +``` +main.ts 启动 + └─ initPlugins(app) ← 插件注册(Pinia → Router → 指令 → i18n → Element Plus) + └─ mount("#app") + └─ App.vue + ├─ onBeforeMount: 主题初始化 + └─ onMounted: bootstrap() → 存储检查/版本升级/站点配置 + └─ 路由守卫 beforeEach + ├─ 存储失效检测 + ├─ 登录态校验 + ├─ 动态路由注册(菜单 → addRoute) + └─ 标签/标题同步 +``` + +路由采用 **Hash 模式**,静态路由(Layout/登录/404)首屏注册,业务路由由守卫根据菜单权限延迟 `addRoute`。HTTP 拦截器支持 **Token 静默续期**(401 时自动 refresh,失败后跳转登录)。 + --- ## 第一次运行(最快上手) diff --git a/frontend/web/index.html b/frontend/web/index.html index 6111faca..ffce9caf 100755 --- a/frontend/web/index.html +++ b/frontend/web/index.html @@ -12,7 +12,7 @@ diff --git a/frontend/web/src/components/DatePicker/index.vue b/frontend/web/src/components/DatePicker/index.vue index 1c791696..db3a915b 100644 --- a/frontend/web/src/components/DatePicker/index.vue +++ b/frontend/web/src/components/DatePicker/index.vue @@ -1,39 +1,91 @@ - + diff --git a/frontend/web/src/components/layouts/fa-menus/fa-mixed-menu/index.vue b/frontend/web/src/components/layouts/fa-menus/fa-mixed-menu/index.vue index 5d6588ee..edbc6993 100644 --- a/frontend/web/src/components/layouts/fa-menus/fa-mixed-menu/index.vue +++ b/frontend/web/src/components/layouts/fa-menus/fa-mixed-menu/index.vue @@ -248,13 +248,13 @@ onMounted(initScrollState); diff --git a/frontend/web/src/components/others/fa-copy-button/index.vue b/frontend/web/src/components/others/fa-copy-button/index.vue index f7f7498f..56731e66 100644 --- a/frontend/web/src/components/others/fa-copy-button/index.vue +++ b/frontend/web/src/components/others/fa-copy-button/index.vue @@ -28,18 +28,16 @@ const props = defineProps({ }, }); -function handleClipboard() { +async function handleClipboard() { if (navigator.clipboard && navigator.clipboard.writeText) { // 使用 Clipboard API - navigator.clipboard - .writeText(props.text) - .then(() => { - ElMessage.success(t("common.copySuccess")); - }) - .catch((error) => { - ElMessage.warning(t("common.copyFailed")); - console.log("[CopyButton] Copy failed", error); - }); + try { + await navigator.clipboard.writeText(props.text); + ElMessage.success(t("common.copySuccess")); + } catch (error) { + ElMessage.warning(t("common.copyFailed")); + console.warn("[CopyButton] Copy failed:", error); + } } else { // 兼容性处理(useClipboard 有兼容性问题) const input = document.createElement("input"); @@ -57,7 +55,7 @@ function handleClipboard() { } } catch (err) { ElMessage.warning(t("common.copyFailed")); - console.log("[CopyButton] Copy failed.", err); + console.warn("[CopyButton] Copy failed:", err); } finally { document.body.removeChild(input); } diff --git a/frontend/web/src/components/others/fa-markdown-renderer/index.vue b/frontend/web/src/components/others/fa-markdown-renderer/index.vue index b29a0519..27298252 100644 --- a/frontend/web/src/components/others/fa-markdown-renderer/index.vue +++ b/frontend/web/src/components/others/fa-markdown-renderer/index.vue @@ -70,7 +70,7 @@ const renderedContent = computed(() => { color: var(--el-text-color-primary); word-wrap: break-word; - ::v-deep(pre) { + :deep(pre) { padding: 12px; margin: 12px 0; overflow-x: auto; @@ -83,7 +83,7 @@ const renderedContent = computed(() => { } } - ::v-deep(code) { + :deep(code) { padding: 2px 6px; font-family: "Courier New", Courier, monospace; font-size: 13px; @@ -91,21 +91,21 @@ const renderedContent = computed(() => { border-radius: 3px; } - ::v-deep(p) { + :deep(p) { margin: 8px 0; } - ::v-deep(ul), - ::v-deep(ol) { + :deep(ul), + :deep(ol) { padding-left: 24px; margin: 8px 0; } - ::v-deep(li) { + :deep(li) { margin: 4px 0; } - ::v-deep(a) { + :deep(a) { color: var(--el-color-primary); text-decoration: none; @@ -114,14 +114,14 @@ const renderedContent = computed(() => { } } - ::v-deep(blockquote) { + :deep(blockquote) { padding: 8px 16px; margin: 12px 0; background: var(--el-fill-color-light); border-left: 4px solid var(--el-color-primary); } - ::v-deep(table) { + :deep(table) { width: 100%; margin: 12px 0; border-collapse: collapse; diff --git a/frontend/web/src/components/others/fa-menu-right/index.vue b/frontend/web/src/components/others/fa-menu-right/index.vue index 0a766412..a566a202 100644 --- a/frontend/web/src/components/others/fa-menu-right/index.vue +++ b/frontend/web/src/components/others/fa-menu-right/index.vue @@ -384,7 +384,7 @@ defineExpose({ } .menu-item.is-disabled i:not(.submenu-arrow), -.menu-item.is-disabled ::v-deep(.fa-svg-icon) { +.menu-item.is-disabled :deep(.fa-svg-icon) { color: var(--el-text-color-disabled) !important; } diff --git a/frontend/web/src/components/others/fa-table-select/index.vue b/frontend/web/src/components/others/fa-table-select/index.vue index 3dd36f82..f3182860 100644 --- a/frontend/web/src/components/others/fa-table-select/index.vue +++ b/frontend/web/src/components/others/fa-table-select/index.vue @@ -124,7 +124,7 @@ - ; @@ -264,21 +265,19 @@ function handleQuery() { } // 获取分页数据 -function fetchPageData(isRestart = false) { +async function fetchPageData(isRestart = false) { loading.value = true; if (isRestart) { queryParams.page_no = 1; queryParams.page_size = page_size; } - props.selectConfig - .indexAction(queryParams) - .then((data) => { - total.value = data.total; - pageData.value = data.list; - }) - .finally(() => { - loading.value = false; - }); + try { + const data = await props.selectConfig.indexAction(queryParams); + total.value = data.total; + pageData.value = data.list; + } finally { + loading.value = false; + } } // 列表操作 @@ -352,8 +351,8 @@ const popoverContentRef = ref(); diff --git a/frontend/web/src/components/others/fa-upload/index.vue b/frontend/web/src/components/others/fa-upload/index.vue index 34991428..85648b88 100644 --- a/frontend/web/src/components/others/fa-upload/index.vue +++ b/frontend/web/src/components/others/fa-upload/index.vue @@ -464,7 +464,7 @@ const onError = (error: any) => { } } -::v-deep(.el-upload--picture-card) { +:deep(.el-upload--picture-card) { position: relative; width: v-bind("props.style.width ?? '150px'"); height: v-bind("props.style.height ?? '150px'"); diff --git a/frontend/web/src/components/tables/fa-table/index.vue b/frontend/web/src/components/tables/fa-table/index.vue index a6c4e513..d6c6546f 100644 --- a/frontend/web/src/components/tables/fa-table/index.vue +++ b/frontend/web/src/components/tables/fa-table/index.vue @@ -4,7 +4,7 @@ - 暴露 `elTableRef`、`scrollToTop`;formatter 列见 TableFormatterOutlet 注释。 --> diff --git a/frontend/web/src/views/dashboard/article/components/ArticleDetailDrawer.vue b/frontend/web/src/views/dashboard/article/components/ArticleDetailDrawer.vue index 618fe8a1..251ead1a 100644 --- a/frontend/web/src/views/dashboard/article/components/ArticleDetailDrawer.vue +++ b/frontend/web/src/views/dashboard/article/components/ArticleDetailDrawer.vue @@ -127,12 +127,12 @@ watch( .article-detail-markdown { margin-top: 8px; - ::v-deep(img) { + :deep(img) { width: 100%; border: 1px solid var(--fa-gray-200); } - ::v-deep(pre) { + :deep(pre) { position: relative; &:hover { @@ -152,11 +152,11 @@ watch( } } - ::v-deep(.code-wrapper) { + :deep(.code-wrapper) { overflow-x: auto; } - ::v-deep(.line-number) { + :deep(.line-number) { position: sticky; left: 0; z-index: 2; @@ -169,7 +169,7 @@ watch( text-align: center; } - ::v-deep(.copy-button) { + :deep(.copy-button) { position: absolute; top: 6px; right: 6px; diff --git a/frontend/web/src/views/dashboard/console/modules/new-user.vue b/frontend/web/src/views/dashboard/console/modules/new-user.vue index 1194f69c..7fbd40be 100755 --- a/frontend/web/src/views/dashboard/console/modules/new-user.vue +++ b/frontend/web/src/views/dashboard/console/modules/new-user.vue @@ -164,7 +164,7 @@ onMounted(() => { diff --git a/frontend/web/src/views/module_application/portal/index.vue b/frontend/web/src/views/module_application/portal/index.vue index ac535223..539f3b3f 100644 --- a/frontend/web/src/views/module_application/portal/index.vue +++ b/frontend/web/src/views/module_application/portal/index.vue @@ -532,12 +532,12 @@ async function handleSubmit() { opacity: 0.55; } - ::v-deep(.el-card__header) { + :deep(.el-card__header) { padding: 14px 14px 12px; border-bottom: none; } - ::v-deep(.el-card__body) { + :deep(.el-card__body) { display: flex; flex: 1; flex-direction: column; @@ -546,7 +546,7 @@ async function handleSubmit() { padding: 12px 14px; } - ::v-deep(.el-card__footer) { + :deep(.el-card__footer) { padding: 10px 14px 14px; margin-top: auto; } @@ -634,11 +634,11 @@ async function handleSubmit() { } } -.crud-dialog-art-form ::v-deep(.el-row > .el-col:last-child) { +.crud-dialog-art-form :deep(.el-row > .el-col:last-child) { display: none; } -.crud-dialog-art-form ::v-deep(.el-form-item__content) { +.crud-dialog-art-form :deep(.el-form-item__content) { max-width: 100%; } diff --git a/frontend/web/src/views/module_example/demo/index.vue b/frontend/web/src/views/module_example/demo/index.vue index 36c2b4e1..93f5bd2e 100644 --- a/frontend/web/src/views/module_example/demo/index.vue +++ b/frontend/web/src/views/module_example/demo/index.vue @@ -472,7 +472,7 @@ const exportQueryParams = computed(() => { const demoImportContentConfig = computed(() => ({ permPrefix: "module_example:demo", cols: demoCrudCols.value, - indexAction: async () => ({}) as any, + indexAction: async () => ({}), importTemplate: () => DemoAPI.downloadTemplateDemo(), })); @@ -685,84 +685,91 @@ async function handleSubmit() { }); } -const deleteDemoRow = (row: DemoTable) => { +const deleteDemoRow = async (row: DemoTable) => { if (!row.id) return; - ElMessageBox.confirm(`确定删除「${row.name ?? row.id}」吗?此操作不可恢复!`, "删除确认", { - confirmButtonText: "确定", - cancelButtonText: "取消", - type: "warning", - }) - .then(async () => { - await DemoAPI.deleteDemo([row.id!]); - ElMessage.success("删除成功"); - faTableRef.value?.elTableRef?.clearSelection(); - await refreshRemove(); - }) - .catch(() => { - ElMessage.info("已取消删除"); - }); + try { + await ElMessageBox.confirm( + `确定删除「${row.name ?? row.id}」吗?此操作不可恢复!`, + "删除确认", + { + confirmButtonText: "确定", + cancelButtonText: "取消", + type: "warning", + } + ); + await DemoAPI.deleteDemo([row.id!]); + ElMessage.success("删除成功"); + faTableRef.value?.elTableRef?.clearSelection(); + await refreshRemove(); + } catch { + ElMessage.info("已取消删除"); + } }; -function handleBatchDelete() { +async function handleBatchDelete() { const ids = selectedIds.value; if (ids.length === 0) return; - ElMessageBox.confirm(`确定删除选中的 ${ids.length} 条数据吗?此操作不可恢复!`, "批量删除", { - confirmButtonText: "确定", - cancelButtonText: "取消", - type: "warning", - }) - .then(async () => { - try { - batchDeleting.value = true; - await DemoAPI.deleteDemo(ids); - ElMessage.success("删除成功"); - faTableRef.value?.elTableRef?.clearSelection(); - await refreshRemove(); - } finally { - batchDeleting.value = false; + try { + await ElMessageBox.confirm( + `确定删除选中的 ${ids.length} 条数据吗?此操作不可恢复!`, + "批量删除", + { + confirmButtonText: "确定", + cancelButtonText: "取消", + type: "warning", } - }) - .catch(() => { - ElMessage.info("已取消删除"); - }); + ); + batchDeleting.value = true; + await DemoAPI.deleteDemo(ids); + ElMessage.success("删除成功"); + faTableRef.value?.elTableRef?.clearSelection(); + await refreshRemove(); + } catch { + ElMessage.info("已取消删除"); + } finally { + batchDeleting.value = false; + } } -function runBatchStatus(status: string) { +async function runBatchStatus(status: string) { const ids = selectedIds.value; if (ids.length === 0) { ElMessage.warning("请先在列表中勾选数据"); return; } - ElMessageBox.confirm( - `确认对选中的 ${ids.length} 条数据${status === "0" ? "启用" : "停用"}?`, - "批量设置", - { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" } - ) - .then(async () => { - await DemoAPI.batchDemo({ ids, status }); - ElMessage.success("操作成功"); - faTableRef.value?.elTableRef?.clearSelection(); - await refreshData(); - }) - .catch(() => {}); + try { + await ElMessageBox.confirm( + `确认对选中的 ${ids.length} 条数据${status === "0" ? "启用" : "停用"}?`, + "批量设置", + { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" } + ); + await DemoAPI.batchDemo({ ids, status }); + ElMessage.success("操作成功"); + faTableRef.value?.elTableRef?.clearSelection(); + await refreshData(); + } catch { + // 用户取消 + } } function openImportModal() { importModalVisible.value = true; } -function handleCrudImportUpload(formData: FormData) { - DemoAPI.importDemo(formData) - .then((res) => { - if (res.data.code !== ResultEnum.SUCCESS) { - ElMessage.error(res.data.msg || "导入失败"); - return; - } - ElMessage.success(res.data.msg || "导入成功"); - importModalVisible.value = false; - return refreshData(); - }) - .catch(console.error); +async function handleCrudImportUpload(formData: FormData) { + try { + const res = await DemoAPI.importDemo(formData); + if (res.data.code !== ResultEnum.SUCCESS) { + ElMessage.error(res.data.msg || "导入失败"); + return; + } + ElMessage.success(res.data.msg || "导入成功"); + importModalVisible.value = false; + await refreshData(); + } catch (error) { + console.error("[Import]", error); + ElMessage.error("导入失败"); + } } function openExportModal() { diff --git a/frontend/web/src/views/module_example/demo01/index.vue b/frontend/web/src/views/module_example/demo01/index.vue index fcf65a3c..91b6f4c2 100644 --- a/frontend/web/src/views/module_example/demo01/index.vue +++ b/frontend/web/src/views/module_example/demo01/index.vue @@ -541,84 +541,83 @@ async function handleSubmit() { }); } -const deleteDemo01Row = (row: Demo01Table) => { +const deleteDemo01Row = async (row: Demo01Table) => { if (!row.id) return; - ElMessageBox.confirm(`确定删除「${row.name ?? row.id}」吗?此操作不可恢复!`, "删除确认", { - confirmButtonText: "确定", - cancelButtonText: "取消", - type: "warning", - }) - .then(async () => { - await Demo01API.deleteDemo01([row.id!]); - ElMessage.success("删除成功"); - faTableRef.value?.elTableRef?.clearSelection(); - await refreshRemove(); - }) - .catch(() => { - ElMessage.info("已取消删除"); - }); + try { + await ElMessageBox.confirm( + `确定删除「${row.name ?? row.id}」吗?此操作不可恢复!`, + "删除确认", + { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" } + ); + await Demo01API.deleteDemo01([row.id!]); + ElMessage.success("删除成功"); + faTableRef.value?.elTableRef?.clearSelection(); + await refreshRemove(); + } catch { + ElMessage.info("已取消删除"); + } }; -function handleBatchDelete() { +async function handleBatchDelete() { const ids = selectedIds.value; if (ids.length === 0) return; - ElMessageBox.confirm(`确定删除选中的 ${ids.length} 条数据吗?此操作不可恢复!`, "批量删除", { - confirmButtonText: "确定", - cancelButtonText: "取消", - type: "warning", - }) - .then(async () => { - try { - batchDeleting.value = true; - await Demo01API.deleteDemo01(ids); - ElMessage.success("删除成功"); - faTableRef.value?.elTableRef?.clearSelection(); - await refreshRemove(); - } finally { - batchDeleting.value = false; - } - }) - .catch(() => { - ElMessage.info("已取消删除"); - }); + try { + await ElMessageBox.confirm( + `确定删除选中的 ${ids.length} 条数据吗?此操作不可恢复!`, + "批量删除", + { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" } + ); + batchDeleting.value = true; + await Demo01API.deleteDemo01(ids); + ElMessage.success("删除成功"); + faTableRef.value?.elTableRef?.clearSelection(); + await refreshRemove(); + } catch { + ElMessage.info("已取消删除"); + } finally { + batchDeleting.value = false; + } } -function runBatchStatus(status: string) { +async function runBatchStatus(status: string) { const ids = selectedIds.value; if (ids.length === 0) { ElMessage.warning("请先在列表中勾选数据"); return; } - ElMessageBox.confirm( - `确认对选中的 ${ids.length} 条数据${status === "0" ? "启用" : "停用"}?`, - "批量设置", - { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" } - ) - .then(async () => { - await Demo01API.batchDemo01({ ids, status }); - ElMessage.success("操作成功"); - faTableRef.value?.elTableRef?.clearSelection(); - await refreshData(); - }) - .catch(() => {}); + try { + await ElMessageBox.confirm( + `确认对选中的 ${ids.length} 条数据${status === "0" ? "启用" : "停用"}?`, + "批量设置", + { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" } + ); + await Demo01API.batchDemo01({ ids, status }); + ElMessage.success("操作成功"); + faTableRef.value?.elTableRef?.clearSelection(); + await refreshData(); + } catch { + // 用户取消操作,无需处理 + } } function openImportModal() { importModalVisible.value = true; } -function handleCrudImportUpload(formDataUpload: FormData) { - Demo01API.importDemo01(formDataUpload) - .then((res) => { - if (res.data.code !== ResultEnum.SUCCESS) { - ElMessage.error(res.data.msg || "导入失败"); - return; - } - ElMessage.success(res.data.msg || "导入成功"); - importModalVisible.value = false; - return refreshData(); - }) - .catch(console.error); +async function handleCrudImportUpload(formDataUpload: FormData) { + try { + const res = await Demo01API.importDemo01(formDataUpload); + if (res.data.code !== ResultEnum.SUCCESS) { + ElMessage.error(res.data.msg || "导入失败"); + return; + } + ElMessage.success(res.data.msg || "导入成功"); + importModalVisible.value = false; + await refreshData(); + } catch (error) { + console.error("[Import]", error); + ElMessage.error("导入失败"); + } } function openExportModal() { @@ -627,11 +626,11 @@ function openExportModal() { diff --git a/frontend/web/src/views/module_generator/gencode/components/CreateTableDialog.vue b/frontend/web/src/views/module_generator/gencode/components/CreateTableDialog.vue index b5d7aa95..07550b94 100644 --- a/frontend/web/src/views/module_generator/gencode/components/CreateTableDialog.vue +++ b/frontend/web/src/views/module_generator/gencode/components/CreateTableDialog.vue @@ -426,7 +426,7 @@ function handleCancel() { position: relative; } -.visual-pane ::v-deep(.el-textarea__inner) { +.visual-pane :deep(.el-textarea__inner) { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; } @@ -437,20 +437,20 @@ function handleCancel() { /* 表结构:描述列表表格化,标签列对齐、内容区可伸缩 */ .visual-structure { .visual-desc { - ::v-deep(.el-descriptions__label) { + :deep(.el-descriptions__label) { width: 108px; vertical-align: middle; } - ::v-deep(.el-descriptions__cell) { + :deep(.el-descriptions__cell) { vertical-align: middle; } - ::v-deep(.el-descriptions__content) { + :deep(.el-descriptions__content) { min-width: 0; } - ::v-deep(.el-descriptions__title) { + :deep(.el-descriptions__title) { margin-bottom: 8px; } } diff --git a/frontend/web/src/views/module_generator/gencode/components/GenBasicStep.vue b/frontend/web/src/views/module_generator/gencode/components/GenBasicStep.vue index 5c52f85b..7982cd6e 100644 --- a/frontend/web/src/views/module_generator/gencode/components/GenBasicStep.vue +++ b/frontend/web/src/views/module_generator/gencode/components/GenBasicStep.vue @@ -237,7 +237,7 @@ const props = defineProps<{ function findOptionByValue(options: OptionType[], value: number | string): any | null { for (const opt of options) { - if (String(opt.value) === String(value)) return opt as any; + if (String(opt.value) === String(value)) return opt; if (opt.children?.length) { const hit = findOptionByValue(opt.children, value); if (hit) return hit; @@ -352,15 +352,15 @@ onUnmounted(() => { min-width: 0; } -.gen-basic-step ::v-deep(.el-col) { +.gen-basic-step :deep(.el-col) { min-width: 0; } -.gen-basic-step ::v-deep(.el-form-item__content) { +.gen-basic-step :deep(.el-form-item__content) { min-width: 0; } -.gen-basic-step ::v-deep(.el-input-group) { +.gen-basic-step :deep(.el-input-group) { width: 100%; min-width: 0; max-width: 100%; @@ -383,11 +383,11 @@ onUnmounted(() => { border: 1px solid var(--el-border-color-lighter); } -.master-sub-card ::v-deep(.el-card__header) { +.master-sub-card :deep(.el-card__header) { padding: 8px 10px; } -.master-sub-card ::v-deep(.el-card__body) { +.master-sub-card :deep(.el-card__body) { padding: 10px; } @@ -396,7 +396,7 @@ onUnmounted(() => { border: 1px solid var(--el-border-color-lighter); } -.gen-form-card ::v-deep(.el-card__body) { +.gen-form-card :deep(.el-card__body) { overflow-x: hidden; } @@ -425,7 +425,7 @@ onUnmounted(() => { border-bottom: 1px solid var(--el-border-color-lighter); } -.gen-echo-card ::v-deep(.el-card__body) { +.gen-echo-card :deep(.el-card__body) { padding: 6px 8px; } diff --git a/frontend/web/src/views/module_generator/gencode/components/GenColumnsStep.vue b/frontend/web/src/views/module_generator/gencode/components/GenColumnsStep.vue index dd86d269..614f0c71 100644 --- a/frontend/web/src/views/module_generator/gencode/components/GenColumnsStep.vue +++ b/frontend/web/src/views/module_generator/gencode/components/GenColumnsStep.vue @@ -249,7 +249,7 @@ import { computed, onBeforeUnmount, onMounted, ref, watch, nextTick } from "vue"; import { Search } from "@element-plus/icons-vue"; import { useDraggable } from "vue-draggable-plus"; -import type { GenTableSchema } from "@/api/module_generator/gencode"; +import type { GenTableSchema, GenTableColumnSchema } from "@/api/module_generator/gencode"; import type { DictTable } from "@/api/module_system/dict"; defineOptions({ name: "GenColumnsStep" }); @@ -276,7 +276,7 @@ const columnsModel = computed({ get: () => props.info.columns || [], set: (v) => { // props.info 是父组件传入的 reactive 对象,可以直接回写 - props.info.columns = v as any; + props.info.columns = v as GenTableColumnSchema[]; }, }); diff --git a/frontend/web/src/views/module_generator/gencode/components/GencodeHelpPanel.vue b/frontend/web/src/views/module_generator/gencode/components/GencodeHelpPanel.vue index a9b0e2dd..88aae17f 100644 --- a/frontend/web/src/views/module_generator/gencode/components/GencodeHelpPanel.vue +++ b/frontend/web/src/views/module_generator/gencode/components/GencodeHelpPanel.vue @@ -66,18 +66,18 @@ const rows = [ border-radius: var(--el-border-radius-base); } -.gencode-help-collapse ::v-deep(.el-collapse-item__header) { +.gencode-help-collapse :deep(.el-collapse-item__header) { padding: 8px 12px; font-size: 13px; font-weight: 500; background: var(--el-fill-color-light); } -.gencode-help-collapse ::v-deep(.el-collapse-item__wrap) { +.gencode-help-collapse :deep(.el-collapse-item__wrap) { border-top: 1px solid var(--el-border-color-lighter); } -.gencode-help-collapse ::v-deep(.el-collapse-item__content) { +.gencode-help-collapse :deep(.el-collapse-item__content) { padding: 10px 12px 12px; } @@ -91,7 +91,7 @@ const rows = [ flex-shrink: 0; } -.gencode-rules-table ::v-deep(.el-table__cell) { +.gencode-rules-table :deep(.el-table__cell) { font-size: 12px; } diff --git a/frontend/web/src/views/module_generator/gencode/components/ImportDbTableDialog.vue b/frontend/web/src/views/module_generator/gencode/components/ImportDbTableDialog.vue index 43e4e883..2630b193 100644 --- a/frontend/web/src/views/module_generator/gencode/components/ImportDbTableDialog.vue +++ b/frontend/web/src/views/module_generator/gencode/components/ImportDbTableDialog.vue @@ -73,7 +73,7 @@ > - { try { loading.value = true; const previewRes = await GencodeAPI.syncDbPreview(tableName); - const preview = previewRes.data?.data as any; + const preview = previewRes.data?.data as Record; const mainHtml = renderHtml(`主表:${tableName}`, preview); const subHtml = preview?.sub_table_name && preview?.sub diff --git a/frontend/web/src/views/module_monitor/cache/index.vue b/frontend/web/src/views/module_monitor/cache/index.vue index 9ad49061..d7b3d479 100644 --- a/frontend/web/src/views/module_monitor/cache/index.vue +++ b/frontend/web/src/views/module_monitor/cache/index.vue @@ -1,3 +1,4 @@ + - - - - - - - -