@ -0,0 +1,14 @@ |
|||
# http://editorconfig.org |
|||
root = true |
|||
|
|||
# 表示所有文件适用 |
|||
[*] |
|||
charset = utf-8 # 设置文件字符集为 utf-8 |
|||
end_of_line = lf # 控制换行类型(lf | cr | crlf) |
|||
indent_style = tab # 缩进风格(tab | space) |
|||
insert_final_newline = true # 始终在文件末尾插入一个新行 |
|||
|
|||
# 表示仅 md 文件适用以下规则 |
|||
[*.md] |
|||
max_line_length = off # 关闭最大行长度限制 |
|||
trim_trailing_whitespace = false # 关闭末尾空格修剪 |
|||
@ -0,0 +1,9 @@ |
|||
## 开发环境 |
|||
|
|||
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 |
|||
NODE_ENV='development' |
|||
|
|||
VITE_APP_TITLE = 'vue3-element-admin' |
|||
VITE_APP_PORT = 9999 |
|||
VITE_APP_BASE_API = '/dev-api' |
|||
VITE_APP_BASE_URL = 'http://myvuetest.net' |
|||
@ -0,0 +1,5 @@ |
|||
## 生产环境 |
|||
|
|||
VITE_APP_TITLE = '恒信高科' |
|||
VITE_APP_PORT = 17777 |
|||
VITE_APP_BASE_API = '/systemapi' |
|||
@ -0,0 +1,6 @@ |
|||
## 模拟环境 |
|||
NODE_ENV='staging' |
|||
|
|||
VITE_APP_TITLE = '恒信高科' |
|||
VITE_APP_PORT = 3000 |
|||
VITE_APP_BASE_API = '/prod--api' |
|||
@ -0,0 +1,14 @@ |
|||
dist |
|||
node_modules |
|||
public |
|||
.husky |
|||
.vscode |
|||
.idea |
|||
*.sh |
|||
*.md |
|||
|
|||
src/assets |
|||
|
|||
.eslintrc.cjs |
|||
.prettierrc.cjs |
|||
.stylelintrc.cjs |
|||
@ -0,0 +1,269 @@ |
|||
{ |
|||
"globals": { |
|||
"EffectScope": true, |
|||
"ElForm": true, |
|||
"ElMessage": true, |
|||
"ElMessageBox": true, |
|||
"ElTree": true, |
|||
"asyncComputed": true, |
|||
"autoResetRef": true, |
|||
"computed": true, |
|||
"computedAsync": true, |
|||
"computedEager": true, |
|||
"computedInject": true, |
|||
"computedWithControl": true, |
|||
"controlledComputed": true, |
|||
"controlledRef": true, |
|||
"createApp": true, |
|||
"createEventHook": true, |
|||
"createGlobalState": true, |
|||
"createInjectionState": true, |
|||
"createReactiveFn": true, |
|||
"createSharedComposable": true, |
|||
"createUnrefFn": true, |
|||
"customRef": true, |
|||
"debouncedRef": true, |
|||
"debouncedWatch": true, |
|||
"defineAsyncComponent": true, |
|||
"defineComponent": true, |
|||
"eagerComputed": true, |
|||
"effectScope": true, |
|||
"extendRef": true, |
|||
"getCurrentInstance": true, |
|||
"getCurrentScope": true, |
|||
"h": true, |
|||
"ignorableWatch": true, |
|||
"inject": true, |
|||
"isDefined": true, |
|||
"isProxy": true, |
|||
"isReactive": true, |
|||
"isReadonly": true, |
|||
"isRef": true, |
|||
"makeDestructurable": true, |
|||
"markRaw": true, |
|||
"nextTick": true, |
|||
"onActivated": true, |
|||
"onBeforeMount": true, |
|||
"onBeforeUnmount": true, |
|||
"onBeforeUpdate": true, |
|||
"onClickOutside": true, |
|||
"onDeactivated": true, |
|||
"onErrorCaptured": true, |
|||
"onKeyStroke": true, |
|||
"onLongPress": true, |
|||
"onMounted": true, |
|||
"onRenderTracked": true, |
|||
"onRenderTriggered": true, |
|||
"onScopeDispose": true, |
|||
"onServerPrefetch": true, |
|||
"onStartTyping": true, |
|||
"onUnmounted": true, |
|||
"onUpdated": true, |
|||
"pausableWatch": true, |
|||
"provide": true, |
|||
"reactify": true, |
|||
"reactifyObject": true, |
|||
"reactive": true, |
|||
"reactiveComputed": true, |
|||
"reactiveOmit": true, |
|||
"reactivePick": true, |
|||
"readonly": true, |
|||
"ref": true, |
|||
"refAutoReset": true, |
|||
"refDebounced": true, |
|||
"refDefault": true, |
|||
"refThrottled": true, |
|||
"refWithControl": true, |
|||
"resolveComponent": true, |
|||
"resolveDirective": true, |
|||
"resolveRef": true, |
|||
"resolveUnref": true, |
|||
"shallowReactive": true, |
|||
"shallowReadonly": true, |
|||
"shallowRef": true, |
|||
"syncRef": true, |
|||
"syncRefs": true, |
|||
"templateRef": true, |
|||
"throttledRef": true, |
|||
"throttledWatch": true, |
|||
"toRaw": true, |
|||
"toReactive": true, |
|||
"toRef": true, |
|||
"toRefs": true, |
|||
"triggerRef": true, |
|||
"tryOnBeforeMount": true, |
|||
"tryOnBeforeUnmount": true, |
|||
"tryOnMounted": true, |
|||
"tryOnScopeDispose": true, |
|||
"tryOnUnmounted": true, |
|||
"unref": true, |
|||
"unrefElement": true, |
|||
"until": true, |
|||
"useActiveElement": true, |
|||
"useArrayEvery": true, |
|||
"useArrayFilter": true, |
|||
"useArrayFind": true, |
|||
"useArrayFindIndex": true, |
|||
"useArrayFindLast": true, |
|||
"useArrayJoin": true, |
|||
"useArrayMap": true, |
|||
"useArrayReduce": true, |
|||
"useArraySome": true, |
|||
"useArrayUnique": true, |
|||
"useAsyncQueue": true, |
|||
"useAsyncState": true, |
|||
"useAttrs": true, |
|||
"useBase64": true, |
|||
"useBattery": true, |
|||
"useBluetooth": true, |
|||
"useBreakpoints": true, |
|||
"useBroadcastChannel": true, |
|||
"useBrowserLocation": true, |
|||
"useCached": true, |
|||
"useClipboard": true, |
|||
"useCloned": true, |
|||
"useColorMode": true, |
|||
"useConfirmDialog": true, |
|||
"useCounter": true, |
|||
"useCssModule": true, |
|||
"useCssVar": true, |
|||
"useCssVars": true, |
|||
"useCurrentElement": true, |
|||
"useCycleList": true, |
|||
"useDark": true, |
|||
"useDateFormat": true, |
|||
"useDebounce": true, |
|||
"useDebounceFn": true, |
|||
"useDebouncedRefHistory": true, |
|||
"useDeviceMotion": true, |
|||
"useDeviceOrientation": true, |
|||
"useDevicePixelRatio": true, |
|||
"useDevicesList": true, |
|||
"useDisplayMedia": true, |
|||
"useDocumentVisibility": true, |
|||
"useDraggable": true, |
|||
"useDropZone": true, |
|||
"useElementBounding": true, |
|||
"useElementByPoint": true, |
|||
"useElementHover": true, |
|||
"useElementSize": true, |
|||
"useElementVisibility": true, |
|||
"useEventBus": true, |
|||
"useEventListener": true, |
|||
"useEventSource": true, |
|||
"useEyeDropper": true, |
|||
"useFavicon": true, |
|||
"useFetch": true, |
|||
"useFileDialog": true, |
|||
"useFileSystemAccess": true, |
|||
"useFocus": true, |
|||
"useFocusWithin": true, |
|||
"useFps": true, |
|||
"useFullscreen": true, |
|||
"useGamepad": true, |
|||
"useGeolocation": true, |
|||
"useIdle": true, |
|||
"useImage": true, |
|||
"useInfiniteScroll": true, |
|||
"useIntersectionObserver": true, |
|||
"useInterval": true, |
|||
"useIntervalFn": true, |
|||
"useKeyModifier": true, |
|||
"useLastChanged": true, |
|||
"useLocalStorage": true, |
|||
"useMagicKeys": true, |
|||
"useManualRefHistory": true, |
|||
"useMediaControls": true, |
|||
"useMediaQuery": true, |
|||
"useMemoize": true, |
|||
"useMemory": true, |
|||
"useMounted": true, |
|||
"useMouse": true, |
|||
"useMouseInElement": true, |
|||
"useMousePressed": true, |
|||
"useMutationObserver": true, |
|||
"useNavigatorLanguage": true, |
|||
"useNetwork": true, |
|||
"useNow": true, |
|||
"useObjectUrl": true, |
|||
"useOffsetPagination": true, |
|||
"useOnline": true, |
|||
"usePageLeave": true, |
|||
"useParallax": true, |
|||
"usePermission": true, |
|||
"usePointer": true, |
|||
"usePointerLock": true, |
|||
"usePointerSwipe": true, |
|||
"usePreferredColorScheme": true, |
|||
"usePreferredContrast": true, |
|||
"usePreferredDark": true, |
|||
"usePreferredLanguages": true, |
|||
"usePreferredReducedMotion": true, |
|||
"usePrevious": true, |
|||
"useRafFn": true, |
|||
"useRefHistory": true, |
|||
"useResizeObserver": true, |
|||
"useScreenOrientation": true, |
|||
"useScreenSafeArea": true, |
|||
"useScriptTag": true, |
|||
"useScroll": true, |
|||
"useScrollLock": true, |
|||
"useSessionStorage": true, |
|||
"useShare": true, |
|||
"useSlots": true, |
|||
"useSorted": true, |
|||
"useSpeechRecognition": true, |
|||
"useSpeechSynthesis": true, |
|||
"useStepper": true, |
|||
"useStorage": true, |
|||
"useStorageAsync": true, |
|||
"useStyleTag": true, |
|||
"useSupported": true, |
|||
"useSwipe": true, |
|||
"useTemplateRefsList": true, |
|||
"useTextDirection": true, |
|||
"useTextSelection": true, |
|||
"useTextareaAutosize": true, |
|||
"useThrottle": true, |
|||
"useThrottleFn": true, |
|||
"useThrottledRefHistory": true, |
|||
"useTimeAgo": true, |
|||
"useTimeout": true, |
|||
"useTimeoutFn": true, |
|||
"useTimeoutPoll": true, |
|||
"useTimestamp": true, |
|||
"useTitle": true, |
|||
"useToNumber": true, |
|||
"useToString": true, |
|||
"useToggle": true, |
|||
"useTransition": true, |
|||
"useUrlSearchParams": true, |
|||
"useUserMedia": true, |
|||
"useVModel": true, |
|||
"useVModels": true, |
|||
"useVibrate": true, |
|||
"useVirtualList": true, |
|||
"useWakeLock": true, |
|||
"useWebNotification": true, |
|||
"useWebSocket": true, |
|||
"useWebWorker": true, |
|||
"useWebWorkerFn": true, |
|||
"useWindowFocus": true, |
|||
"useWindowScroll": true, |
|||
"useWindowSize": true, |
|||
"watch": true, |
|||
"watchArray": true, |
|||
"watchAtMost": true, |
|||
"watchDebounced": true, |
|||
"watchEffect": true, |
|||
"watchIgnorable": true, |
|||
"watchOnce": true, |
|||
"watchPausable": true, |
|||
"watchPostEffect": true, |
|||
"watchSyncEffect": true, |
|||
"watchThrottled": true, |
|||
"watchTriggerable": true, |
|||
"watchWithFilter": true, |
|||
"whenever": true |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
module.exports = { |
|||
env: { |
|||
browser: true, |
|||
es2021: true, |
|||
node: true, |
|||
}, |
|||
parser: "vue-eslint-parser", |
|||
extends: [ |
|||
// 参考vuejs官方的eslint配置: https://eslint.vuejs.org/user-guide/#usage |
|||
"plugin:vue/vue3-recommended", |
|||
"./.eslintrc-auto-import.json", |
|||
"prettier", |
|||
], |
|||
parserOptions: { |
|||
ecmaVersion: "latest", |
|||
sourceType: "module", |
|||
parser: "@typescript-eslint/parser", |
|||
}, |
|||
plugins: ["vue", "@typescript-eslint"], |
|||
rules: { |
|||
"vue/multi-word-component-names": "off", // 关闭组件名必须多字: https://eslint.vuejs.org/rules/multi-word-component-names.html |
|||
"@typescript-eslint/no-empty-function": "off", // 关闭空方法检查 |
|||
"@typescript-eslint/no-explicit-any": "off", // 关闭any类型的警告 |
|||
"vue/no-v-model-argument": "off", |
|||
"@typescript-eslint/no-non-null-assertion": "off", |
|||
}, |
|||
// https://eslint.org/docs/latest/use/configure/language-options#specifying-globals |
|||
globals: { |
|||
DialogOption: "readonly", |
|||
OptionType: "readonly", |
|||
}, |
|||
}; |
|||
@ -0,0 +1,17 @@ |
|||
node_modules |
|||
.DS_Store |
|||
dist |
|||
dist-ssr |
|||
*.local |
|||
|
|||
# Editor directories and files |
|||
.idea |
|||
.vscode |
|||
*.suo |
|||
*.ntvs* |
|||
*.njsproj |
|||
*.sln |
|||
*.local |
|||
|
|||
package-lock.json |
|||
pnpm-lock.yaml |
|||
@ -0,0 +1,4 @@ |
|||
#!/bin/sh |
|||
. "$(dirname "$0")/_/husky.sh" |
|||
|
|||
npx --no-install commitlint --edit $1 |
|||
@ -0,0 +1,4 @@ |
|||
#!/bin/sh |
|||
. "$(dirname "$0")/_/husky.sh" |
|||
|
|||
npm run lint:lint-staged |
|||
@ -0,0 +1,10 @@ |
|||
dist |
|||
node_modules |
|||
public |
|||
.husky |
|||
.vscode |
|||
.idea |
|||
*.sh |
|||
*.md |
|||
|
|||
src/assets |
|||
@ -0,0 +1,36 @@ |
|||
module.exports = { |
|||
// (x)=>{},单个参数箭头函数是否显示小括号。(always:始终显示;avoid:省略括号。默认:always) |
|||
arrowParens: "always", |
|||
// 开始标签的右尖括号是否跟随在最后一行属性末尾,默认false |
|||
bracketSameLine: false, |
|||
// 对象字面量的括号之间打印空格 (true - Example: { foo: bar } ; false - Example: {foo:bar}) |
|||
bracketSpacing: true, |
|||
// 是否格式化一些文件中被嵌入的代码片段的风格(auto|off;默认auto) |
|||
embeddedLanguageFormatting: "auto", |
|||
// 指定 HTML 文件的空格敏感度 (css|strict|ignore;默认css) |
|||
htmlWhitespaceSensitivity: "css", |
|||
// 当文件已经被 Prettier 格式化之后,是否会在文件顶部插入一个特殊的 @format 标记,默认false |
|||
insertPragma: false, |
|||
// 在 JSX 中使用单引号替代双引号,默认false |
|||
jsxSingleQuote: false, |
|||
// 每行最多字符数量,超出换行(默认80) |
|||
printWidth: 80, |
|||
// 超出打印宽度 (always | never | preserve ) |
|||
proseWrap: "preserve", |
|||
// 对象属性是否使用引号(as-needed | consistent | preserve;默认as-needed:对象的属性需要加引号才添加;) |
|||
quoteProps: "as-needed", |
|||
// 是否只格式化在文件顶部包含特定注释(@prettier| @format)的文件,默认false |
|||
requirePragma: false, |
|||
// 结尾添加分号 |
|||
semi: true, |
|||
// 使用单引号 (true:单引号;false:双引号) |
|||
singleQuote: false, |
|||
// 缩进空格数,默认2个空格 |
|||
tabWidth: 2, |
|||
// 元素末尾是否加逗号,默认es5: ES5中的 objects, arrays 等会添加逗号,TypeScript 中的 type 后不加逗号 |
|||
trailingComma: "es5", |
|||
// 指定缩进方式,空格或tab,默认false,即使用空格 |
|||
useTabs: false, |
|||
// vue 文件中是否缩进 <style> 和 <script> 标签,默认 false |
|||
vueIndentScriptAndStyle: false, |
|||
}; |
|||
@ -0,0 +1,10 @@ |
|||
dist |
|||
node_modules |
|||
public |
|||
.husky |
|||
.vscode |
|||
.idea |
|||
*.sh |
|||
*.md |
|||
|
|||
src/assets |
|||
@ -0,0 +1,43 @@ |
|||
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, // 允许无降序特异性 |
|||
// 允许 global 、export 、deep伪类 |
|||
"selector-pseudo-class-no-unknown": [ |
|||
true, |
|||
{ |
|||
ignorePseudoClasses: ["global", "export", "deep"], |
|||
}, |
|||
], |
|||
// 允许未知属性 |
|||
"property-no-unknown": [ |
|||
true, |
|||
{ |
|||
ignoreProperties: ["menuBg", "menuText", "menuActiveText"], |
|||
}, |
|||
], |
|||
}, |
|||
}; |
|||
@ -0,0 +1,20 @@ |
|||
# 2.3.0 (2023/5/12) |
|||
|
|||
### 📦️ build |
|||
- vue 版本升级 3.2.45 → 3.3.1 ([CHANGELOG](https://github.com/vuejs/core/blob/main/CHANGELOG.md)) |
|||
- vite 版本升级 4.3.1 → 4.3.5 |
|||
|
|||
### ♻️ refactor |
|||
- 使用 vue 3.3 版本新特性 `defineOptions` 在 `setup` 定义组件名称,移除重复的 `script` 标签 |
|||
|
|||
# 2.2.2 (2023/5/11) |
|||
|
|||
### ✨ feat |
|||
- 用户新增提交添加 `vueUse` 的 `useDebounceFn` 函数实现按钮防抖节流 |
|||
|
|||
|
|||
# 2.2.1 (2023/4/25) |
|||
|
|||
### 🐛 fix |
|||
- 图标选择器组件使用 `onClickOutside` 未排除下拉弹出框元素导致无法输入搜索。 |
|||
|
|||
@ -0,0 +1,93 @@ |
|||
module.exports = { |
|||
// 继承的规则 |
|||
extends: ["@commitlint/config-conventional"], |
|||
// 自定义规则 |
|||
rules: { |
|||
// @see https://commitlint.js.org/#/reference-rules |
|||
|
|||
// 提交类型枚举,git提交type必须是以下类型 |
|||
"type-enum": [ |
|||
2, |
|||
"always", |
|||
[ |
|||
"feat", // 新增功能 |
|||
"fix", // 修复缺陷 |
|||
"docs", // 文档变更 |
|||
"style", // 代码格式(不影响功能,例如空格、分号等格式修正) |
|||
"refactor", // 代码重构(不包括 bug 修复、功能新增) |
|||
"perf", // 性能优化 |
|||
"test", // 添加疏漏测试或已有测试改动 |
|||
"build", // 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等) |
|||
"ci", // 修改 CI 配置、脚本 |
|||
"revert", // 回滚 commit |
|||
"chore", // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例) |
|||
], |
|||
], |
|||
"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: "特性: ✨ 新增功能", emoji: ":sparkles:" }, |
|||
{ value: "fix", name: "修复: 🐛 修复缺陷", emoji: ":bug:" }, |
|||
{ value: "docs", name: "文档: 📝 文档变更", emoji: ":memo:" }, |
|||
{ value: "style", name: "格式: 💄 代码格式(不影响功能,例如空格、分号等格式修正)", emoji: ":lipstick:" }, |
|||
{ value: "refactor", name: "重构: ♻️ 代码重构(不包括 bug 修复、功能新增)", emoji: ":recycle:" }, |
|||
{ value: "perf", name: "性能: ⚡️ 性能优化", emoji: ":zap:" }, |
|||
{ value: "test", name: "测试: ✅ 添加疏漏测试或已有测试改动", emoji: ":white_check_mark:"}, |
|||
{ value: "build", name: "构建: 📦️ 构建流程、外部依赖变更(如升级 npm 包、修改 vite 配置等)", emoji: ":package:"}, |
|||
{ value: "ci", name: "集成: 🎡 修改 CI 配置、脚本", emoji: ":ferris_wheel:"}, |
|||
{ value: "revert", name: "回退: ⏪️ 回滚 commit",emoji: ":rewind:"}, |
|||
{ value: "chore", name: "其他: 🔨 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)", emoji: ":hammer:"}, |
|||
], |
|||
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: [], |
|||
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: "", |
|||
}, |
|||
}; |
|||
@ -0,0 +1,18 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
|
|||
<head> |
|||
<meta charset="UTF-8" /> |
|||
<link rel="icon" href="/favicon.ico" /> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|||
<meta name="description" content="恒信高科应用平台" /> |
|||
<meta name="keywords" content="恒信高科" /> |
|||
<title>恒信高科应用平台</title> |
|||
</head> |
|||
|
|||
<body> |
|||
<div id="app"></div> |
|||
<script type="module" src="/src/main.ts"></script> |
|||
</body> |
|||
|
|||
</html> |
|||
@ -0,0 +1,101 @@ |
|||
{ |
|||
"name": "appsys", |
|||
"private": true, |
|||
"version": "2.3.0", |
|||
"type": "module", |
|||
"scripts": { |
|||
"dev": "vite serve --mode development", |
|||
"build:prod": "vite build --mode production &&vue-tsc --noEmit", |
|||
"prepare": "husky install", |
|||
"lint:eslint": "eslint --fix --ext .ts,.js,.vue ./src ", |
|||
"lint:prettier": "prettier --write \"**/*.{js,cjs,ts,json,tsx,css,less,scss,vue,html,md}\"", |
|||
"lint:stylelint": "stylelint \"**/*.{css,scss,vue}\" --fix", |
|||
"lint:lint-staged": "lint-staged", |
|||
"commit": "git-cz" |
|||
}, |
|||
"config": { |
|||
"commitizen": { |
|||
"path": "node_modules/cz-git" |
|||
} |
|||
}, |
|||
"lint-staged": { |
|||
"*.{js,ts}": [ |
|||
"eslint --fix", |
|||
"prettier --write" |
|||
], |
|||
"*.{cjs,json}": [ |
|||
"prettier --write" |
|||
], |
|||
"*.{vue,html}": [ |
|||
"eslint --fix", |
|||
"prettier --write", |
|||
"stylelint --fix" |
|||
], |
|||
"*.{scss,css}": [ |
|||
"stylelint --fix", |
|||
"prettier --write" |
|||
], |
|||
"*.md": [ |
|||
"prettier --write" |
|||
] |
|||
}, |
|||
"dependencies": { |
|||
"@vitejs/plugin-vue": "^4.2.3", |
|||
"@vueuse/core": "^10.1.2", |
|||
"@wangeditor/editor": "^5.1.23", |
|||
"@wangeditor/editor-for-vue": "5.1.10", |
|||
"axios": "^1.4.0", |
|||
"echarts": "^5.2.2", |
|||
"element-plus": "^2.3.4", |
|||
"nprogress": "^0.2.0", |
|||
"path-browserify": "^1.0.1", |
|||
"path-to-regexp": "^6.2.0", |
|||
"pinia": "^2.0.33", |
|||
"screenfull": "^6.0.0", |
|||
"vue": "^3.3.1", |
|||
"vue-i18n": "9.2.2", |
|||
"vue-router": "^4.2.0" |
|||
}, |
|||
"devDependencies": { |
|||
"@commitlint/cli": "^17.6.3", |
|||
"@commitlint/config-conventional": "^17.6.3", |
|||
"@iconify-json/ep": "^1.1.10", |
|||
"@types/nprogress": "^0.2.0", |
|||
"@types/path-browserify": "^1.0.0", |
|||
"@typescript-eslint/eslint-plugin": "^5.59.6", |
|||
"@typescript-eslint/parser": "^5.59.6", |
|||
"autoprefixer": "^10.4.14", |
|||
"commitizen": "^4.3.0", |
|||
"cz-git": "^1.6.1", |
|||
"eslint": "^8.40.0", |
|||
"eslint-config-prettier": "^8.8.0", |
|||
"eslint-plugin-prettier": "^4.2.1", |
|||
"eslint-plugin-vue": "^9.13.0", |
|||
"fast-glob": "^3.2.11", |
|||
"husky": "^8.0.3", |
|||
"lint-staged": "^13.2.2", |
|||
"postcss": "^8.4.23", |
|||
"postcss-html": "^1.5.0", |
|||
"postcss-scss": "^4.0.6", |
|||
"prettier": "^2.8.8", |
|||
"sass": "^1.58.3", |
|||
"stylelint": "^15.5.0", |
|||
"stylelint-config-html": "^1.1.0", |
|||
"stylelint-config-recess-order": "^4.0.0", |
|||
"stylelint-config-recommended-scss": "11.0.0 ", |
|||
"stylelint-config-recommended-vue": "^1.4.0", |
|||
"stylelint-config-standard": "^33.0.0", |
|||
"stylelint-config-standard-scss": "^9.0.0", |
|||
"typescript": "^5.0.4", |
|||
"unocss": "^0.51.13", |
|||
"unplugin-auto-import": "^0.15.3", |
|||
"unplugin-icons": "^0.16.1", |
|||
"unplugin-vue-components": "^0.24.1", |
|||
"vite": "^4.3.5", |
|||
"vite-plugin-svg-icons": "^2.0.1", |
|||
"vue-tsc": "^1.6.5 " |
|||
}, |
|||
"repository": "https://gitee.com/youlaiorg/vue3-element-admin.git", |
|||
"author": "有来开源组织", |
|||
"license": "MIT" |
|||
} |
|||
|
After Width: | Height: | Size: 4.2 KiB |
@ -0,0 +1,11 @@ |
|||
<script setup lang="ts"> |
|||
import { ElConfigProvider } from 'element-plus'; |
|||
import { useAppStore } from '@/store/modules/app'; |
|||
const appStore = useAppStore(); |
|||
</script> |
|||
|
|||
<template> |
|||
<el-config-provider :locale="appStore.locale" :size="appStore.size"> |
|||
<router-view /> |
|||
</el-config-provider> |
|||
</template> |
|||
@ -0,0 +1,56 @@ |
|||
import request from '@/utils/request'; |
|||
import { AxiosPromise } from 'axios'; |
|||
import { CaptchaResult, LoginData, LoginResult } from './types'; |
|||
|
|||
/** |
|||
* 登录API |
|||
* |
|||
* @param data {LoginData} |
|||
* @returns |
|||
*/ |
|||
export function loginApi(data: LoginData): AxiosPromise<LoginResult> { |
|||
return request({ |
|||
url: '/api/v1/auth/login', |
|||
method: 'post', |
|||
params: data |
|||
}); |
|||
} |
|||
export function loginApiIng(data: LoginData): AxiosPromise<LoginResult> { |
|||
return request({ |
|||
url: "/kpiapi/base/login", |
|||
method: "post", |
|||
data: data, |
|||
}); |
|||
} |
|||
/** |
|||
* 注销API |
|||
*/ |
|||
export function logoutApiOld() { |
|||
return request({ |
|||
url: '/api/v1/auth/logout', |
|||
method: 'delete' |
|||
}); |
|||
} |
|||
|
|||
export function logoutApi() { |
|||
return request({ |
|||
url: "/kpiapi/base/signout", |
|||
method: "post", |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 获取验证码 |
|||
*/ |
|||
export function getCaptchaApi(): AxiosPromise<CaptchaResult> { |
|||
return request({ |
|||
url: '/api/v1/auth/captcha', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
export function getCaptchaApiIng(): AxiosPromise<CaptchaResult> { |
|||
return request({ |
|||
url: "/kpiapi/base/captcha", |
|||
method: "post", |
|||
}); |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
/** |
|||
* 登录请求参数 |
|||
*/ |
|||
export interface LoginData { |
|||
/** |
|||
* 用户名 |
|||
*/ |
|||
username?: string; |
|||
/** |
|||
* 密码 |
|||
*/ |
|||
password?: string; |
|||
|
|||
/** |
|||
* 验证码缓存key |
|||
*/ |
|||
verifyCodeKey?: string; |
|||
|
|||
/** |
|||
* 验证码 |
|||
*/ |
|||
verifyCode?: string; |
|||
captcha?: string; |
|||
captchaId?: string; |
|||
} |
|||
|
|||
/** |
|||
* 登录响应 |
|||
*/ |
|||
export interface LoginResult { |
|||
/** |
|||
* 访问token |
|||
*/ |
|||
accessToken?: string; |
|||
/** |
|||
* 过期时间(单位:毫秒) |
|||
*/ |
|||
expires?: number; |
|||
/** |
|||
* 刷新token |
|||
*/ |
|||
refreshToken?: string; |
|||
/** |
|||
* token 类型 |
|||
*/ |
|||
tokenType?: string; |
|||
key?: string; |
|||
token?: string; |
|||
} |
|||
|
|||
/** |
|||
* 验证码响应 |
|||
*/ |
|||
export interface CaptchaResult { |
|||
/** |
|||
* 验证码缓存key |
|||
*/ |
|||
verifyCodeKey: string; |
|||
/** |
|||
* 验证码图片Base64字符串 |
|||
*/ |
|||
verifyCodeBase64: string; |
|||
/** |
|||
* 验证码缓存key |
|||
*/ |
|||
captchaid: string; |
|||
/** |
|||
* 验证码图片Base64字符串 |
|||
*/ |
|||
picPath: string; |
|||
} |
|||
|
|||
@ -0,0 +1,77 @@ |
|||
import request from '@/utils/request'; |
|||
import { AxiosPromise } from 'axios'; |
|||
import { DeptForm, DeptQuery, DeptVO } from './types'; |
|||
|
|||
/** |
|||
* 部门树形表格 |
|||
* |
|||
* @param queryParams |
|||
*/ |
|||
export function listDepts(queryParams?: DeptQuery): AxiosPromise<DeptVO[]> { |
|||
return request({ |
|||
url: '/api/v1/dept', |
|||
method: 'get', |
|||
params: queryParams |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 部门下拉列表 |
|||
*/ |
|||
export function listDeptOptions(): AxiosPromise<[]> { |
|||
return request({ |
|||
url: '/api/v1/dept/options', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 获取部门详情 |
|||
* |
|||
* @param id |
|||
*/ |
|||
export function getDeptForm(id: number): AxiosPromise<DeptForm> { |
|||
return request({ |
|||
url: '/api/v1/dept/' + id + '/form', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 新增部门 |
|||
* |
|||
* @param data |
|||
*/ |
|||
export function addDept(data: DeptForm) { |
|||
return request({ |
|||
url: '/api/v1/dept', |
|||
method: 'post', |
|||
data: data |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 修改部门 |
|||
* |
|||
* @param id |
|||
* @param data |
|||
*/ |
|||
export function updateDept(id: number, data: DeptForm) { |
|||
return request({ |
|||
url: '/api/v1/dept/' + id, |
|||
method: 'put', |
|||
data: data |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 删除部门 |
|||
* |
|||
* @param ids |
|||
*/ |
|||
export function deleteDept(ids: string) { |
|||
return request({ |
|||
url: '/api/v1/dept/' + ids, |
|||
method: 'delete' |
|||
}); |
|||
} |
|||
@ -0,0 +1,71 @@ |
|||
/** |
|||
* 部门查询参数 |
|||
*/ |
|||
export interface DeptQuery { |
|||
keywords?: string; |
|||
status?: number; |
|||
} |
|||
|
|||
/** |
|||
* 部门类型 |
|||
*/ |
|||
export interface DeptVO { |
|||
/** |
|||
* 子部门 |
|||
*/ |
|||
children?: DeptVO[]; |
|||
/** |
|||
* 创建时间 |
|||
*/ |
|||
createTime?: Date; |
|||
/** |
|||
* 部门ID |
|||
*/ |
|||
id?: number; |
|||
/** |
|||
* 部门名称 |
|||
*/ |
|||
name?: string; |
|||
/** |
|||
* 父部门ID |
|||
*/ |
|||
parentId?: number; |
|||
/** |
|||
* 排序 |
|||
*/ |
|||
sort?: number; |
|||
/** |
|||
* 状态(1:启用;0:禁用) |
|||
*/ |
|||
status?: number; |
|||
/** |
|||
* 修改时间 |
|||
*/ |
|||
updateTime?: Date; |
|||
} |
|||
|
|||
/** |
|||
* 部门表单类型 |
|||
*/ |
|||
export interface DeptForm { |
|||
/** |
|||
* 部门ID(新增不填) |
|||
*/ |
|||
id?: number; |
|||
/** |
|||
* 部门名称 |
|||
*/ |
|||
name?: string; |
|||
/** |
|||
* 父部门ID |
|||
*/ |
|||
parentId: number; |
|||
/** |
|||
* 排序 |
|||
*/ |
|||
sort?: number; |
|||
/** |
|||
* 状态(1:启用;0:禁用) |
|||
*/ |
|||
status?: number; |
|||
} |
|||
@ -0,0 +1,150 @@ |
|||
import request from '@/utils/request'; |
|||
import { AxiosPromise } from 'axios'; |
|||
import { |
|||
DictTypeQuery, |
|||
DictTypePageResult, |
|||
DictTypeForm, |
|||
DictQuery, |
|||
DictForm, |
|||
DictPageResult |
|||
} from './types'; |
|||
|
|||
/** |
|||
* 字典类型分页列表 |
|||
* |
|||
* @param queryParams |
|||
*/ |
|||
export function getDictTypePage( |
|||
queryParams: DictTypeQuery |
|||
): AxiosPromise<DictTypePageResult> { |
|||
return request({ |
|||
url: '/api/v1/dict/types/page', |
|||
method: 'get', |
|||
params: queryParams |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 字典类型表单数据 |
|||
* |
|||
* @param id |
|||
*/ |
|||
export function getDictTypeForm(id: number): AxiosPromise<DictTypeForm> { |
|||
return request({ |
|||
url: '/api/v1/dict/types/' + id + '/form', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 新增字典类型 |
|||
* |
|||
* @param data |
|||
*/ |
|||
export function addDictType(data: DictTypeForm) { |
|||
return request({ |
|||
url: '/api/v1/dict/types', |
|||
method: 'post', |
|||
data: data |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 修改字典类型 |
|||
* |
|||
* @param id |
|||
* @param data |
|||
*/ |
|||
export function updateDictType(id: number, data: DictTypeForm) { |
|||
return request({ |
|||
url: '/api/v1/dict/types/' + id, |
|||
method: 'put', |
|||
data: data |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 删除字典类型 |
|||
*/ |
|||
export function deleteDictTypes(ids: string) { |
|||
return request({ |
|||
url: '/api/v1/dict/types/' + ids, |
|||
method: 'delete' |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 获取字典类型的数据项 |
|||
* |
|||
* @param typeCode 字典类型编码 |
|||
*/ |
|||
export function getDictOptions(typeCode: string): AxiosPromise<OptionType[]> { |
|||
return request({ |
|||
url: '/api/v1/dict/types/' + typeCode + '/items', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 字典分页列表 |
|||
*/ |
|||
export function getDictPage( |
|||
queryParams: DictQuery |
|||
): AxiosPromise<DictPageResult> { |
|||
return request({ |
|||
url: '/api/v1/dict/page', |
|||
method: 'get', |
|||
params: queryParams |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 获取字典表单数据 |
|||
* |
|||
* @param id |
|||
*/ |
|||
export function getDictFormData(id: number): AxiosPromise<DictForm> { |
|||
return request({ |
|||
url: '/api/v1/dict/' + id + '/form', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 新增字典 |
|||
* |
|||
* @param data |
|||
*/ |
|||
export function addDict(data: DictForm) { |
|||
return request({ |
|||
url: '/api/v1/dict', |
|||
method: 'post', |
|||
data: data |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 修改字典项 |
|||
* |
|||
* @param id |
|||
* @param data |
|||
*/ |
|||
export function updateDict(id: number, data: DictForm) { |
|||
return request({ |
|||
url: '/api/v1/dict/' + id, |
|||
method: 'put', |
|||
data: data |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 删除字典 |
|||
* |
|||
* @param ids 字典项ID,多个以英文逗号(,)分割 |
|||
*/ |
|||
export function deleteDict(ids: string) { |
|||
return request({ |
|||
url: '/api/v1/dict/' + ids, |
|||
method: 'delete' |
|||
}); |
|||
} |
|||
@ -0,0 +1,142 @@ |
|||
/** |
|||
* 字典类型查询参数 |
|||
*/ |
|||
export interface DictTypeQuery extends PageQuery { |
|||
/** |
|||
* 关键字(字典类型名称/编码) |
|||
*/ |
|||
keywords?: string; |
|||
} |
|||
|
|||
/** |
|||
* 字典类型分页对象 |
|||
*/ |
|||
export interface DictTypePageVO { |
|||
/** |
|||
* 字典类型ID |
|||
*/ |
|||
id: number; |
|||
/** |
|||
* 类型编码 |
|||
*/ |
|||
code: string; |
|||
/** |
|||
* 类型名称 |
|||
*/ |
|||
name: string; |
|||
/** |
|||
* 状态(1:启用;0:禁用) |
|||
*/ |
|||
status?: number; |
|||
/** |
|||
* 备注 |
|||
*/ |
|||
remark?: string; |
|||
} |
|||
|
|||
/** |
|||
* 字典分页项类型声明 |
|||
*/ |
|||
export type DictTypePageResult = PageResult<DictTypePageVO[]>; |
|||
|
|||
/** |
|||
* 字典表单类型声明 |
|||
*/ |
|||
export interface DictTypeForm { |
|||
/** |
|||
* 字典类型ID |
|||
*/ |
|||
id?: number; |
|||
/** |
|||
* 类型名称 |
|||
*/ |
|||
name?: string; |
|||
/** |
|||
* 类型编码 |
|||
*/ |
|||
code?: string; |
|||
/** |
|||
* 类型状态:1:启用;0:禁用 |
|||
*/ |
|||
status: number; |
|||
/** |
|||
* 备注 |
|||
*/ |
|||
remark?: string; |
|||
} |
|||
|
|||
/** |
|||
* 字典查询参数 |
|||
*/ |
|||
export interface DictQuery extends PageQuery { |
|||
/** |
|||
* 字典项名称 |
|||
*/ |
|||
name?: string; |
|||
/** |
|||
* 字典类型编码 |
|||
*/ |
|||
typeCode?: string; |
|||
} |
|||
|
|||
/** |
|||
* 字典分页对象 |
|||
*/ |
|||
export interface DictPageVO { |
|||
/** |
|||
* 字典ID |
|||
*/ |
|||
id?: number; |
|||
/** |
|||
* 字典名称 |
|||
*/ |
|||
name?: string; |
|||
/** |
|||
* 状态(1:启用;0:禁用) |
|||
*/ |
|||
status?: number; |
|||
/** |
|||
* 字典值 |
|||
*/ |
|||
value?: string; |
|||
} |
|||
|
|||
/** |
|||
* 字典分页 |
|||
*/ |
|||
export type DictPageResult = PageResult<DictPageVO[]>; |
|||
|
|||
/** |
|||
* 字典表单 |
|||
*/ |
|||
export interface DictForm { |
|||
/** |
|||
* 字典ID |
|||
*/ |
|||
id?: number; |
|||
/** |
|||
* 字典名称 |
|||
*/ |
|||
name?: string; |
|||
/** |
|||
* 排序 |
|||
*/ |
|||
sort?: number; |
|||
/** |
|||
* 状态(1:启用;0:禁用) |
|||
*/ |
|||
status?: number; |
|||
/** |
|||
* 类型编码 |
|||
*/ |
|||
typeCode?: string; |
|||
/** |
|||
* 值 |
|||
*/ |
|||
value?: string; |
|||
|
|||
/** |
|||
* 备注 |
|||
*/ |
|||
remark?: string; |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
import request from '@/utils/request'; |
|||
import { AxiosPromise } from 'axios'; |
|||
import { FileInfo } from './types'; |
|||
|
|||
/** |
|||
* 上传文件 |
|||
* |
|||
* @param file |
|||
*/ |
|||
export function uploadFileApi(file: File): AxiosPromise<FileInfo> { |
|||
const formData = new FormData(); |
|||
formData.append('file', file); |
|||
return request({ |
|||
url: '/api/v1/files', |
|||
method: 'post', |
|||
data: formData, |
|||
headers: { |
|||
'Content-Type': 'multipart/form-data' |
|||
} |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 删除文件 |
|||
* |
|||
* @param filePath 文件完整路径 |
|||
*/ |
|||
export function deleteFileApi(filePath?: string) { |
|||
return request({ |
|||
url: '/api/v1/files', |
|||
method: 'delete', |
|||
params: { filePath: filePath } |
|||
}); |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
/** |
|||
* 文件API类型声明 |
|||
*/ |
|||
export interface FileInfo { |
|||
name: string; |
|||
url: string; |
|||
} |
|||
@ -0,0 +1,128 @@ |
|||
import request from '@/utils/request'; |
|||
import { AxiosPromise } from 'axios'; |
|||
import { MenuQuery, MenuVO, MenuForm,menuInfo } from './types'; |
|||
|
|||
/** |
|||
* 获取路由列表 |
|||
*/ |
|||
export function listRoutesOld() { |
|||
return request({ |
|||
url: '/api/v1/menus/routes', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
export function listRoutes() { |
|||
return request({ |
|||
url: '/systemapi/menus/get_routers_three', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
/** |
|||
* 获取菜单树形列表 |
|||
* |
|||
* @param queryParams |
|||
*/ |
|||
export function listMenusOld(queryParams: MenuQuery): AxiosPromise<MenuVO[]> { |
|||
return request({ |
|||
url: '/api/v1/menus', |
|||
method: 'get', |
|||
params: queryParams |
|||
}); |
|||
} |
|||
export function listMenus(queryParams: MenuQuery): AxiosPromise<MenuVO[]> { |
|||
return request({ |
|||
url: '/systemapi/menus/get_menus_three', |
|||
method: 'get', |
|||
params: queryParams |
|||
}); |
|||
} |
|||
/** |
|||
* 获取菜单下拉树形列表 |
|||
*/ |
|||
export function listMenuOptionsOld(): AxiosPromise<OptionType[]> { |
|||
return request({ |
|||
url: '/api/v1/menus/options', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
export function listMenuOptions(): AxiosPromise<OptionType[]> { |
|||
return request({ |
|||
url: '/systemapi/menus/menu_options', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
/** |
|||
* 获取菜单表单数据 |
|||
* |
|||
* @param id |
|||
*/ |
|||
export function getMenuFormOld(id: number): AxiosPromise<MenuForm> { |
|||
return request({ |
|||
url: '/api/v1/menus/' + id + '/form', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
export function getMenuForm(data: menuInfo): AxiosPromise<MenuForm> { |
|||
return request({ |
|||
url: '/systemapi/menus/get_one_menu_cont', |
|||
method: 'post', |
|||
data:data |
|||
}); |
|||
} |
|||
/** |
|||
* 添加菜单 |
|||
* |
|||
* @param data |
|||
*/ |
|||
export function addMenuOld(data: MenuForm) { |
|||
return request({ |
|||
url: '/api/v1/menus', |
|||
method: 'post', |
|||
data: data |
|||
}); |
|||
} |
|||
export function addMenu(data: MenuForm) { |
|||
return request({ |
|||
url: '/systemapi/menus/add_new_menu', |
|||
method: 'post', |
|||
data: data |
|||
}); |
|||
} |
|||
/** |
|||
* 修改菜单 |
|||
* |
|||
* @param id |
|||
* @param data |
|||
*/ |
|||
export function updateMenuOld(id: string, data: MenuForm) { |
|||
return request({ |
|||
url: '/api/v1/menus/' + id, |
|||
method: 'put', |
|||
data: data |
|||
}); |
|||
} |
|||
export function updateMenu(data: MenuForm) { |
|||
return request({ |
|||
url: '/systemapi/menus/edit_menus_cont', |
|||
method: 'post', |
|||
data: data |
|||
}); |
|||
} |
|||
/** |
|||
* 删除菜单 |
|||
* |
|||
* @param id 菜单ID |
|||
*/ |
|||
export function deleteMenuOld(id: number) { |
|||
return request({ |
|||
url: '/api/v1/menus/' + id, |
|||
method: 'delete' |
|||
}); |
|||
} |
|||
export function deleteMenu(data: menuInfo) { |
|||
return request({ |
|||
url: '/systemapi/menus/delt_menus_cont', |
|||
method: 'post', |
|||
data:data |
|||
}); |
|||
} |
|||
@ -0,0 +1,121 @@ |
|||
import { MenuTypeEnum } from '@/enums/MenuTypeEnum'; |
|||
|
|||
/** |
|||
* 菜单查询参数类型 |
|||
*/ |
|||
export interface MenuQuery { |
|||
keywords?: string; |
|||
} |
|||
|
|||
/** |
|||
* 菜单视图对象类型 |
|||
*/ |
|||
export interface MenuVO { |
|||
/** |
|||
* 子菜单 |
|||
*/ |
|||
children?: MenuVO[]; |
|||
/** |
|||
* 组件路径 |
|||
*/ |
|||
component?: string; |
|||
/** |
|||
* ICON |
|||
*/ |
|||
icon?: string; |
|||
/** |
|||
* 菜单ID |
|||
*/ |
|||
id?: number; |
|||
/** |
|||
* 菜单名称 |
|||
*/ |
|||
name?: string; |
|||
/** |
|||
* 父菜单ID |
|||
*/ |
|||
parentId?: number; |
|||
/** |
|||
* 按钮权限标识 |
|||
*/ |
|||
perm?: string; |
|||
/** |
|||
* 跳转路径 |
|||
*/ |
|||
redirect?: string; |
|||
/** |
|||
* 路由名称 |
|||
*/ |
|||
routeName?: string; |
|||
/** |
|||
* 路由相对路径 |
|||
*/ |
|||
routePath?: string; |
|||
/** |
|||
* 菜单排序(数字越小排名越靠前) |
|||
*/ |
|||
sort?: number; |
|||
/** |
|||
* 菜单类型 |
|||
*/ |
|||
type?: MenuTypeEnum; |
|||
/** |
|||
* 菜单是否可见(1:显示;0:隐藏) |
|||
*/ |
|||
visible?: number; |
|||
} |
|||
|
|||
/** |
|||
* 菜单表单对象类型 |
|||
*/ |
|||
export interface MenuForm { |
|||
/** |
|||
* 菜单ID |
|||
*/ |
|||
id?: string; |
|||
/** |
|||
* 父菜单ID |
|||
*/ |
|||
parentId?: number; |
|||
/** |
|||
* 菜单名称 |
|||
*/ |
|||
name?: string; |
|||
/** |
|||
* 菜单是否可见(1:是;0:否;) |
|||
*/ |
|||
visible: number; |
|||
icon?: string; |
|||
/** |
|||
* 排序 |
|||
*/ |
|||
sort: number; |
|||
/** |
|||
* 组件路径 |
|||
*/ |
|||
component?: string; |
|||
/** |
|||
* 路由路径 |
|||
*/ |
|||
path?: string; |
|||
/** |
|||
* 跳转路由路径 |
|||
*/ |
|||
redirect?: string; |
|||
|
|||
/** |
|||
* 菜单类型 |
|||
*/ |
|||
type: MenuTypeEnum; |
|||
|
|||
/** |
|||
* 权限标识 |
|||
*/ |
|||
perm?: string; |
|||
} |
|||
/** |
|||
* 查看菜单内容 |
|||
*/ |
|||
export interface menuInfo { |
|||
id:string; |
|||
} |
|||
@ -0,0 +1,112 @@ |
|||
import request from '@/utils/request'; |
|||
import { AxiosPromise } from 'axios'; |
|||
import { RoleQuery, RolePageResult, RoleForm } from './types'; |
|||
|
|||
/** |
|||
* 获取角色分页数据 |
|||
* |
|||
* @param queryParams |
|||
*/ |
|||
export function getRolePage( |
|||
queryParams?: RoleQuery |
|||
): AxiosPromise<RolePageResult> { |
|||
return request({ |
|||
url: '/api/v1/roles/page', |
|||
method: 'get', |
|||
params: queryParams |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 获取角色下拉数据 |
|||
* |
|||
* @param queryParams |
|||
*/ |
|||
export function listRoleOptions( |
|||
queryParams?: RoleQuery |
|||
): AxiosPromise<OptionType[]> { |
|||
return request({ |
|||
url: '/api/v1/roles/options', |
|||
method: 'get', |
|||
params: queryParams |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 获取角色的菜单ID集合 |
|||
* |
|||
* @param queryParams |
|||
*/ |
|||
export function getRoleMenuIds(roleId: number): AxiosPromise<number[]> { |
|||
return request({ |
|||
url: '/api/v1/roles/' + roleId + '/menuIds', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 分配菜单权限给角色 |
|||
* |
|||
* @param queryParams |
|||
*/ |
|||
export function updateRoleMenus( |
|||
roleId: number, |
|||
data: number[] |
|||
): AxiosPromise<any> { |
|||
return request({ |
|||
url: '/api/v1/roles/' + roleId + '/menus', |
|||
method: 'put', |
|||
data: data |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 获取角色详情 |
|||
* |
|||
* @param id |
|||
*/ |
|||
export function getRoleForm(id: number): AxiosPromise<RoleForm> { |
|||
return request({ |
|||
url: '/api/v1/roles/' + id + '/form', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 添加角色 |
|||
* |
|||
* @param data |
|||
*/ |
|||
export function addRole(data: RoleForm) { |
|||
return request({ |
|||
url: '/api/v1/roles', |
|||
method: 'post', |
|||
data: data |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 更新角色 |
|||
* |
|||
* @param id |
|||
* @param data |
|||
*/ |
|||
export function updateRole(id: number, data: RoleForm) { |
|||
return request({ |
|||
url: '/api/v1/roles/' + id, |
|||
method: 'put', |
|||
data: data |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 批量删除角色,多个以英文逗号(,)分割 |
|||
* |
|||
* @param ids |
|||
*/ |
|||
export function deleteRoles(ids: string) { |
|||
return request({ |
|||
url: '/api/v1/roles/' + ids, |
|||
method: 'delete' |
|||
}); |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
/** |
|||
* 角色查询参数 |
|||
*/ |
|||
export interface RoleQuery extends PageQuery { |
|||
keywords?: string; |
|||
} |
|||
|
|||
/** |
|||
* 角色分页对象 |
|||
*/ |
|||
export interface RolePageVO { |
|||
/** |
|||
* 角色编码 |
|||
*/ |
|||
code?: string; |
|||
|
|||
/** |
|||
* 角色ID |
|||
*/ |
|||
id?: number; |
|||
/** |
|||
* 角色名称 |
|||
*/ |
|||
name?: string; |
|||
/** |
|||
* 排序 |
|||
*/ |
|||
sort?: number; |
|||
/** |
|||
* 角色状态 |
|||
*/ |
|||
status?: number; |
|||
/** |
|||
* 创建时间 |
|||
*/ |
|||
createTime?: Date; |
|||
/** |
|||
* 修改时间 |
|||
*/ |
|||
updateTime?: Date; |
|||
} |
|||
|
|||
/** |
|||
* 角色分页 |
|||
*/ |
|||
export type RolePageResult = PageResult<RolePageVO[]>; |
|||
|
|||
/** |
|||
* 角色表单对象 |
|||
*/ |
|||
export interface RoleForm { |
|||
/** |
|||
* 角色ID |
|||
*/ |
|||
id?: number; |
|||
|
|||
/** |
|||
* 角色编码 |
|||
*/ |
|||
code: string; |
|||
/** |
|||
* 数据权限 |
|||
*/ |
|||
dataScope?: number; |
|||
|
|||
/** |
|||
* 角色名称 |
|||
*/ |
|||
name: string; |
|||
/** |
|||
* 排序 |
|||
*/ |
|||
sort?: number; |
|||
/** |
|||
* 角色状态(1-正常;0-停用) |
|||
*/ |
|||
status?: number; |
|||
} |
|||
@ -0,0 +1,159 @@ |
|||
import request from '@/utils/request'; |
|||
import { AxiosPromise } from 'axios'; |
|||
import { UserForm, UserInfo, UserPageVO, UserQuery } from './types'; |
|||
|
|||
/** |
|||
* 登录成功后获取用户信息(昵称、头像、权限集合和角色集合) |
|||
*/ |
|||
export function getUserInfo(): AxiosPromise<UserInfo> { |
|||
return request({ |
|||
url: '/api/v1/users/me', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
export function getUserInfoIng(): AxiosPromise<UserInfo> { |
|||
return request({ |
|||
url: '/systemapi/user/get_user_cont', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
/** |
|||
* 获取用户分页列表 |
|||
* |
|||
* @param queryParams |
|||
*/ |
|||
export function getUserPage( |
|||
queryParams: UserQuery |
|||
): AxiosPromise<PageResult<UserPageVO[]>> { |
|||
return request({ |
|||
url: '/api/v1/users/page', |
|||
method: 'get', |
|||
params: queryParams |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 获取用户表单详情 |
|||
* |
|||
* @param userId |
|||
*/ |
|||
export function getUserForm(userId: number): AxiosPromise<UserForm> { |
|||
return request({ |
|||
url: '/api/v1/users/' + userId + '/form', |
|||
method: 'get' |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 添加用户 |
|||
* |
|||
* @param data |
|||
*/ |
|||
export function addUser(data: any) { |
|||
return request({ |
|||
url: '/api/v1/users', |
|||
method: 'post', |
|||
data: data |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 修改用户 |
|||
* |
|||
* @param id |
|||
* @param data |
|||
*/ |
|||
export function updateUser(id: number, data: UserForm) { |
|||
return request({ |
|||
url: '/api/v1/users/' + id, |
|||
method: 'put', |
|||
data: data |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 修改用户状态 |
|||
* |
|||
* @param id |
|||
* @param status |
|||
*/ |
|||
export function updateUserStatus(id: number, status: number) { |
|||
return request({ |
|||
url: '/api/v1/users/' + id + '/status', |
|||
method: 'patch', |
|||
params: { status: status } |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 修改用户密码 |
|||
* |
|||
* @param id |
|||
* @param password |
|||
*/ |
|||
export function updateUserPassword(id: number, password: string) { |
|||
return request({ |
|||
url: '/api/v1/users/' + id + '/password', |
|||
method: 'patch', |
|||
params: { password: password } |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 删除用户 |
|||
* |
|||
* @param ids |
|||
*/ |
|||
export function deleteUsers(ids: string) { |
|||
return request({ |
|||
url: '/api/v1/users/' + ids, |
|||
method: 'delete' |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 下载用户导入模板 |
|||
* |
|||
* @returns |
|||
*/ |
|||
export function downloadTemplateApi() { |
|||
return request({ |
|||
url: '/api/v1/users/template', |
|||
method: 'get', |
|||
responseType: 'arraybuffer' |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 导出用户 |
|||
* |
|||
* @param queryParams |
|||
* @returns |
|||
*/ |
|||
export function exportUser(queryParams: UserQuery) { |
|||
return request({ |
|||
url: '/api/v1/users/_export', |
|||
method: 'get', |
|||
params: queryParams, |
|||
responseType: 'arraybuffer' |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 导入用户 |
|||
* |
|||
* @param file |
|||
*/ |
|||
export function importUser(deptId: number, file: File) { |
|||
const formData = new FormData(); |
|||
formData.append('file', file); |
|||
return request({ |
|||
url: '/api/v1/users/_import', |
|||
method: 'post', |
|||
params: { deptId: deptId }, |
|||
data: formData, |
|||
headers: { |
|||
'Content-Type': 'multipart/form-data' |
|||
} |
|||
}); |
|||
} |
|||
@ -0,0 +1,111 @@ |
|||
/** |
|||
* 登录用户信息 |
|||
*/ |
|||
export interface UserInfo { |
|||
nickname: string; |
|||
avatar: string; |
|||
roles: string[]; |
|||
perms: string[]; |
|||
} |
|||
|
|||
/** |
|||
* 用户查询对象类型 |
|||
*/ |
|||
export interface UserQuery extends PageQuery { |
|||
keywords?: string; |
|||
status?: number; |
|||
deptId?: number; |
|||
} |
|||
|
|||
/** |
|||
* 用户分页对象 |
|||
*/ |
|||
export interface UserPageVO { |
|||
/** |
|||
* 用户头像地址 |
|||
*/ |
|||
avatar?: string; |
|||
/** |
|||
* 创建时间 |
|||
*/ |
|||
createTime?: Date; |
|||
/** |
|||
* 部门名称 |
|||
*/ |
|||
deptName?: string; |
|||
/** |
|||
* 用户邮箱 |
|||
*/ |
|||
email?: string; |
|||
/** |
|||
* 性别 |
|||
*/ |
|||
genderLabel?: string; |
|||
/** |
|||
* 用户ID |
|||
*/ |
|||
id?: number; |
|||
/** |
|||
* 手机号 |
|||
*/ |
|||
mobile?: string; |
|||
/** |
|||
* 用户昵称 |
|||
*/ |
|||
nickname?: string; |
|||
/** |
|||
* 角色名称,多个使用英文逗号(,)分割 |
|||
*/ |
|||
roleNames?: string; |
|||
/** |
|||
* 用户状态(1:启用;0:禁用) |
|||
*/ |
|||
status?: number; |
|||
/** |
|||
* 用户名 |
|||
*/ |
|||
username?: string; |
|||
} |
|||
|
|||
/** |
|||
* 用户表单类型 |
|||
*/ |
|||
export interface UserForm { |
|||
/** |
|||
* 用户头像 |
|||
*/ |
|||
avatar?: string; |
|||
/** |
|||
* 部门ID |
|||
*/ |
|||
deptId?: number; |
|||
/** |
|||
* 邮箱 |
|||
*/ |
|||
email?: string; |
|||
/** |
|||
* 性别 |
|||
*/ |
|||
gender?: number; |
|||
/** |
|||
* 用户ID |
|||
*/ |
|||
id?: number; |
|||
mobile?: string; |
|||
/** |
|||
* 昵称 |
|||
*/ |
|||
nickname?: string; |
|||
/** |
|||
* 角色ID集合 |
|||
*/ |
|||
roleIds?: number[]; |
|||
/** |
|||
* 用户状态(1:正常;0:禁用) |
|||
*/ |
|||
status?: number; |
|||
/** |
|||
* 用户名 |
|||
*/ |
|||
username?: string; |
|||
} |
|||
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 179 B |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 395 B |
|
After Width: | Height: | Size: 279 B |
|
After Width: | Height: | Size: 647 B |
|
After Width: | Height: | Size: 284 B |
|
After Width: | Height: | Size: 693 B |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 927 B |
|
After Width: | Height: | Size: 909 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 356 B |
|
After Width: | Height: | Size: 818 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 944 B |
|
After Width: | Height: | Size: 421 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 320 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 730 B |
|
After Width: | Height: | Size: 1001 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 914 B |
|
After Width: | Height: | Size: 883 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 821 B |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 367 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 561 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 211 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 689 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 959 B |
|
After Width: | Height: | Size: 988 B |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 334 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
@ -0,0 +1,103 @@ |
|||
<template> |
|||
<el-breadcrumb class="h-[50px] flex items-center"> |
|||
<transition-group name="breadcrumb"> |
|||
<el-breadcrumb-item v-for="(item, index) in breadcrumbs" :key="item.path"> |
|||
<span |
|||
v-if=" |
|||
item.redirect === 'noredirect' || index === breadcrumbs.length - 1 |
|||
" |
|||
class="text-[var(--el-disabled-text-color)]" |
|||
>{{ translateRouteTitleI18n(item.meta.title) }}</span |
|||
> |
|||
<a v-else @click.prevent="handleLink(item)"> |
|||
{{ translateRouteTitleI18n(item.meta.title) }} |
|||
</a> |
|||
</el-breadcrumb-item> |
|||
</transition-group> |
|||
</el-breadcrumb> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { onBeforeMount, ref, watch } from "vue"; |
|||
import { useRoute, RouteLocationMatched } from "vue-router"; |
|||
import { compile } from "path-to-regexp"; |
|||
import router from "@/router"; |
|||
import { translateRouteTitleI18n } from "@/utils/i18n"; |
|||
|
|||
const currentRoute = useRoute(); |
|||
const pathCompile = (path: string) => { |
|||
const { params } = currentRoute; |
|||
const toPath = compile(path); |
|||
return toPath(params); |
|||
}; |
|||
|
|||
const breadcrumbs = ref([] as Array<RouteLocationMatched>); |
|||
|
|||
function getBreadcrumb() { |
|||
let matched = currentRoute.matched.filter( |
|||
(item) => item.meta && item.meta.title |
|||
); |
|||
const first = matched[0]; |
|||
if (!isDashboard(first)) { |
|||
matched = [ |
|||
{ path: "/dashboard", meta: { title: "dashboard" } } as any, |
|||
].concat(matched); |
|||
} |
|||
breadcrumbs.value = matched.filter((item) => { |
|||
return item.meta && item.meta.title && item.meta.breadcrumb !== false; |
|||
}); |
|||
} |
|||
|
|||
function isDashboard(route: RouteLocationMatched) { |
|||
const name = route && route.name; |
|||
if (!name) { |
|||
return false; |
|||
} |
|||
return ( |
|||
name.toString().trim().toLocaleLowerCase() === |
|||
"Dashboard".toLocaleLowerCase() |
|||
); |
|||
} |
|||
|
|||
function handleLink(item: any) { |
|||
const { redirect, path } = item; |
|||
if (redirect) { |
|||
router.push(redirect).catch((err) => { |
|||
console.warn(err); |
|||
}); |
|||
return; |
|||
} |
|||
router.push(pathCompile(path)).catch((err) => { |
|||
console.warn(err); |
|||
}); |
|||
} |
|||
|
|||
watch( |
|||
() => currentRoute.path, |
|||
(path) => { |
|||
if (path.startsWith("/redirect/")) { |
|||
return; |
|||
} |
|||
getBreadcrumb(); |
|||
} |
|||
); |
|||
|
|||
onBeforeMount(() => { |
|||
getBreadcrumb(); |
|||
}); |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.app-breadcrumb.el-breadcrumb { |
|||
display: inline-block; |
|||
margin-left: 8px; |
|||
font-size: 14px; |
|||
line-height: 50px; |
|||
} |
|||
|
|||
// 覆盖 element-plus 的样式 |
|||
.el-breadcrumb__inner, |
|||
.el-breadcrumb__inner a { |
|||
font-weight: 400 !important; |
|||
} |
|||
</style> |
|||