create-art-app-pino 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +34 -6
- package/package.json +25 -8
- package/template/auth-art/_env.development +6 -0
- package/template/auth-art/src/router/guards/beforeEach.ts +32 -5
- package/template/auth-art/src/router/index.ts.ejs +37 -9
- package/template/auth-art/src/store/modules/user.ts +62 -12
- package/template/auth-art/src/utils/http/index.ts +15 -1
- package/template/auth-art/src/utils/http/mock.ts +94 -0
- package/template/auth-art/src/views/auth/login/index.vue +265 -157
- package/template/auth-art/src/views/auth/login/style.css +38 -0
- package/template/auth-zhihuishu/_env.development +9 -0
- package/template/auth-zhihuishu/src/router/guards/beforeEach.ts +34 -11
- package/template/auth-zhihuishu/src/router/index.ts.ejs +37 -9
- package/template/auth-zhihuishu/src/store/modules/auth.ts +22 -11
- package/template/auth-zhihuishu/src/utils/auth.ts +2 -1
- package/template/base/eslint.config.mjs +5 -0
- package/template/base/index.html +31 -1
- package/template/base/package.json.ejs +10 -2
- package/template/base/src/App.vue +36 -1
- package/template/base/src/api/system-manage.ts +25 -0
- package/template/base/src/assets/images/avatar/avatar.webp +0 -0
- package/template/base/src/assets/images/avatar/avatar1.webp +0 -0
- package/template/base/src/assets/images/avatar/avatar10.webp +0 -0
- package/template/base/src/assets/images/avatar/avatar2.webp +0 -0
- package/template/base/src/assets/images/avatar/avatar3.webp +0 -0
- package/template/base/src/assets/images/avatar/avatar4.webp +0 -0
- package/template/base/src/assets/images/avatar/avatar5.webp +0 -0
- package/template/base/src/assets/images/avatar/avatar6.webp +0 -0
- package/template/base/src/assets/images/avatar/avatar7.webp +0 -0
- package/template/base/src/assets/images/avatar/avatar8.webp +0 -0
- package/template/base/src/assets/images/avatar/avatar9.webp +0 -0
- package/template/base/src/assets/images/common/logo.webp +0 -0
- package/template/base/src/assets/images/draw/draw1.png +0 -0
- package/template/base/src/assets/images/settings/menu_layouts/dual_column.png +0 -0
- package/template/base/src/assets/images/settings/menu_layouts/horizontal.png +0 -0
- package/template/base/src/assets/images/settings/menu_layouts/mixed.png +0 -0
- package/template/base/src/assets/images/settings/menu_layouts/vertical.png +0 -0
- package/template/base/src/assets/images/settings/menu_styles/dark.png +0 -0
- package/template/base/src/assets/images/settings/menu_styles/design.png +0 -0
- package/template/base/src/assets/images/settings/menu_styles/light.png +0 -0
- package/template/base/src/assets/images/settings/theme_styles/dark.png +0 -0
- package/template/base/src/assets/images/settings/theme_styles/light.png +0 -0
- package/template/base/src/assets/images/settings/theme_styles/system.png +0 -0
- package/template/base/src/assets/images/svg/403.svg +1 -0
- package/template/base/src/assets/images/svg/404.svg +1 -0
- package/template/base/src/assets/images/svg/500.svg +5 -0
- package/template/base/src/assets/images/svg/login_icon.svg +1 -0
- package/template/base/src/assets/images/user/avatar.webp +0 -0
- package/template/base/src/assets/images/user/bg.webp +0 -0
- package/template/base/src/assets/styles/core/app.scss +292 -0
- package/template/base/src/assets/styles/core/dark.scss +93 -0
- package/template/base/src/assets/styles/core/el-dark.scss +2 -0
- package/template/base/src/assets/styles/core/el-light.scss +34 -0
- package/template/base/src/assets/styles/core/el-ui.scss +519 -0
- package/template/base/src/assets/styles/core/md.scss +1036 -0
- package/template/base/src/assets/styles/core/mixin.scss +157 -0
- package/template/base/src/assets/styles/core/reset.scss +41 -0
- package/template/base/src/assets/styles/core/router-transition.scss +104 -0
- package/template/base/src/assets/styles/core/tailwind.css +208 -0
- package/template/base/src/assets/styles/core/theme-animation.scss +63 -0
- package/template/base/src/assets/styles/core/theme-change.scss +11 -0
- package/template/base/src/assets/styles/custom/one-dark-pro.scss +98 -0
- package/template/base/src/assets/styles/index.scss +21 -8
- package/template/base/src/assets/svg/loading.ts +32 -0
- package/template/base/src/components/core/base/art-logo/index.vue +21 -0
- package/template/base/src/components/core/base/art-svg-icon/index.vue +24 -0
- package/template/base/src/components/core/charts/art-bar-chart/index.vue +203 -0
- package/template/base/src/components/core/charts/art-line-chart/index.vue +371 -0
- package/template/base/src/components/core/charts/art-ring-chart/index.vue +134 -0
- package/template/base/src/components/core/forms/art-drag-verify/index.vue +430 -0
- package/template/base/src/components/core/layouts/art-breadcrumb/index.vue +142 -0
- package/template/base/src/components/core/layouts/art-fast-enter/index.vue +113 -0
- package/template/base/src/components/core/layouts/art-global-component/index.vue +14 -0
- package/template/base/src/components/core/layouts/art-header-bar/index.vue +431 -0
- package/template/base/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue +167 -0
- package/template/base/src/components/core/layouts/art-menus/art-horizontal-menu/index.vue +110 -0
- package/template/base/src/components/core/layouts/art-menus/art-horizontal-menu/widget/HorizontalSubmenu.vue +106 -0
- package/template/base/src/components/core/layouts/art-menus/art-mixed-menu/index.vue +279 -0
- package/template/base/src/components/core/layouts/art-menus/art-sidebar-menu/index.vue +354 -0
- package/template/base/src/components/core/layouts/art-menus/art-sidebar-menu/style.scss +251 -0
- package/template/base/src/components/core/layouts/art-menus/art-sidebar-menu/theme.scss +258 -0
- package/template/base/src/components/core/layouts/art-menus/art-sidebar-menu/widget/SidebarSubmenu.vue +201 -0
- package/template/base/src/components/core/layouts/art-page-content/index.vue +133 -0
- package/template/base/src/components/core/layouts/art-work-tab/index.vue +584 -0
- package/template/base/src/components/core/others/art-menu-right/index.vue +415 -0
- package/template/base/src/components/core/tables/art-table/index.vue +344 -0
- package/template/base/src/components/core/tables/art-table/style.scss +94 -0
- package/template/base/src/components/core/text-effect/art-count-to/index.vue +310 -0
- package/template/base/src/components/core/theme/theme-svg/index.vue +100 -0
- package/template/base/src/components/core/views/exception/ArtException.vue +55 -0
- package/template/base/src/components/core/views/login/AuthTopBar.vue +149 -0
- package/template/base/src/components/core/views/login/LoginLeftView.vue +602 -0
- package/template/base/src/components/core/widget/art-icon-button/index.vue +23 -0
- package/template/base/src/config/assets/images.ts +61 -0
- package/template/base/src/config/index.ts +135 -0
- package/template/base/src/config/modules/component.ts +47 -0
- package/template/base/src/config/modules/fastEnter.ts.ejs +63 -0
- package/template/base/src/config/modules/festival.ts +51 -0
- package/template/base/src/config/modules/headerBar.ts +63 -0
- package/template/base/src/config/setting.ts +109 -0
- package/template/base/src/directives/business/highlight.ts +250 -0
- package/template/base/src/directives/business/ripple.ts +116 -0
- package/template/base/src/directives/core/auth.ts +66 -0
- package/template/base/src/directives/core/roles.ts +87 -0
- package/template/base/src/directives/index.ts +14 -0
- package/template/base/src/enums/appEnum.ts +81 -0
- package/template/base/src/enums/formEnum.ts +24 -0
- package/template/base/src/env.d.ts +9 -0
- package/template/base/src/hooks/core/useAppMode.ts +45 -0
- package/template/base/src/hooks/core/useAuth.ts +74 -0
- package/template/base/src/hooks/core/useCeremony.ts +184 -0
- package/template/base/src/hooks/core/useChart.ts +745 -0
- package/template/base/src/hooks/core/useCommon.ts +87 -0
- package/template/base/src/hooks/core/useFastEnter.ts +55 -0
- package/template/base/src/hooks/core/useHeaderBar.ts +179 -0
- package/template/base/src/hooks/core/useLayoutHeight.ts +148 -0
- package/template/base/src/hooks/core/useTable.ts +762 -0
- package/template/base/src/hooks/core/useTableColumns.ts +312 -0
- package/template/base/src/hooks/core/useTableHeight.ts +105 -0
- package/template/base/src/hooks/core/useTheme.ts +174 -0
- package/template/base/src/locales/index.ts +123 -0
- package/template/base/src/locales/langs/en.json +348 -0
- package/template/base/src/locales/langs/zh.json +348 -0
- package/template/base/src/main.ts +11 -12
- package/template/base/src/mock/upgrade/changeLog.ts +449 -0
- package/template/base/src/plugins/echarts.ts +76 -0
- package/template/base/src/router/core/ComponentLoader.ts +82 -0
- package/template/base/src/router/core/IframeRouteManager.ts +78 -0
- package/template/base/src/router/core/MenuProcessor.ts +280 -0
- package/template/base/src/router/core/RoutePermissionValidator.ts +161 -0
- package/template/base/src/router/core/RouteRegistry.ts +90 -0
- package/template/base/src/router/core/RouteTransformer.ts +132 -0
- package/template/base/src/router/core/RouteValidator.ts +187 -0
- package/template/base/src/router/core/index.ts +14 -0
- package/template/base/src/router/index.ts.ejs +37 -9
- package/template/base/src/router/routes/asyncRoutes.ts +38 -0
- package/template/base/src/router/routesAlias.ts +8 -0
- package/template/base/src/store/index.ts +49 -4
- package/template/base/src/store/modules/menu.ts +109 -0
- package/template/base/src/store/modules/setting.ts +447 -14
- package/template/base/src/store/modules/table.ts +97 -0
- package/template/base/src/store/modules/user.ts +78 -0
- package/template/base/src/store/modules/worktab.ts +568 -0
- package/template/base/src/types/api/api.d.ts +138 -0
- package/template/base/src/types/common/index.ts +95 -0
- package/template/base/src/types/common/response.ts +30 -0
- package/template/base/src/types/component/chart.ts +324 -0
- package/template/base/src/types/component/index.ts +145 -0
- package/template/base/src/types/config/index.ts +211 -0
- package/template/base/src/types/directive/directive.d.ts +15 -0
- package/template/base/src/types/import/auto-imports.d.ts +319 -0
- package/template/base/src/types/index.ts +22 -0
- package/template/base/src/types/router/index.ts +80 -0
- package/template/base/src/types/store/index.ts +157 -0
- package/template/base/src/utils/constants/index.ts +8 -0
- package/template/base/src/utils/constants/links.ts +35 -0
- package/template/base/src/utils/form/index.ts +12 -0
- package/template/base/src/utils/form/responsive.ts +122 -0
- package/template/base/src/utils/form/validator.ts +316 -0
- package/template/base/src/utils/http/error.ts +153 -0
- package/template/base/src/utils/http/index.ts +44 -14
- package/template/base/src/utils/http/status.ts +18 -0
- package/template/base/src/utils/index.ts +31 -0
- package/template/base/src/utils/navigation/index.ts +10 -0
- package/template/base/src/utils/navigation/jump.ts +68 -0
- package/template/base/src/utils/navigation/route.ts +85 -0
- package/template/base/src/utils/navigation/worktab.ts +67 -0
- package/template/base/src/utils/router.ts +61 -0
- package/template/base/src/utils/storage/index.ts +7 -0
- package/template/base/src/utils/storage/storage-config.ts +125 -0
- package/template/base/src/utils/storage/storage-key-manager.ts +97 -0
- package/template/base/src/utils/storage/storage.ts +250 -0
- package/template/base/src/utils/sys/error-handle.ts +143 -0
- package/template/base/src/utils/sys/index.ts +6 -0
- package/template/base/src/utils/sys/mittBus.ts +63 -0
- package/template/base/src/utils/sys/upgrade.ts +277 -0
- package/template/base/src/utils/table/tableCache.ts +267 -0
- package/template/base/src/utils/table/tableConfig.ts +55 -0
- package/template/base/src/utils/table/tableUtils.ts +297 -0
- package/template/base/src/utils/ui/animation.ts +80 -0
- package/template/base/src/utils/ui/colors.ts +273 -0
- package/template/base/src/utils/ui/emojo.ts +24 -0
- package/template/base/src/utils/ui/iconify-loader.ts +31 -0
- package/template/base/src/utils/ui/index.ts +11 -0
- package/template/base/src/utils/ui/loading.ts +84 -0
- package/template/base/src/utils/ui/tabs.ts +60 -0
- package/template/base/src/views/dashboard/analysis/index.vue +50 -0
- package/template/base/src/views/dashboard/analysis/modules/customer-satisfaction.vue +42 -0
- package/template/base/src/views/dashboard/analysis/modules/sales-mapping-by-country.vue +19 -0
- package/template/base/src/views/dashboard/analysis/modules/target-vs-reality.vue +69 -0
- package/template/base/src/views/dashboard/analysis/modules/today-sales.vue +83 -0
- package/template/base/src/views/dashboard/analysis/modules/top-products.vue +89 -0
- package/template/base/src/views/dashboard/analysis/modules/total-revenue.vue +37 -0
- package/template/base/src/views/dashboard/analysis/modules/visitor-insights.vue +35 -0
- package/template/base/src/views/dashboard/analysis/modules/volume-service-level.vue +43 -0
- package/template/base/src/views/dashboard/console/index.vue +41 -0
- package/template/base/src/views/dashboard/console/modules/about-project.vue +44 -0
- package/template/base/src/views/dashboard/console/modules/active-user.vue +47 -0
- package/template/base/src/views/dashboard/console/modules/card-list.vue +74 -0
- package/template/base/src/views/dashboard/console/modules/dynamic-stats.vue +79 -0
- package/template/base/src/views/dashboard/console/modules/new-user.vue +169 -0
- package/template/base/src/views/dashboard/console/modules/sales-overview.vue +43 -0
- package/template/base/src/views/dashboard/console/modules/todo-list.vue +71 -0
- package/template/base/src/views/exception/403/index.vue +18 -0
- package/template/base/src/views/exception/404/index.vue +18 -0
- package/template/base/src/views/exception/500/index.vue +18 -0
- package/template/base/src/views/index/index.vue +19 -112
- package/template/base/src/views/index/style.scss +93 -0
- package/template/base/src/views/outside/Iframe.vue +42 -0
- package/template/base/tsconfig.app.json +18 -5
- package/template/base/tsconfig.json +2 -14
- package/template/base/tsconfig.node.json +8 -2
- package/template/base/vite.config.ts +59 -28
- package/template/feature-echarts/src/plugins/echarts.ts +56 -2
- package/template/feature-markdown/src/components/MdPreviewWrapper.vue +9 -9
- package/template/feature-sse/src/utils/sse.ts +1 -1
- package/template/scaffold-doc-governance/AGENTS.md +32 -0
- package/template/scaffold-doc-governance/docs/README.md +12 -12
- package/template/scaffold-doc-governance/docs/adr/0001-doc-governance.md +18 -18
- package/template/scaffold-doc-governance/docs/getting-started/quick-start.md +62 -0
- package/template/scaffold-doc-governance/docs/reference/cli.md +15 -15
- package/template/scaffold-doc-governance/docs/templates/adr.md +5 -0
- package/template/scaffold-doc-governance/docs/templates/incident.md +8 -0
- package/template/scaffold-doc-governance/docs/templates/requirement.md +12 -0
- package/template/scaffold-doc-governance/scripts/docs/lint-frontmatter.mjs +17 -6
- package/template/scaffold-doc-governance/scripts/docs/lint-naming.mjs +17 -9
- package/template/base/src/views/dashboard/index.vue +0 -42
- package/template/base/src/views/exception/403.vue +0 -25
- package/template/base/src/views/exception/404.vue +0 -25
- package/template/scaffold-doc-governance/_github/PULL_REQUEST_TEMPLATE.md +0 -28
package/dist/index.cjs
CHANGED
|
@@ -97,7 +97,7 @@ async function getProjectOptions(argv) {
|
|
|
97
97
|
{ title: ".reference \u53C2\u8003\u9879\u76EE\uFF08\u514B\u9686 art-design-pro \u6700\u65B0\u4EE3\u7801\uFF09", value: "reference", selected: true },
|
|
98
98
|
{ title: ".vscode \u7EDF\u4E00\u7F16\u8F91\u5668\u914D\u7F6E", value: "vscode", selected: true },
|
|
99
99
|
{ title: "AGENTS.md AI \u5F00\u53D1\u7EA6\u675F\u6587\u4EF6", value: "agentsMd", selected: true },
|
|
100
|
-
{ title: "\u6587\u6863\u6CBB\u7406\uFF08docs/ + 4 \u9053\u62A4\u680F
|
|
100
|
+
{ title: "\u6587\u6863\u6CBB\u7406\uFF08docs/ + 4 \u9053\u62A4\u680F\uFF09", value: "docGovernance", selected: true }
|
|
101
101
|
]
|
|
102
102
|
},
|
|
103
103
|
{
|
|
@@ -171,6 +171,24 @@ function getFeatureDeps(features) {
|
|
|
171
171
|
var import_node_fs = __toESM(require("fs"), 1);
|
|
172
172
|
var import_node_path = __toESM(require("path"), 1);
|
|
173
173
|
var import_ejs = __toESM(require("ejs"), 1);
|
|
174
|
+
var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
175
|
+
".png",
|
|
176
|
+
".jpg",
|
|
177
|
+
".jpeg",
|
|
178
|
+
".webp",
|
|
179
|
+
".gif",
|
|
180
|
+
".ico",
|
|
181
|
+
".bmp",
|
|
182
|
+
".avif",
|
|
183
|
+
".pdf",
|
|
184
|
+
".zip",
|
|
185
|
+
".gz",
|
|
186
|
+
".tgz",
|
|
187
|
+
".woff",
|
|
188
|
+
".woff2",
|
|
189
|
+
".ttf",
|
|
190
|
+
".eot"
|
|
191
|
+
]);
|
|
174
192
|
async function renderTemplate(templateDir, targetDir, options, skipFiles = []) {
|
|
175
193
|
const stats = import_node_fs.default.statSync(templateDir);
|
|
176
194
|
if (!stats.isDirectory()) return;
|
|
@@ -191,21 +209,31 @@ async function renderTemplate(templateDir, targetDir, options, skipFiles = []) {
|
|
|
191
209
|
}
|
|
192
210
|
async function renderFile(srcPath, targetDir, fileName, options) {
|
|
193
211
|
let destName = fileName;
|
|
194
|
-
let
|
|
212
|
+
let textContent = null;
|
|
213
|
+
let binaryContent = null;
|
|
195
214
|
if (fileName.endsWith(".ejs")) {
|
|
196
215
|
destName = fileName.slice(0, -4);
|
|
197
216
|
const template = import_node_fs.default.readFileSync(srcPath, "utf-8");
|
|
198
|
-
|
|
199
|
-
if (!
|
|
217
|
+
textContent = import_ejs.default.render(template, { options });
|
|
218
|
+
if (!textContent.trim()) return;
|
|
219
|
+
} else if (isBinaryTemplateFile(srcPath)) {
|
|
220
|
+
binaryContent = import_node_fs.default.readFileSync(srcPath);
|
|
200
221
|
} else {
|
|
201
|
-
|
|
222
|
+
textContent = import_node_fs.default.readFileSync(srcPath, "utf-8");
|
|
202
223
|
}
|
|
203
224
|
if (destName.startsWith("_")) {
|
|
204
225
|
destName = `.${destName.slice(1)}`;
|
|
205
226
|
}
|
|
206
227
|
const destPath = import_node_path.default.join(targetDir, destName);
|
|
207
228
|
import_node_fs.default.mkdirSync(import_node_path.default.dirname(destPath), { recursive: true });
|
|
208
|
-
|
|
229
|
+
if (binaryContent) {
|
|
230
|
+
import_node_fs.default.writeFileSync(destPath, binaryContent);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
import_node_fs.default.writeFileSync(destPath, textContent ?? "");
|
|
234
|
+
}
|
|
235
|
+
function isBinaryTemplateFile(filePath) {
|
|
236
|
+
return BINARY_EXTENSIONS.has(import_node_path.default.extname(filePath).toLowerCase());
|
|
209
237
|
}
|
|
210
238
|
async function renderEjsInPlace(targetDir, options) {
|
|
211
239
|
const files = getAllFiles(targetDir);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-art-app-pino",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "CLI scaffold tool for creating Art Design Pro based projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
"dist",
|
|
11
11
|
"template"
|
|
12
12
|
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"dev": "tsup --watch",
|
|
15
|
+
"build": "tsup",
|
|
16
|
+
"start": "node dist/index.cjs",
|
|
17
|
+
"prepublishOnly": "pnpm build"
|
|
18
|
+
},
|
|
13
19
|
"keywords": [
|
|
14
20
|
"cli",
|
|
15
21
|
"scaffold",
|
|
@@ -26,19 +32,30 @@
|
|
|
26
32
|
"prompts": "^2.4.2"
|
|
27
33
|
},
|
|
28
34
|
"devDependencies": {
|
|
35
|
+
"@element-plus/icons-vue": "^2.3.2",
|
|
36
|
+
"@iconify/vue": "^5.0.1",
|
|
29
37
|
"@types/ejs": "^3.1.5",
|
|
30
38
|
"@types/minimist": "^1.2.5",
|
|
31
39
|
"@types/node": "^22.10.0",
|
|
40
|
+
"@types/nprogress": "^0.2.3",
|
|
32
41
|
"@types/prompts": "^2.4.9",
|
|
42
|
+
"@vueuse/core": "^14.3.0",
|
|
43
|
+
"axios": "^1.18.0",
|
|
44
|
+
"echarts": "^6.1.0",
|
|
45
|
+
"element-plus": "^2.14.2",
|
|
46
|
+
"highlight.js": "^11.11.1",
|
|
47
|
+
"mitt": "^3.0.1",
|
|
48
|
+
"nprogress": "^0.2.0",
|
|
49
|
+
"ohash": "^2.0.11",
|
|
50
|
+
"pinia": "^3.0.4",
|
|
51
|
+
"pinia-plugin-persistedstate": "^4.7.1",
|
|
33
52
|
"tsup": "^8.3.5",
|
|
34
|
-
"typescript": "^5.7.2"
|
|
53
|
+
"typescript": "^5.7.2",
|
|
54
|
+
"vue": "^3.5.38",
|
|
55
|
+
"vue-i18n": "^11.4.5",
|
|
56
|
+
"vue-router": "^5.1.0"
|
|
35
57
|
},
|
|
36
58
|
"publishConfig": {
|
|
37
59
|
"registry": "https://registry.npmjs.org"
|
|
38
|
-
},
|
|
39
|
-
"scripts": {
|
|
40
|
-
"dev": "tsup --watch",
|
|
41
|
-
"build": "tsup",
|
|
42
|
-
"start": "node dist/index.cjs"
|
|
43
60
|
}
|
|
44
|
-
}
|
|
61
|
+
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { Router } from 'vue-router'
|
|
2
2
|
import NProgress from 'nprogress'
|
|
3
|
-
import { useUserStore } from '@/store/modules/user'
|
|
4
3
|
import { fetchGetUserInfo } from '@/api/auth'
|
|
4
|
+
import { useUserStore } from '@/store/modules/user'
|
|
5
|
+
import { useMenuStore } from '@/store/modules/menu'
|
|
6
|
+
import { setWorktab } from '@/utils/navigation'
|
|
7
|
+
import { setPageTitle } from '@/utils/router'
|
|
8
|
+
import { MenuProcessor, RouteRegistry } from '@/router/core'
|
|
5
9
|
|
|
6
10
|
// 是否已获取过用户信息
|
|
7
11
|
let hasLoadedUserInfo = false
|
|
@@ -25,8 +29,9 @@ export function setupBeforeEachGuard(router: Router): void {
|
|
|
25
29
|
// 访问登录页直接放行
|
|
26
30
|
if (to.path === '/login') {
|
|
27
31
|
if (userStore.isLogin) {
|
|
28
|
-
next('/')
|
|
29
|
-
}
|
|
32
|
+
next('/dashboard/console')
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
30
35
|
next()
|
|
31
36
|
}
|
|
32
37
|
return
|
|
@@ -45,9 +50,10 @@ export function setupBeforeEachGuard(router: Router): void {
|
|
|
45
50
|
if (!hasLoadedUserInfo) {
|
|
46
51
|
try {
|
|
47
52
|
const userInfo = await fetchGetUserInfo()
|
|
48
|
-
userStore.setUserInfo(userInfo
|
|
53
|
+
userStore.setUserInfo(userInfo)
|
|
49
54
|
hasLoadedUserInfo = true
|
|
50
|
-
}
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
51
57
|
console.error('[Router] 获取用户信息失败:', error)
|
|
52
58
|
userStore.logOut()
|
|
53
59
|
next({ path: '/login' })
|
|
@@ -55,6 +61,27 @@ export function setupBeforeEachGuard(router: Router): void {
|
|
|
55
61
|
}
|
|
56
62
|
}
|
|
57
63
|
|
|
64
|
+
// 初始化菜单和动态路由
|
|
65
|
+
const menuStore = useMenuStore()
|
|
66
|
+
if (menuStore.menuList.length === 0) {
|
|
67
|
+
try {
|
|
68
|
+
const menuProcessor = new MenuProcessor()
|
|
69
|
+
const menuList = await menuProcessor.getMenuList()
|
|
70
|
+
menuStore.setMenuList(menuList)
|
|
71
|
+
|
|
72
|
+
const routeRegistry = new RouteRegistry(router)
|
|
73
|
+
routeRegistry.register(menuList)
|
|
74
|
+
|
|
75
|
+
// 注册动态路由后,进行重定向跳转以使新路由生效
|
|
76
|
+
next({ ...to, replace: true })
|
|
77
|
+
return
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.error('[Router] 初始化菜单或路由失败:', error)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
setWorktab(to)
|
|
84
|
+
setPageTitle(to)
|
|
58
85
|
next()
|
|
59
86
|
})
|
|
60
87
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
|
|
2
1
|
import type { RouteRecordRaw } from 'vue-router'
|
|
2
|
+
import { createRouter, <%- options.routerMode === 'hash' ? 'createWebHashHistory' : 'createWebHistory' %> } from 'vue-router'
|
|
3
3
|
import { setupBeforeEachGuard } from './guards/beforeEach'
|
|
4
4
|
|
|
5
5
|
const routes: RouteRecordRaw[] = [
|
|
@@ -11,30 +11,56 @@ const routes: RouteRecordRaw[] = [
|
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
path: '/',
|
|
14
|
-
|
|
14
|
+
redirect: '/dashboard/console',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
path: '/dashboard',
|
|
18
|
+
name: 'Dashboard',
|
|
15
19
|
component: () => import('@/views/index/index.vue'),
|
|
16
|
-
redirect: '/dashboard',
|
|
20
|
+
redirect: '/dashboard/console',
|
|
21
|
+
meta: { title: '仪表盘', icon: 'ri:pie-chart-line' },
|
|
17
22
|
children: [
|
|
18
23
|
{
|
|
19
|
-
path: '
|
|
20
|
-
name: '
|
|
21
|
-
component: () => import('@/views/dashboard/index.vue'),
|
|
22
|
-
meta: {
|
|
24
|
+
path: 'console',
|
|
25
|
+
name: 'Console',
|
|
26
|
+
component: () => import('@/views/dashboard/console/index.vue'),
|
|
27
|
+
meta: {
|
|
28
|
+
title: '工作台',
|
|
29
|
+
icon: 'ri:home-smile-2-line',
|
|
30
|
+
keepAlive: false,
|
|
31
|
+
fixedTab: true,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
path: 'analysis',
|
|
36
|
+
name: 'Analysis',
|
|
37
|
+
component: () => import('@/views/dashboard/analysis/index.vue'),
|
|
38
|
+
meta: {
|
|
39
|
+
title: '分析页',
|
|
40
|
+
icon: 'ri:align-item-bottom-line',
|
|
41
|
+
keepAlive: false,
|
|
42
|
+
},
|
|
23
43
|
},
|
|
24
44
|
],
|
|
25
45
|
},
|
|
26
46
|
{
|
|
27
47
|
path: '/403',
|
|
28
48
|
name: 'Forbidden',
|
|
29
|
-
component: () => import('@/views/exception/403.vue'),
|
|
49
|
+
component: () => import('@/views/exception/403/index.vue'),
|
|
30
50
|
meta: { title: '403' },
|
|
31
51
|
},
|
|
32
52
|
{
|
|
33
53
|
path: '/404',
|
|
34
54
|
name: 'NotFound',
|
|
35
|
-
component: () => import('@/views/exception/404.vue'),
|
|
55
|
+
component: () => import('@/views/exception/404/index.vue'),
|
|
36
56
|
meta: { title: '404' },
|
|
37
57
|
},
|
|
58
|
+
{
|
|
59
|
+
path: '/500',
|
|
60
|
+
name: 'ServerError',
|
|
61
|
+
component: () => import('@/views/exception/500/index.vue'),
|
|
62
|
+
meta: { title: '500' },
|
|
63
|
+
},
|
|
38
64
|
{
|
|
39
65
|
path: '/:pathMatch(.*)*',
|
|
40
66
|
redirect: '/404',
|
|
@@ -49,4 +75,6 @@ const router = createRouter({
|
|
|
49
75
|
// 设置路由守卫
|
|
50
76
|
setupBeforeEachGuard(router)
|
|
51
77
|
|
|
78
|
+
export const HOME_PAGE_PATH = ''
|
|
79
|
+
export { router }
|
|
52
80
|
export default router
|
|
@@ -1,56 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 用户状态管理(auth-art 版本)
|
|
3
|
+
* 管理用户登录状态、个人信息、语言设置等
|
|
4
|
+
* 基于 Art Design Pro 的 user store 适配
|
|
5
|
+
*/
|
|
1
6
|
import { defineStore } from 'pinia'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
7
|
+
import { computed, ref } from 'vue'
|
|
8
|
+
import { LanguageEnum } from '@/enums/appEnum'
|
|
9
|
+
import { router } from '@/router'
|
|
10
|
+
import { useSettingStore } from './setting'
|
|
11
|
+
import { useMenuStore } from './menu'
|
|
12
|
+
import { setPageTitle } from '@/utils/router'
|
|
13
|
+
import { resetRouterState } from '@/router/guards/beforeEach'
|
|
14
|
+
|
|
15
|
+
export interface UserInfo {
|
|
16
|
+
roles?: string[]
|
|
17
|
+
buttons?: string[]
|
|
18
|
+
userId?: string | number
|
|
19
|
+
[key: string]: any
|
|
20
|
+
}
|
|
4
21
|
|
|
5
22
|
export const useUserStore = defineStore(
|
|
6
23
|
'userStore',
|
|
7
24
|
() => {
|
|
8
|
-
const
|
|
9
|
-
|
|
25
|
+
const language = ref(LanguageEnum.ZH)
|
|
10
26
|
const isLogin = ref(false)
|
|
27
|
+
const isLock = ref(false)
|
|
28
|
+
const lockPassword = ref('')
|
|
29
|
+
const info = ref<UserInfo>({})
|
|
30
|
+
const searchHistory = ref<Record<string, unknown>[]>([])
|
|
11
31
|
const accessToken = ref('')
|
|
12
32
|
const refreshToken = ref('')
|
|
13
|
-
const info = ref<Record<string, any>>({})
|
|
14
33
|
|
|
15
34
|
const getUserInfo = computed(() => info.value)
|
|
35
|
+
const getSettingState = computed(() => useSettingStore().$state)
|
|
16
36
|
|
|
17
|
-
|
|
37
|
+
const setUserInfo = (newInfo: UserInfo) => {
|
|
18
38
|
info.value = newInfo
|
|
19
39
|
}
|
|
20
40
|
|
|
21
|
-
|
|
41
|
+
const setLoginStatus = (status: boolean) => {
|
|
22
42
|
isLogin.value = status
|
|
23
43
|
}
|
|
24
44
|
|
|
25
|
-
|
|
45
|
+
const setLanguage = (lang: LanguageEnum) => {
|
|
46
|
+
setPageTitle(router.currentRoute.value)
|
|
47
|
+
language.value = lang
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const setSearchHistory = (list: Record<string, unknown>[]) => {
|
|
51
|
+
searchHistory.value = list
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const setLockStatus = (status: boolean) => {
|
|
55
|
+
isLock.value = status
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const setLockPassword = (password: string) => {
|
|
59
|
+
lockPassword.value = password
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const setToken = (newAccessToken: string, newRefreshToken?: string) => {
|
|
26
63
|
accessToken.value = newAccessToken
|
|
27
64
|
if (newRefreshToken) {
|
|
28
65
|
refreshToken.value = newRefreshToken
|
|
29
66
|
}
|
|
30
67
|
}
|
|
31
68
|
|
|
32
|
-
|
|
69
|
+
const logOut = () => {
|
|
33
70
|
info.value = {}
|
|
34
71
|
isLogin.value = false
|
|
72
|
+
isLock.value = false
|
|
73
|
+
lockPassword.value = ''
|
|
35
74
|
accessToken.value = ''
|
|
36
75
|
refreshToken.value = ''
|
|
37
|
-
|
|
76
|
+
sessionStorage.removeItem('iframeRoutes')
|
|
77
|
+
useMenuStore().setHomePath('')
|
|
78
|
+
resetRouterState()
|
|
38
79
|
const currentRoute = router.currentRoute.value
|
|
39
80
|
const redirect = currentRoute.path !== '/login' ? currentRoute.fullPath : undefined
|
|
40
81
|
router.push({
|
|
41
|
-
|
|
82
|
+
name: 'Login',
|
|
42
83
|
query: redirect ? { redirect } : undefined,
|
|
43
84
|
})
|
|
44
85
|
}
|
|
45
86
|
|
|
46
87
|
return {
|
|
88
|
+
language,
|
|
47
89
|
isLogin,
|
|
90
|
+
isLock,
|
|
91
|
+
lockPassword,
|
|
92
|
+
info,
|
|
93
|
+
searchHistory,
|
|
48
94
|
accessToken,
|
|
49
95
|
refreshToken,
|
|
50
|
-
info,
|
|
51
96
|
getUserInfo,
|
|
97
|
+
getSettingState,
|
|
52
98
|
setUserInfo,
|
|
53
99
|
setLoginStatus,
|
|
100
|
+
setLanguage,
|
|
101
|
+
setSearchHistory,
|
|
102
|
+
setLockStatus,
|
|
103
|
+
setLockPassword,
|
|
54
104
|
setToken,
|
|
55
105
|
logOut,
|
|
56
106
|
}
|
|
@@ -2,12 +2,16 @@ import type { AxiosRequestConfig } from 'axios'
|
|
|
2
2
|
import axios from 'axios'
|
|
3
3
|
import { ElMessage } from 'element-plus'
|
|
4
4
|
import { useUserStore } from '@/store/modules/user'
|
|
5
|
+
import { setupMock } from './mock'
|
|
5
6
|
|
|
6
7
|
const http = axios.create({
|
|
7
8
|
baseURL: import.meta.env.VITE_API_BASE_URL || '',
|
|
8
9
|
timeout: 30000,
|
|
9
10
|
})
|
|
10
11
|
|
|
12
|
+
// 启用 Mock 拦截器(仅 VITE_MOCK_ENABLED=true 时生效)
|
|
13
|
+
setupMock(http)
|
|
14
|
+
|
|
11
15
|
// 请求拦截器:注入 token
|
|
12
16
|
http.interceptors.request.use(
|
|
13
17
|
(config) => {
|
|
@@ -23,7 +27,17 @@ http.interceptors.request.use(
|
|
|
23
27
|
// 响应拦截器:处理 401 和业务错误
|
|
24
28
|
http.interceptors.response.use(
|
|
25
29
|
(response) => {
|
|
26
|
-
|
|
30
|
+
const res = response.data
|
|
31
|
+
// 剥离业务响应包装
|
|
32
|
+
if (res && typeof res === 'object' && 'code' in res) {
|
|
33
|
+
if (res.code === 0) {
|
|
34
|
+
return res.data
|
|
35
|
+
}
|
|
36
|
+
const message = res.message || '请求失败'
|
|
37
|
+
ElMessage.error(message)
|
|
38
|
+
return Promise.reject(new Error(message))
|
|
39
|
+
}
|
|
40
|
+
return res
|
|
27
41
|
},
|
|
28
42
|
(error) => {
|
|
29
43
|
if (error.response?.status === 401) {
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { AxiosInstance, InternalAxiosRequestConfig } from 'axios'
|
|
2
|
+
|
|
3
|
+
interface MockRoute {
|
|
4
|
+
method: string
|
|
5
|
+
url: string
|
|
6
|
+
handler: (config: InternalAxiosRequestConfig) => unknown
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const MOCK_TOKEN = 'mock-art-token-local-dev'
|
|
10
|
+
|
|
11
|
+
const mockRoutes: MockRoute[] = [
|
|
12
|
+
{
|
|
13
|
+
method: 'post',
|
|
14
|
+
url: '/api/auth/login',
|
|
15
|
+
handler: (config) => {
|
|
16
|
+
const body = typeof config.data === 'string' ? JSON.parse(config.data) : config.data
|
|
17
|
+
const username = body?.userName?.toLowerCase()
|
|
18
|
+
const password = body?.password
|
|
19
|
+
|
|
20
|
+
const isValid = (
|
|
21
|
+
(username === 'super' && password === '123456') ||
|
|
22
|
+
(username === 'admin' && password === '123456') ||
|
|
23
|
+
(username === 'user' && password === '123456') ||
|
|
24
|
+
(username === 'admin' && password === 'admin')
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
if (isValid) {
|
|
28
|
+
const role = username === 'super' ? 'R_SUPER' : (username === 'user' ? 'R_USER' : 'R_ADMIN')
|
|
29
|
+
return { code: 0, data: { token: `${MOCK_TOKEN}-${role}`, refreshToken: MOCK_TOKEN } }
|
|
30
|
+
}
|
|
31
|
+
return { code: 401, message: '用户名或密码错误' }
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
method: 'get',
|
|
36
|
+
url: '/api/user/info',
|
|
37
|
+
handler: (config) => {
|
|
38
|
+
const authHeader = (config.headers as any)?.Authorization as string || ''
|
|
39
|
+
const role = authHeader.includes('R_ADMIN') ? 'R_ADMIN' : (authHeader.includes('R_USER') ? 'R_USER' : 'R_SUPER')
|
|
40
|
+
const name = role === 'R_SUPER' ? 'Super' : (role === 'R_USER' ? 'User' : 'Admin')
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
code: 0,
|
|
44
|
+
data: { userId: 1, userName: name, roles: [role], avatar: '/src/assets/images/user/avatar.webp' },
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
method: 'get',
|
|
50
|
+
url: '/api/v3/system/menus',
|
|
51
|
+
handler: () => ({
|
|
52
|
+
code: 0,
|
|
53
|
+
data: [
|
|
54
|
+
{
|
|
55
|
+
path: '/dashboard',
|
|
56
|
+
name: 'Dashboard',
|
|
57
|
+
component: '/dashboard/console/index',
|
|
58
|
+
meta: { title: '仪表盘', icon: 'ep:home-filled' },
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
}),
|
|
62
|
+
},
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 在 VITE_MOCK_ENABLED=true 时启用本地 mock 拦截器
|
|
67
|
+
* 无需后端即可 admin/admin 登录并获取用户信息
|
|
68
|
+
*/
|
|
69
|
+
export function setupMock(instance: AxiosInstance) {
|
|
70
|
+
if (import.meta.env.VITE_MOCK_ENABLED !== 'true')
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
instance.interceptors.request.use((config) => {
|
|
74
|
+
const matched = mockRoutes.find(
|
|
75
|
+
r => r.method === (config.method || 'get').toLowerCase()
|
|
76
|
+
&& config.url?.includes(r.url),
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
if (matched) {
|
|
80
|
+
// 标记为 mock 请求,用 adapter 直接返回数据
|
|
81
|
+
const result = matched.handler(config)
|
|
82
|
+
config.adapter = () =>
|
|
83
|
+
Promise.resolve({
|
|
84
|
+
data: result,
|
|
85
|
+
status: 200,
|
|
86
|
+
statusText: 'OK',
|
|
87
|
+
headers: {},
|
|
88
|
+
config,
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return config
|
|
93
|
+
})
|
|
94
|
+
}
|