commit 5316a233850e778e75350bd6c0809979412b8df1 Author: 浅念 Date: Mon Dec 22 11:40:28 2025 +0800 提交 diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..ec6c9a4 --- /dev/null +++ b/.env.development @@ -0,0 +1,17 @@ +# 【开发】环境变量 + +# 网站地址前缀 +VITE_BASE_URL = / + +# API 地址前缀 +# VITE_API_URL = https://m1.apifoxmock.com/m1/6400575-6097373-default +# VITE_API_URL = https://bsh.yw.server.hnzhwlkj.cn +VITE_API_URL = https://bsh.info.yw.hnzhwlkj.cn +# VITE_API_URL = https://fdesk.hnxinyouhe.com +# VITE_API_URL = https://x-server.hnxinyouhe.com + +# VITE_API_URL_WSS = wss://mzl.dev.hnxinyouhe.com +# VITE_API_URL_WSS = wss://fdesk.hnxinyouhe.com +# VITE_API_URL_WSS = wss://x-server.hnxinyouhe.com +# Delete console +VITE_DROP_CONSOLE = false \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..438a2c8 --- /dev/null +++ b/.env.production @@ -0,0 +1,13 @@ +# 【生产】环境变量 + +# 网站地址前缀 +VITE_BASE_URL = / + +# API 地址前缀 +# VITE_API_URL = https://fdesk.hnxinyouhe.com +# VITE_API_URL = https://mzl.dev.hnxinyouhe.com +VITE_API_URL = https://bsh.info.yw.hnzhwlkj.cn +# VITE_API_URL_WSS = wss://fdesk.hnxinyouhe.com +# VITE_API_URL_WSS = wss://x-server.hnxinyouhe.com +# Delete console +VITE_DROP_CONSOLE = true \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..866e8ee --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +*.html linguist-detectable=false +*.vue linguist-detectable=true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..559e693 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local +*.env +.cursorrules +src/types/components.d.ts +src/types/auto-imports.d.ts +.vscode +.auto-import.json \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..9e96efc --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +/node_modules/* +/dist/* +/src/main.ts \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..f3d6ad5 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,20 @@ +{ + "printWidth": 100, + "tabWidth": 2, + "useTabs": false, + "semi": false, + "vueIndentScriptAndStyle": true, + "singleQuote": true, + "quoteProps": "as-needed", + "bracketSpacing": true, + "trailingComma": "none", + "bracketSameLine": false, + "jsxSingleQuote": false, + "arrowParens": "always", + "insertPragma": false, + "requirePragma": false, + "proseWrap": "never", + "htmlWhitespaceSensitivity": "strict", + "endOfLine": "auto", + "rangeStart": 0 +} diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 0000000..476ea45 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,9 @@ +dist +node_modules +public +.husky +.vscode + +src/components/Layout/MenuLeft/index.vue +src/assets +stats.html \ No newline at end of file diff --git a/.stylelintrc.cjs b/.stylelintrc.cjs new file mode 100644 index 0000000..c6588f2 --- /dev/null +++ b/.stylelintrc.cjs @@ -0,0 +1,62 @@ +module.exports = { + // 继承推荐规范配置 + extends: [ + 'stylelint-config-standard', + 'stylelint-config-recommended-scss', + 'stylelint-config-recommended-vue/scss', + 'stylelint-config-html/vue', + 'stylelint-config-recess-order' + ], + // 指定不同文件对应的解析器 + overrides: [ + { + files: ['**/*.{vue,html}'], + customSyntax: 'postcss-html' + }, + { + files: ['**/*.{css,scss}'], + customSyntax: 'postcss-scss' + } + ], + // 自定义规则 + rules: { + 'import-notation': 'string', // 指定导入CSS文件的方式("string"|"url") + 'selector-class-pattern': null, // 选择器类名命名规则 + 'custom-property-pattern': null, // 自定义属性命名规则 + 'keyframes-name-pattern': null, // 动画帧节点样式命名规则 + 'no-descending-specificity': null, // 允许无降序特异性 + 'no-empty-source': null, // 允许空样式 + // 允许 global 、export 、deep伪类 + 'selector-pseudo-class-no-unknown': [ + true, + { + ignorePseudoClasses: ['global', 'export', 'deep'] + } + ], + // 允许未知属性 + 'property-no-unknown': [ + true, + { + ignoreProperties: [] + } + ], + // 允许未知规则 + 'at-rule-no-unknown': [ + true, + { + ignoreAtRules: [ + 'apply', + 'use', + 'mixin', + 'include', + 'extend', + 'each', + 'if', + 'else', + 'for', + 'while' + ] + } + ] + } +} diff --git a/commitlint.config.cjs b/commitlint.config.cjs new file mode 100644 index 0000000..2d883ea --- /dev/null +++ b/commitlint.config.cjs @@ -0,0 +1,97 @@ +/** + * commitlint 配置文件 + * 文档 + * https://commitlint.js.org/#/reference-rules + * https://cz-git.qbb.sh/zh/guide/ + */ + +module.exports = { + // 继承的规则 + extends: ['@commitlint/config-conventional'], + // 自定义规则 + rules: { + // 提交类型枚举,git提交type必须是以下类型 + 'type-enum': [ + 2, + 'always', + [ + 'feat', // 新增功能 + 'fix', // 修复缺陷 + 'docs', // 文档变更 + 'style', // 代码格式(不影响功能,例如空格、分号等格式修正) + 'refactor', // 代码重构(不包括 bug 修复、功能新增) + 'perf', // 性能优化 + 'test', // 添加疏漏测试或已有测试改动 + 'build', // 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等) + 'ci', // 修改 CI 配置、脚本 + 'revert', // 回滚 commit + 'chore', // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例) + 'wip' // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例) + ] + ], + 'subject-case': [0] // subject大小写不做校验 + }, + + prompt: { + messages: { + type: '选择你要提交的类型 :', + scope: '选择一个提交范围(可选):', + customScope: '请输入自定义的提交范围 :', + subject: '填写简短精炼的变更描述 :\n', + body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n', + breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n', + footerPrefixesSelect: '选择关联issue前缀(可选):', + customFooterPrefix: '输入自定义issue前缀 :', + footer: '列举关联issue (可选) 例如: #31, #I3244 :\n', + generatingByAI: '正在通过 AI 生成你的提交简短描述...', + generatedSelectByAI: '选择一个 AI 生成的简短描述:', + confirmCommit: '是否提交或修改commit ?' + }, + // prettier-ignore + types: [ + { value: "feat", name: "特性: 新增功能" }, + { value: "fix", name: "修复: 修复缺陷" }, + { value: "docs", name: "文档: 文档变更(更新README文件,或者注释)" }, + { value: "style", name: "格式: 代码格式(空格、格式化、缺失的分号等)" }, + { value: "refactor", name: "重构: 代码重构(不修复错误也不添加特性的代码更改)" }, + { value: "perf", name: "性能: 性能优化" }, + { value: "test", name: "测试: 添加疏漏测试或已有测试改动" }, + { value: "build", name: "构建: 构建流程、外部依赖变更(如升级 npm 包、修改 vite 配置等)" }, + { value: "ci", name: "集成: 修改 CI 配置、脚本" }, + { value: "revert", name: "回退: 回滚 commit" }, + { value: "chore", name: "其他: 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)" }, + ], + useEmoji: true, + emojiAlign: 'center', + useAI: false, + aiNumber: 1, + themeColorCode: '', + scopes: [], + allowCustomScopes: true, + allowEmptyScopes: true, + customScopesAlign: 'bottom', + customScopesAlias: 'custom', + emptyScopesAlias: 'empty', + upperCaseSubject: false, + markBreakingChangeMode: false, + allowBreakingChanges: ['feat', 'fix'], + breaklineNumber: 100, + breaklineChar: '|', + skipQuestions: ['breaking', 'footerPrefix', 'footer'], // 跳过的步骤 + issuePrefixes: [{ value: 'closed', name: 'closed: ISSUES has been processed' }], + customIssuePrefixAlign: 'top', + emptyIssuePrefixAlias: 'skip', + customIssuePrefixAlias: 'custom', + allowCustomIssuePrefix: true, + allowEmptyIssuePrefix: true, + confirmColorize: true, + maxHeaderLength: Infinity, + maxSubjectLength: Infinity, + minSubjectLength: 0, + scopeOverrides: undefined, + defaultBody: '', + defaultIssues: '', + defaultScope: '', + defaultSubject: '' + } +} diff --git a/components.d.ts b/components.d.ts new file mode 100644 index 0000000..6ad3a14 --- /dev/null +++ b/components.d.ts @@ -0,0 +1,70 @@ +/* eslint-disable */ +// @ts-nocheck +// Generated by unplugin-vue-components +// Read more: https://github.com/vuejs/core/pull/3399 +export {} + +/* prettier-ignore */ +declare module 'vue' { + export interface GlobalComponents { + ArtBackToTop: typeof import('./src/components/core/base/ArtBackToTop.vue')['default'] + ArtBarChart: typeof import('./src/components/core/charts/ArtBarChart.vue')['default'] + ArtBarChartCard: typeof import('./src/components/core/cards/ArtBarChartCard.vue')['default'] + ArtBasicBanner: typeof import('./src/components/core/banners/ArtBasicBanner.vue')['default'] + ArtBreadcrumb: typeof import('./src/components/core/layouts/art-breadcrumb/index.vue')['default'] + ArtButtonMore: typeof import('./src/components/core/forms/ArtButtonMore.vue')['default'] + ArtButtonTable: typeof import('./src/components/core/forms/ArtButtonTable.vue')['default'] + ArtCardBanner: typeof import('./src/components/core/banners/ArtCardBanner.vue')['default'] + ArtChatWindow: typeof import('./src/components/core/layouts/art-chat-window/index.vue')['default'] + ArtCutterImg: typeof import('./src/components/core/media/ArtCutterImg.vue')['default'] + ArtDataListCard: typeof import('./src/components/core/cards/ArtDataListCard.vue')['default'] + ArtDonutChartCard: typeof import('./src/components/core/cards/ArtDonutChartCard.vue')['default'] + ArtDragVerify: typeof import('./src/components/core/forms/ArtDragVerify.vue')['default'] + ArtDualBarCompareChart: typeof import('./src/components/core/charts/ArtDualBarCompareChart.vue')['default'] + ArtExcelExport: typeof import('./src/components/core/forms/ArtExcelExport.vue')['default'] + ArtExcelImport: typeof import('./src/components/core/forms/ArtExcelImport.vue')['default'] + ArtException: typeof import('./src/components/core/views/exception/ArtException.vue')['default'] + ArtFastEnter: typeof import('./src/components/core/layouts/art-fast-enter/index.vue')['default'] + ArtFestivalTextScroll: typeof import('./src/components/core/text-effect/ArtFestivalTextScroll.vue')['default'] + ArtFireworksEffect: typeof import('./src/components/core/layouts/art-fireworks-effect/index.vue')['default'] + ArtFormInput: typeof import('./src/components/core/forms/ArtFormInput.vue')['default'] + ArtFormSelect: typeof import('./src/components/core/forms/ArtFormSelect.vue')['default'] + ArtGlobalSearch: typeof import('./src/components/core/layouts/art-global-search/index.vue')['default'] + ArtHBarChart: typeof import('./src/components/core/charts/ArtHBarChart.vue')['default'] + ArtHeaderBar: typeof import('./src/components/core/layouts/art-header-bar/index.vue')['default'] + ArtHorizontalMenu: typeof import('./src/components/core/layouts/art-menus/art-horizontal-menu/index.vue')['default'] + ArtIconSelector: typeof import('./src/components/core/base/ArtIconSelector.vue')['default'] + ArtImageCard: typeof import('./src/components/core/cards/ArtImageCard.vue')['default'] + ArtKLineChart: typeof import('./src/components/core/charts/ArtKLineChart.vue')['default'] + ArtLineChart: typeof import('./src/components/core/charts/ArtLineChart.vue')['default'] + ArtLineChartCard: typeof import('./src/components/core/cards/ArtLineChartCard.vue')['default'] + ArtMapChart: typeof import('./src/components/core/charts/ArtMapChart.vue')['default'] + ArtMenuRight: typeof import('./src/components/core/others/ArtMenuRight.vue')['default'] + ArtMixedMenu: typeof import('./src/components/core/layouts/art-menus/art-mixed-menu/index.vue')['default'] + ArtNetwork: typeof import('./src/components/core/base/ArtNetwork.vue')['default'] + ArtNotification: typeof import('./src/components/core/layouts/art-notification/index.vue')['default'] + ArtPageContent: typeof import('./src/components/core/layouts/art-page-content/index.vue')['default'] + ArtProgressCard: typeof import('./src/components/core/cards/ArtProgressCard.vue')['default'] + ArtRadarChart: typeof import('./src/components/core/charts/ArtRadarChart.vue')['default'] + ArtRingChart: typeof import('./src/components/core/charts/ArtRingChart.vue')['default'] + ArtScatterChart: typeof import('./src/components/core/charts/ArtScatterChart.vue')['default'] + ArtScreenLock: typeof import('./src/components/core/layouts/art-screen-lock/index.vue')['default'] + ArtSettingsPanel: typeof import('./src/components/core/layouts/art-settings-panel/index.vue')['default'] + ArtSidebarMenu: typeof import('./src/components/core/layouts/art-menus/art-sidebar-menu/index.vue')['default'] + ArtStatsCard: typeof import('./src/components/core/cards/ArtStatsCard.vue')['default'] + ArtTable: typeof import('./src/components/core/tables/ArtTable.vue')['default'] + ArtTableBar: typeof import('./src/components/core/tables/ArtTableBar.vue')['default'] + ArtTextScroll: typeof import('./src/components/core/text-effect/ArtTextScroll.vue')['default'] + ArtTimelineListCard: typeof import('./src/components/core/cards/ArtTimelineListCard.vue')['default'] + ArtVideoPlayer: typeof import('./src/components/core/media/ArtVideoPlayer.vue')['default'] + ArtWangEditor: typeof import('./src/components/core/forms/ArtWangEditor.vue')['default'] + ArtWatermark: typeof import('./src/components/core/others/ArtWatermark.vue')['default'] + ArtWorkTab: typeof import('./src/components/core/layouts/art-work-tab/index.vue')['default'] + BannerWidget: typeof import('./src/components/core/BannerWidget.vue')['default'] + HorizontalSubmenu: typeof import('./src/components/core/layouts/art-menus/art-horizontal-menu/widget/HorizontalSubmenu.vue')['default'] + LoginLeftView: typeof import('./src/components/core/views/login/LoginLeftView.vue')['default'] + RouterLink: typeof import('vue-router')['RouterLink'] + RouterView: typeof import('vue-router')['RouterView'] + SidebarSubmenu: typeof import('./src/components/core/layouts/art-menus/art-sidebar-menu/widget/SidebarSubmenu.vue')['default'] + } +} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..2e5dfb8 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,81 @@ +// 从 URL 和路径模块中导入必要的功能 +import fs from 'fs' +import path, { dirname } from 'path' +import { fileURLToPath } from 'url' + +// 从 ESLint 插件中导入推荐配置 +import pluginJs from '@eslint/js' +import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended' +import pluginVue from 'eslint-plugin-vue' +import globals from 'globals' +import tseslint from 'typescript-eslint' + +// 使用 import.meta.url 获取当前模块的路径 +const __filename = fileURLToPath(import.meta.url) +const __dirname = dirname(__filename) + +// 读取 .auto-import.json 文件的内容,并将其解析为 JSON 对象 +const autoImportConfig = JSON.parse( + fs.readFileSync(path.resolve(__dirname, '.auto-import.json'), 'utf-8') +) + +export default [ + // 指定文件匹配规则 + { + files: ['**/*.{js,mjs,cjs,ts,vue}'] + }, + // 指定全局变量和环境 + { + languageOptions: { + globals: { + ...globals.browser, + ...globals.node + } + } + }, + // 扩展配置 + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + ...pluginVue.configs['flat/essential'], + // 自定义规则 + { + // 针对所有 JavaScript、TypeScript 和 Vue 文件应用以下配置 + files: ['**/*.{js,mjs,cjs,ts,vue}'], + + languageOptions: { + globals: { + // 合并从 autoImportConfig 中读取的全局变量配置 + ...autoImportConfig.globals + } + }, + rules: { + quotes: ['error', 'single'], // 使用单引号 + semi: ['error', 'never'], // 语句末尾不加分号 + 'no-var': 'error', // 要求使用 let 或 const 而不是 var + '@typescript-eslint/no-explicit-any': 'off', // 禁用 any 检查 + 'vue/multi-word-component-names': 'off', // 禁用对 Vue 组件名称的多词要求检查 + 'no-multiple-empty-lines': ['warn', { max: 1 }], // 不允许多个空行 + 'no-unexpected-multiline': 'error' // 禁止空余的多行 + } + }, + // vue 规则 + { + files: ['**/*.vue'], + languageOptions: { + parserOptions: { parser: tseslint.parser } + } + }, + // 忽略文件 + { + ignores: [ + 'node_modules', + 'dist', + 'public', + '.vscode/**', + 'src/assets/**', + 'src/utils/console.ts' + ] + }, + // prettier 配置 + eslintPluginPrettierRecommended +] diff --git a/index.html b/index.html new file mode 100644 index 0000000..16755a9 --- /dev/null +++ b/index.html @@ -0,0 +1,15 @@ + + + + 系统管理 + + + + + + +
+ + + +