优化一些组件效果
This commit is contained in:
parent
2c10bb44d5
commit
16e2611a1e
|
@ -0,0 +1,4 @@
|
|||
> 1%
|
||||
last 2 versions
|
||||
not dead
|
||||
not ie 11
|
|
@ -0,0 +1 @@
|
|||
export { default } from '@vben/commitlint-config';
|
|
@ -0,0 +1,5 @@
|
|||
node_modules
|
||||
.git
|
||||
.gitignore
|
||||
*.md
|
||||
dist
|
|
@ -1,11 +1,18 @@
|
|||
# Editor configuration, see http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset=utf-8
|
||||
end_of_line=lf
|
||||
insert_final_newline=true
|
||||
indent_style=space
|
||||
indent_size=2
|
||||
end_of_line = lf
|
||||
max_line_length = 100
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
quote_type = single
|
||||
|
||||
[*.{yml,yaml,json}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
|
48
.env
48
.env
|
@ -1,48 +0,0 @@
|
|||
VITE_BASE_URL=/
|
||||
|
||||
VITE_APP_TITLE=ERP 综合办公系统
|
||||
|
||||
VITE_APP_DESC=
|
||||
|
||||
# the prefix of the icon name
|
||||
VITE_ICON_PREFIX=icon
|
||||
|
||||
# the prefix of the local svg icon component, must include VITE_ICON_PREFIX
|
||||
# format {VITE_ICON_PREFIX}-{local icon name}
|
||||
VITE_ICON_LOCAL_PREFIX=icon-local
|
||||
|
||||
# 路由模式: static 静态 | dynamic 动态
|
||||
VITE_AUTH_ROUTE_MODE=dynamic
|
||||
|
||||
# static 静态路由首页地址
|
||||
VITE_ROUTE_HOME=home
|
||||
|
||||
# 默认菜单图标
|
||||
VITE_MENU_ICON=mdi:menu
|
||||
|
||||
# 当在开发模式下,是否使用代理
|
||||
VITE_HTTP_PROXY=Y
|
||||
|
||||
# vue-router 路由模式: hash | history | memory
|
||||
VITE_ROUTER_HISTORY_MODE=history
|
||||
|
||||
# success code of backend service, when the code is received, the request is successful
|
||||
VITE_SERVICE_SUCCESS_CODE=200
|
||||
|
||||
# logout codes of backend service, when the code is received, the user will be logged out and redirected to login page
|
||||
VITE_SERVICE_LOGOUT_CODES=8888,8889
|
||||
|
||||
# modal logout codes of backend service, when the code is received, the user will be logged out by displaying a modal
|
||||
VITE_SERVICE_MODAL_LOGOUT_CODES=7777,7778
|
||||
|
||||
# token expired codes of backend service, when the code is received, it will refresh the token and resend the request
|
||||
VITE_SERVICE_EXPIRED_TOKEN_CODES=9999,9998
|
||||
|
||||
# when the route mode is static, the defined super role
|
||||
VITE_STATIC_SUPER_ROLE=R_SUPER
|
||||
|
||||
# sourcemap
|
||||
VITE_SOURCE_MAP=N
|
||||
|
||||
# Used to differentiate storage across different domains
|
||||
VITE_STORAGE_PREFIX=app_
|
|
@ -1,7 +0,0 @@
|
|||
# backend service base url, prod environment
|
||||
VITE_SERVICE_BASE_URL=https://mock.apifox.com/m1/3109515-0-default
|
||||
|
||||
# other backend service base url, prod environment
|
||||
VITE_OTHER_SERVICE_BASE_URL= `{
|
||||
"demo": "http://localhost:9529"
|
||||
}`
|
|
@ -1,7 +0,0 @@
|
|||
# backend service base url, prod environment
|
||||
VITE_SERVICE_BASE_URL=http://192.168.147.238:8083
|
||||
|
||||
# other backend service base url, prod environment
|
||||
VITE_OTHER_SERVICE_BASE_URL= `{
|
||||
"demo": "http://localhost:9529"
|
||||
}`
|
|
@ -1,3 +0,0 @@
|
|||
module.exports = {
|
||||
extends: ['antfu'],
|
||||
};
|
|
@ -1,13 +1,11 @@
|
|||
"*.vue" eol=lf
|
||||
"*.js" eol=lf
|
||||
"*.ts" eol=lf
|
||||
"*.jsx" eol=lf
|
||||
"*.tsx" eol=lf
|
||||
"*.mjs" eol=lf
|
||||
"*.json" eol=lf
|
||||
"*.html" eol=lf
|
||||
"*.css" eol=lf
|
||||
"*.scss" eol=lf
|
||||
"*.md" eol=lf
|
||||
"*.yaml" eol=lf
|
||||
"*.yml" eol=lf
|
||||
# https://docs.github.com/cn/get-started/getting-started-with-git/configuring-git-to-handle-line-endings
|
||||
|
||||
# Automatically normalize line endings (to LF) for all text-based files.
|
||||
* text=auto eol=lf
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
*.{cmd,[cC][mM][dD]} text eol=crlf
|
||||
*.{bat,[bB][aA][tT]} text eol=crlf
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.{ico,png,jpg,jpeg,gif,webp,svg,woff,woff2} binary
|
|
@ -0,0 +1,2 @@
|
|||
[core]
|
||||
ignorecase = false
|
|
@ -1,4 +1,33 @@
|
|||
# Logs
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
dist.zip
|
||||
dist.tar
|
||||
dist.war
|
||||
.nitro
|
||||
.output
|
||||
*-dist.zip
|
||||
*-dist.tar
|
||||
*-dist.war
|
||||
coverage
|
||||
*.local
|
||||
**/.vitepress/cache
|
||||
.cache
|
||||
.turbo
|
||||
.temp
|
||||
dev-dist
|
||||
.stylelintcache
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
.VSCodeCounter
|
||||
**/backend-mock/data
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
.eslintcache
|
||||
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
@ -6,31 +35,17 @@ yarn-debug.log*
|
|||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
vite.config.mts.*
|
||||
vite.config.mjs.*
|
||||
vite.config.js.*
|
||||
vite.config.ts.*
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
!.vscode/settings.json
|
||||
!.vscode/launch.json
|
||||
.idea
|
||||
# .vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
.history
|
||||
.VSCodeCounter
|
||||
vite.config.ts.**
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
ports:
|
||||
- port: 5555
|
||||
onOpen: open-preview
|
||||
tasks:
|
||||
- init: corepack enable && pnpm install
|
||||
command: pnpm run dev
|
|
@ -0,0 +1,6 @@
|
|||
echo Start running commit-msg hook...
|
||||
|
||||
# Check whether the git commit information is standardized
|
||||
pnpm exec commitlint --edit "$1"
|
||||
|
||||
echo Run commit-msg hook done.
|
|
@ -0,0 +1,3 @@
|
|||
# 每次 git pull 之后, 安装依赖
|
||||
|
||||
pnpm install
|
|
@ -0,0 +1,7 @@
|
|||
# update `.vscode/vben-admin.code-workspace` file
|
||||
pnpm vsh code-workspace --auto-commit
|
||||
|
||||
# Format and submit code according to lintstagedrc.js configuration
|
||||
pnpm exec lint-staged
|
||||
|
||||
echo Run pre-commit hook done.
|
|
@ -0,0 +1,20 @@
|
|||
export default {
|
||||
'{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': [
|
||||
'prettier --cache --write--parser json',
|
||||
],
|
||||
'*.{js,jsx,ts,tsx}': [
|
||||
'prettier --cache --ignore-unknown --write',
|
||||
'eslint --cache --fix',
|
||||
],
|
||||
'*.{scss,less,styl,html,vue,css}': [
|
||||
'prettier --cache --ignore-unknown --write',
|
||||
'stylelint --fix --allow-empty-input',
|
||||
],
|
||||
'*.md': ['prettier --cache --ignore-unknown --write'],
|
||||
'*.vue': [
|
||||
'prettier --write',
|
||||
'eslint --cache --fix',
|
||||
'stylelint --fix --allow-empty-input',
|
||||
],
|
||||
'package.json': ['prettier --cache --write'],
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
ls:
|
||||
.js: kebab-case | pointcase
|
||||
.vue: kebab-case | pointcase
|
||||
.ts: kebab-case | pointcase
|
||||
.tsx: kebab-case | pointcase
|
||||
.jsx: kebab-case | pointcase
|
||||
.css: kebab-case | pointcase
|
||||
.d.ts: kebab-case | pointcase
|
||||
# shadcn 自动生成文件为 PascalCase 格式
|
||||
packages/@core/ui-kit/shadcn-ui/src/components/ui:
|
||||
.vue: PascalCase
|
||||
|
||||
ignore:
|
||||
- "**/*.png"
|
||||
- "**/*.jpg"
|
||||
- "**/*.jpeg"
|
||||
- "**/*.jpeg"
|
||||
- "**/*.gif"
|
||||
- "**/_util.ts"
|
||||
- "**/deps/**"
|
||||
- "**/dist/**"
|
||||
- "**/node_modules/**"
|
||||
- "**/.turbo/**"
|
||||
- .git
|
||||
- .vscode
|
||||
- .idea
|
||||
- node_modules
|
||||
- .cache
|
|
@ -0,0 +1 @@
|
|||
20.14.0
|
17
.npmrc
17
.npmrc
|
@ -1,4 +1,13 @@
|
|||
registry=https://registry.npmmirror.com/
|
||||
shamefully-hoist=true
|
||||
ignore-workspace-root-check=true
|
||||
link-workspace-packages=true
|
||||
registry = "https://registry.npmmirror.com"
|
||||
public-hoist-pattern[]=husky
|
||||
public-hoist-pattern[]=eslint
|
||||
public-hoist-pattern[]=prettier
|
||||
public-hoist-pattern[]=prettier-plugin-tailwindcss
|
||||
public-hoist-pattern[]=stylelint
|
||||
public-hoist-pattern[]=*postcss*
|
||||
public-hoist-pattern[]=@commitlint/*
|
||||
public-hoist-pattern[]=czg
|
||||
|
||||
strict-peer-dependencies=false
|
||||
auto-install-peers=true
|
||||
dedupe-peer-dependents=true
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
dist
|
||||
dev-dist
|
||||
.local
|
||||
.output.js
|
||||
node_modules
|
||||
.nvmrc
|
||||
coverage
|
||||
CODEOWNERS
|
||||
.nitro
|
||||
.output
|
||||
|
||||
|
||||
**/*.svg
|
||||
**/*.sh
|
||||
|
||||
public
|
||||
.npmrc
|
||||
*-lock.yaml
|
|
@ -0,0 +1 @@
|
|||
export { default } from '@vben/prettier-config';
|
|
@ -0,0 +1,4 @@
|
|||
dist
|
||||
public
|
||||
__tests__
|
||||
coverage
|
|
@ -1,34 +1,28 @@
|
|||
{
|
||||
"recommendations": [
|
||||
// my extensions, ofc :P
|
||||
"antfu.browse-lite",
|
||||
"antfu.iconify",
|
||||
"antfu.slidev",
|
||||
"antfu.unocss",
|
||||
"antfu.vite",
|
||||
"antfu.where-am-i",
|
||||
"antfu.open-in-github-button",
|
||||
"lokalise.i18n-ally",
|
||||
// themes & icons
|
||||
"antfu.icons-carbon",
|
||||
"antfu.theme-vitesse",
|
||||
"file-icons.file-icons",
|
||||
"sainnhe.gruvbox-material",
|
||||
// life savers!
|
||||
"dbaeumer.vscode-eslint",
|
||||
// Vue 3 的语言支持
|
||||
"Vue.volar",
|
||||
"GitHub.copilot",
|
||||
"usernamehw.errorlens",
|
||||
// 将 ESLint JavaScript 集成到 VS Code 中。
|
||||
"dbaeumer.vscode-eslint",
|
||||
// Visual Studio Code 的官方 Stylelint 扩展
|
||||
"stylelint.vscode-stylelint",
|
||||
// 使用 Prettier 的代码格式化程序
|
||||
"esbenp.prettier-vscode",
|
||||
// 支持 dotenv 文件语法
|
||||
"mikestead.dotenv",
|
||||
// 源代码的拼写检查器
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
// up to you
|
||||
"eamodio.gitlens",
|
||||
"EditorConfig.EditorConfig",
|
||||
"github.vscode-github-actions",
|
||||
"GitHub.vscode-pull-request-github",
|
||||
"johnsoncodehk.vscode-tsconfig-helper",
|
||||
"mpontus.tab-cycle",
|
||||
"naumovs.color-highlight",
|
||||
"WakaTime.vscode-wakatime",
|
||||
"znck.grammarly"
|
||||
// Tailwind CSS 的官方 VS Code 插件
|
||||
"bradlc.vscode-tailwindcss",
|
||||
// iconify 图标插件
|
||||
"antfu.iconify",
|
||||
// i18n 插件
|
||||
"Lokalise.i18n-ally",
|
||||
// CSS 变量提示
|
||||
"vunguyentuan.vscode-css-variables"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
// 和 volar 冲突
|
||||
"octref.vetur"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"import": {
|
||||
"scope": "javascript,typescript",
|
||||
"prefix": "im",
|
||||
"body": ["import { $2 } from '$1';"],
|
||||
"description": "Import a module",
|
||||
},
|
||||
"export-all": {
|
||||
"scope": "javascript,typescript",
|
||||
"prefix": "ex",
|
||||
"body": ["export * from '$1';"],
|
||||
"description": "Export a module",
|
||||
},
|
||||
"vue-script-setup": {
|
||||
"scope": "vue",
|
||||
"prefix": "<sc",
|
||||
"body": [
|
||||
"<script setup lang=\"ts\">",
|
||||
"const props = defineProps<{",
|
||||
" modelValue?: boolean,",
|
||||
"}>()",
|
||||
"$1",
|
||||
"</script>",
|
||||
"",
|
||||
"<template>",
|
||||
" <div>",
|
||||
" <slot/>",
|
||||
" </div>",
|
||||
"</template>",
|
||||
],
|
||||
},
|
||||
"vue-computed": {
|
||||
"scope": "javascript,typescript,vue",
|
||||
"prefix": "com",
|
||||
"body": ["computed(() => { $1 })"],
|
||||
},
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"name": "vben admin playground dev",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:5555",
|
||||
"env": { "NODE_ENV": "development" },
|
||||
"sourceMaps": true,
|
||||
"webRoot": "${workspaceFolder}/playground/src"
|
||||
},
|
||||
{
|
||||
"type": "chrome",
|
||||
"name": "vben admin antd dev",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:5666",
|
||||
"env": { "NODE_ENV": "development" },
|
||||
"sourceMaps": true,
|
||||
"webRoot": "${workspaceFolder}/apps/web-antd/src"
|
||||
},
|
||||
{
|
||||
"type": "chrome",
|
||||
"name": "vben admin ele dev",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:5777",
|
||||
"env": { "NODE_ENV": "development" },
|
||||
"sourceMaps": true,
|
||||
"webRoot": "${workspaceFolder}/apps/web-ele/src"
|
||||
},
|
||||
{
|
||||
"type": "chrome",
|
||||
"name": "vben admin naive dev",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:5888",
|
||||
"env": { "NODE_ENV": "development" },
|
||||
"sourceMaps": true,
|
||||
"webRoot": "${workspaceFolder}/apps/web-naive/src"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,304 +1,228 @@
|
|||
{
|
||||
// ========== Visuals ==========
|
||||
"editor.cursorSmoothCaretAnimation": "on",
|
||||
// "editor.fontFamily": "Input Mono, monospace",
|
||||
"editor.guides.bracketPairs": "active",
|
||||
"editor.lineNumbers": "interval",
|
||||
"editor.renderWhitespace": "boundary",
|
||||
"window.autoDetectColorScheme": true,
|
||||
"workbench.colorTheme": "Vitesse Dark Soft",
|
||||
"workbench.editor.tabActionLocation": "left",
|
||||
"workbench.fontAliasing": "antialiased",
|
||||
"workbench.iconTheme": "file-icons-colourless",
|
||||
"tailwindCSS.experimental.configFile": "internal/tailwind-config/src/index.ts",
|
||||
// workbench
|
||||
"workbench.list.smoothScrolling": true,
|
||||
"workbench.preferredDarkColorTheme": "Vitesse Dark",
|
||||
"workbench.preferredLightColorTheme": "Vitesse Dark Soft",
|
||||
"workbench.productIconTheme": "icons-carbon",
|
||||
"workbench.sideBar.location": "right",
|
||||
"workbench.startupEditor": "newUntitledFile",
|
||||
"workbench.tree.expandMode": "singleClick",
|
||||
"workbench.tree.indent": 10,
|
||||
// ========== Editor ==========
|
||||
"debug.onTaskErrors": "debugAnyway",
|
||||
"diffEditor.ignoreTrimWhitespace": true,
|
||||
"editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?",
|
||||
"editor.find.addExtraSpaceOnTop": false,
|
||||
"editor.inlineSuggest.enabled": true,
|
||||
"editor.multiCursorModifier": "ctrlCmd",
|
||||
"editor.suggestSelection": "first",
|
||||
"editor.tabSize": 2,
|
||||
"editor.unicodeHighlight.invisibleCharacters": false,
|
||||
"editor.stickyScroll.enabled": true,
|
||||
"editor.hover.sticky": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": "never",
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.organizeImports": "never"
|
||||
},
|
||||
"explorer.confirmDelete": false,
|
||||
"explorer.confirmDragAndDrop": false,
|
||||
"files.eol": "\n",
|
||||
"files.insertFinalNewline": true,
|
||||
"files.simpleDialog.enable": true,
|
||||
"git.autofetch": true,
|
||||
"git.confirmSync": false,
|
||||
"git.enableSmartCommit": true,
|
||||
"git.untrackedChanges": "separate",
|
||||
"scm.diffDecorationsGutterWidth": 2,
|
||||
"terminal.integrated.cursorBlinking": true,
|
||||
"terminal.integrated.cursorStyle": "line",
|
||||
"terminal.integrated.fontWeight": "300",
|
||||
"terminal.integrated.persistentSessionReviveProcess": "never",
|
||||
"terminal.integrated.tabs.enabled": true,
|
||||
"workbench.editor.closeOnFileDelete": true,
|
||||
"workbench.editor.highlightModifiedTabs": true,
|
||||
"workbench.editor.closeOnFileDelete": true,
|
||||
"workbench.editor.limit.enabled": true,
|
||||
"workbench.editor.limit.perEditorGroup": true,
|
||||
"workbench.editor.limit.value": 5,
|
||||
"search.exclude": {
|
||||
"**/*.snap": true,
|
||||
"**/*.svg": true,
|
||||
"**/.git": true,
|
||||
"**/.github": false,
|
||||
"**/.nuxt": true,
|
||||
"**/.output": true,
|
||||
"**/.pnpm": true,
|
||||
"**/.vscode": true,
|
||||
"**/.yarn": true,
|
||||
"**/assets": true,
|
||||
"**/bower_components": true,
|
||||
"**/dist/**": true,
|
||||
"**/logs": true,
|
||||
"**/node_modules": true,
|
||||
"**/out/**": true,
|
||||
"**/package-lock.json": true,
|
||||
"**/pnpm-lock.yaml": true,
|
||||
"**/public": true,
|
||||
"**/temp": true,
|
||||
"**/yarn.lock": true,
|
||||
"**/CHANGELOG*": true,
|
||||
"**/LICENSE*": true,
|
||||
|
||||
// editor
|
||||
"editor.tabSize": 2,
|
||||
"editor.detectIndentation": false,
|
||||
"editor.cursorBlinking": "expand",
|
||||
"editor.largeFileOptimizations": false,
|
||||
"editor.accessibilitySupport": "off",
|
||||
"editor.cursorSmoothCaretAnimation": "on",
|
||||
"editor.guides.bracketPairs": "active",
|
||||
"editor.inlineSuggest.enabled": true,
|
||||
"editor.suggestSelection": "recentlyUsedByPrefix",
|
||||
"editor.acceptSuggestionOnEnter": "smart",
|
||||
"editor.suggest.snippetsPreventQuickSuggestions": false,
|
||||
"editor.stickyScroll.enabled": true,
|
||||
"editor.hover.sticky": true,
|
||||
"editor.suggest.insertMode": "replace",
|
||||
"editor.bracketPairColorization.enabled": true,
|
||||
"editor.autoClosingBrackets": "beforeWhitespace",
|
||||
"editor.autoClosingDelete": "always",
|
||||
"editor.autoClosingOvertype": "always",
|
||||
"editor.autoClosingQuotes": "beforeWhitespace",
|
||||
"editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.fixAll.stylelint": "explicit",
|
||||
"source.organizeImports": "never"
|
||||
},
|
||||
// ========== Global Level Config, needs to put in User Settings ==========
|
||||
"window.dialogStyle": "custom",
|
||||
"window.nativeTabs": true, // this is great, macOS only
|
||||
"window.title": "${rootName}", // this make tabs more readable
|
||||
"window.titleBarStyle": "custom",
|
||||
"extensions.autoUpdate": "onlyEnabledExtensions",
|
||||
// ========== Extension configs ==========
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"[html]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[css]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[scss]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "vscode.typescript-language-features"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[markdown]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[vue]": {
|
||||
"editor.defaultFormatter": "Vue.volar"
|
||||
},
|
||||
// extensions
|
||||
"extensions.ignoreRecommendations": true,
|
||||
|
||||
// terminal
|
||||
"terminal.integrated.cursorBlinking": true,
|
||||
"terminal.integrated.persistentSessionReviveProcess": "never",
|
||||
"terminal.integrated.tabs.enabled": true,
|
||||
"terminal.integrated.scrollback": 10000,
|
||||
"terminal.integrated.stickyScroll.enabled": true,
|
||||
|
||||
// files
|
||||
"files.eol": "\n",
|
||||
"files.insertFinalNewline": true,
|
||||
"files.simpleDialog.enable": true,
|
||||
"files.associations": {
|
||||
"*.ejs": "html",
|
||||
"*.art": "html",
|
||||
"**/tsconfig.json": "jsonc",
|
||||
"*.json": "jsonc",
|
||||
"package.json": "json"
|
||||
},
|
||||
|
||||
"files.exclude": {
|
||||
"**/.eslintcache": true,
|
||||
"**/bower_components": true,
|
||||
"**/.turbo": true,
|
||||
"**/.idea": true,
|
||||
"**/tmp": true,
|
||||
"**/.git": true,
|
||||
"**/.svn": true,
|
||||
"**/.hg": true,
|
||||
"**/CVS": true,
|
||||
"**/.stylelintcache": true,
|
||||
"**/.DS_Store": true,
|
||||
"**/vite.config.mts.*": true,
|
||||
"**/tea.yaml": true
|
||||
},
|
||||
"files.watcherExclude": {
|
||||
"**/.git/objects/**": true,
|
||||
"**/.git/subtree-cache/**": true,
|
||||
"**/.vscode/**": true,
|
||||
"**/node_modules/**": true,
|
||||
"**/tmp/**": true,
|
||||
"**/bower_components/**": true,
|
||||
"**/dist/**": true,
|
||||
"**/yarn.lock": true
|
||||
},
|
||||
|
||||
// search
|
||||
"search.searchEditor.singleClickBehaviour": "peekDefinition",
|
||||
"search.followSymlinks": false,
|
||||
// 在使用搜索功能时,将这些文件夹/文件排除在外
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/*.log": true,
|
||||
"**/*.log*": true,
|
||||
"**/bower_components": true,
|
||||
"**/dist": true,
|
||||
"**/elehukouben": true,
|
||||
"**/.git": true,
|
||||
"**/.github": true,
|
||||
"**/.gitignore": true,
|
||||
"**/.svn": true,
|
||||
"**/.DS_Store": true,
|
||||
"**/.vitepress/cache": true,
|
||||
"**/.idea": true,
|
||||
"**/.vscode": false,
|
||||
"**/.yarn": true,
|
||||
"**/tmp": true,
|
||||
"*.xml": true,
|
||||
"out": true,
|
||||
"dist": true,
|
||||
"node_modules": true,
|
||||
"CHANGELOG.md": true,
|
||||
"**/pnpm-lock.yaml": true,
|
||||
"**/yarn.lock": true
|
||||
},
|
||||
|
||||
"debug.onTaskErrors": "debugAnyway",
|
||||
"diffEditor.ignoreTrimWhitespace": false,
|
||||
"npm.packageManager": "pnpm",
|
||||
|
||||
"css.validate": false,
|
||||
"less.validate": false,
|
||||
"scss.validate": false,
|
||||
|
||||
// extension
|
||||
"emmet.showSuggestionsAsSnippets": true,
|
||||
"emmet.triggerExpansionOnTab": false,
|
||||
"errorLens.enabledDiagnosticLevels": [
|
||||
"warning",
|
||||
"error"
|
||||
],
|
||||
"errorLens.excludeBySource": [
|
||||
"cSpell",
|
||||
"Grammarly",
|
||||
"eslint"
|
||||
],
|
||||
// ESLint config: https://github.com/antfu/eslint-config
|
||||
"eslint.codeAction.showDocumentation": {
|
||||
"enable": true
|
||||
},
|
||||
"eslint.quiet": true,
|
||||
// Silent the stylistic rules in you IDE, but still auto fix them
|
||||
"eslint.rules.customizations": [
|
||||
{
|
||||
"rule": "style/*",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "format/*",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*-indent",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*-spacing",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*-spaces",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*-order",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*-dangle",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*-newline",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*quotes",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*semi",
|
||||
"severity": "off"
|
||||
}
|
||||
],
|
||||
|
||||
"errorLens.enabledDiagnosticLevels": ["warning", "error"],
|
||||
"errorLens.excludeBySource": ["cSpell", "Grammarly", "eslint"],
|
||||
|
||||
"stylelint.enable": true,
|
||||
"stylelint.packageManager": "pnpm",
|
||||
"stylelint.validate": ["css", "less", "postcss", "scss", "vue"],
|
||||
"stylelint.snippet": ["css", "less", "postcss", "scss", "vue"],
|
||||
|
||||
"typescript.inlayHints.enumMemberValues.enabled": true,
|
||||
"typescript.preferences.preferTypeOnlyAutoImports": true,
|
||||
"typescript.preferences.includePackageJsonAutoImports": "on",
|
||||
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"typescript",
|
||||
"javascriptreact",
|
||||
"typescriptreact",
|
||||
"vue",
|
||||
"html",
|
||||
"markdown",
|
||||
"json",
|
||||
"jsonc",
|
||||
"yaml",
|
||||
"toml"
|
||||
"json5"
|
||||
],
|
||||
|
||||
"tailwindCSS.experimental.classRegex": [
|
||||
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
|
||||
],
|
||||
|
||||
"github.copilot.enable": {
|
||||
"*": true,
|
||||
"markdown": true,
|
||||
"plaintext": false,
|
||||
"yaml": false
|
||||
},
|
||||
"cSpell.allowCompoundWords": true,
|
||||
"cSpell.language": "en,en-US",
|
||||
"css.lint.hexColorLength": "ignore",
|
||||
"githubIssues.workingIssueFormatScm": "#${issueNumberLabel}",
|
||||
"githubPullRequests.fileListLayout": "tree",
|
||||
"gitlens.codeLens.authors.enabled": false,
|
||||
"gitlens.codeLens.enabled": false,
|
||||
"gitlens.codeLens.recentChange.enabled": false,
|
||||
"gitlens.menus": {
|
||||
"editor": {
|
||||
"blame": false,
|
||||
"clipboard": true,
|
||||
"compare": true,
|
||||
"history": false,
|
||||
"remote": false
|
||||
},
|
||||
"editorGroup": {
|
||||
"blame": true,
|
||||
"compare": false
|
||||
},
|
||||
"editorTab": {
|
||||
"clipboard": true,
|
||||
"compare": true,
|
||||
"history": true,
|
||||
"remote": true
|
||||
},
|
||||
"explorer": {
|
||||
"clipboard": true,
|
||||
"compare": true,
|
||||
"history": true,
|
||||
"remote": true
|
||||
},
|
||||
"scm": {
|
||||
"authors": true
|
||||
},
|
||||
"scmGroup": {
|
||||
"compare": true,
|
||||
"openClose": true,
|
||||
"stash": true
|
||||
},
|
||||
"scmGroupInline": {
|
||||
"stash": true
|
||||
},
|
||||
"scmItem": {
|
||||
"clipboard": true,
|
||||
"compare": true,
|
||||
"history": true,
|
||||
"remote": false,
|
||||
"stash": true
|
||||
}
|
||||
},
|
||||
"i18n-ally.autoDetection": false,
|
||||
"i18n-ally.displayLanguage": "en",
|
||||
"i18n-ally.ignoredLocales": [],
|
||||
"iconify.annotations": true,
|
||||
"iconify.inplace": true,
|
||||
"svg.preview.mode": "svg",
|
||||
// I only use Prettier for manually formatting
|
||||
"prettier.enable": false,
|
||||
"prettier.printWidth": 200,
|
||||
"prettier.semi": false,
|
||||
"prettier.singleQuote": true,
|
||||
// ========== File Nesting ==========
|
||||
// this might not be up to date with the repo, please check yourself
|
||||
// https://github.com/antfu/vscode-file-nesting-config
|
||||
|
||||
"cssVariables.lookupFiles": ["packages/core/base/design/src/**/*.css"],
|
||||
|
||||
"i18n-ally.localesPaths": [
|
||||
"packages/locales/src/langs",
|
||||
"playground/src/locales/langs",
|
||||
"apps/*/src/locales/langs"
|
||||
],
|
||||
"i18n-ally.pathMatcher": "{locale}.json",
|
||||
"i18n-ally.enabledParsers": ["json", "ts", "js", "yaml"],
|
||||
"i18n-ally.sourceLanguage": "en",
|
||||
"i18n-ally.displayLanguage": "zh-CN",
|
||||
"i18n-ally.enabledFrameworks": ["vue", "react"],
|
||||
|
||||
// 控制相关文件嵌套展示
|
||||
"explorer.fileNesting.enabled": true,
|
||||
"explorer.fileNesting.expand": false,
|
||||
"explorer.fileNesting.patterns": {
|
||||
"*.asax": "$(capture).*.cs, $(capture).*.vb",
|
||||
"*.ascx": "$(capture).*.cs, $(capture).*.vb",
|
||||
"*.ashx": "$(capture).*.cs, $(capture).*.vb",
|
||||
"*.aspx": "$(capture).*.cs, $(capture).*.vb",
|
||||
"*.bloc.dart": "$(capture).event.dart, $(capture).state.dart",
|
||||
"*.c": "$(capture).h",
|
||||
"*.cc": "$(capture).hpp, $(capture).h, $(capture).hxx",
|
||||
"*.cjs": "$(capture).cjs.map, $(capture).*.cjs, $(capture)_*.cjs",
|
||||
"*.component.ts": "$(capture).component.html, $(capture).component.spec.ts, $(capture).component.css, $(capture).component.scss, $(capture).component.sass, $(capture).component.less",
|
||||
"*.cpp": "$(capture).hpp, $(capture).h, $(capture).hxx",
|
||||
"*.cs": "$(capture).*.cs",
|
||||
"*.cshtml": "$(capture).cshtml.cs",
|
||||
"*.csproj": "*.config, *proj.user, appsettings.*, bundleconfig.json",
|
||||
"*.css": "$(capture).css.map, $(capture).*.css",
|
||||
"*.cxx": "$(capture).hpp, $(capture).h, $(capture).hxx",
|
||||
"*.dart": "$(capture).freezed.dart, $(capture).g.dart",
|
||||
"*.ex": "$(capture).html.eex, $(capture).html.heex, $(capture).html.leex",
|
||||
"*.go": "$(capture)_test.go",
|
||||
"*.java": "$(capture).class",
|
||||
"*.js": "$(capture).js.map, $(capture).*.js, $(capture)_*.js",
|
||||
"*.jsx": "$(capture).js, $(capture).*.jsx, $(capture)_*.js, $(capture)_*.jsx",
|
||||
"*.master": "$(capture).*.cs, $(capture).*.vb",
|
||||
"*.mjs": "$(capture).mjs.map, $(capture).*.mjs, $(capture)_*.mjs",
|
||||
"*.module.ts": "$(capture).resolver.ts, $(capture).controller.ts, $(capture).service.ts",
|
||||
"*.pubxml": "$(capture).pubxml.user",
|
||||
"*.resx": "$(capture).*.resx, $(capture).designer.cs, $(capture).designer.vb",
|
||||
"*.tex": "$(capture).acn, $(capture).acr, $(capture).alg, $(capture).aux, $(capture).bbl, $(capture).blg, $(capture).fdb_latexmk, $(capture).fls, $(capture).glg, $(capture).glo, $(capture).gls, $(capture).idx, $(capture).ind, $(capture).ist, $(capture).lof, $(capture).log, $(capture).lot, $(capture).out, $(capture).pdf, $(capture).synctex.gz, $(capture).toc, $(capture).xdv",
|
||||
"*.ts": "$(capture).js, $(capture).d.ts.map, $(capture).*.ts, $(capture)_*.js, $(capture)_*.ts",
|
||||
"*.tsx": "$(capture).ts, $(capture).*.tsx, $(capture)_*.ts, $(capture)_*.tsx",
|
||||
"*.vbproj": "*.config, *proj.user, appsettings.*, bundleconfig.json",
|
||||
"*.vue": "$(capture).*.ts, $(capture).*.js, $(capture).story.vue",
|
||||
"*.xaml": "$(capture).xaml.cs",
|
||||
"+layout.svelte": "+layout.ts,+layout.ts,+layout.js,+layout.server.ts,+layout.server.js,+layout.gql",
|
||||
"+page.svelte": "+page.server.ts,+page.server.js,+page.ts,+page.js,+page.gql",
|
||||
".clang-tidy": ".clang-format, .clangd, compile_commands.json",
|
||||
".env": "*.env, .env.*, .envrc, env.d.ts",
|
||||
".gitignore": ".gitattributes, .gitmodules, .gitmessage, .mailmap, .git-blame*",
|
||||
".project": ".classpath",
|
||||
"//": "Last update at 4/29/2023, 2:04:58 PM",
|
||||
"BUILD.bazel": "*.bzl, *.bazel, *.bazelrc, bazel.rc, .bazelignore, .bazelproject, WORKSPACE",
|
||||
"CMakeLists.txt": "*.cmake, *.cmake.in, .cmake-format.yaml, CMakePresets.json",
|
||||
"I*.cs": "$(capture).cs",
|
||||
"artisan": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, server.php, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, webpack.mix.js, windi.config.*",
|
||||
"astro.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
|
||||
"cargo.toml": ".clippy.toml, .rustfmt.toml, cargo.lock, clippy.toml, cross.toml, rust-toolchain.toml, rustfmt.toml",
|
||||
"composer.json": ".php*.cache, composer.lock, phpunit.xml*, psalm*.xml",
|
||||
"default.nix": "shell.nix",
|
||||
"deno.json*": "*.env, .env.*, .envrc, api-extractor.json, deno.lock, env.d.ts, import-map.json, import_map.json, jsconfig.*, tsconfig.*, tsdoc.*",
|
||||
"dockerfile": ".dockerignore, docker-compose.*, dockerfile*",
|
||||
"flake.nix": "flake.lock",
|
||||
"gatsby-config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, gatsby-browser.*, gatsby-node.*, gatsby-ssr.*, gatsby-transformer.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
|
||||
"gemfile": ".ruby-version, gemfile.lock",
|
||||
"go.mod": ".air*, go.sum",
|
||||
"go.work": "go.work.sum",
|
||||
"mix.exs": ".credo.exs, .dialyzer_ignore.exs, .formatter.exs, .iex.exs, .tool-versions, mix.lock",
|
||||
"next.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, next-env.d.ts, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
|
||||
"nuxt.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
|
||||
"package.json": ".browserslist*, .circleci*, .commitlint*, .cz-config.js, .czrc, .dlint.json, .dprint.json, .editorconfig, .eslint*, .firebase*, .flowconfig, .github*, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .lintstagedrc*, .markdownlint*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .simple-git-hooks*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, apollo.config.*, appveyor*, azure-pipelines*, bower.json, build.config.*, commitlint*, crowdin*, dangerfile*, dlint.json, dprint.json, eslint*, firebase.json, grunt*, gulp*, jenkins*, lerna*, lint-staged*, nest-cli.*, netlify*, nodemon*, npm-shrinkwrap.json, nx.*, package-lock.json, package.nls*.json, phpcs.xml, pm2.*, pnpm*, prettier*, pullapprove*, pyrightconfig.json, release-tasks.sh, release.config.*, renovate*, rollup.config.*, rspack*, simple-git-hooks*, stylelint*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, webpack*, workspace.json, xo.config.*, yarn*",
|
||||
"pubspec.yaml": ".metadata, .packages, all_lint_rules.yaml, analysis_options.yaml, build.yaml, pubspec.lock, pubspec_overrides.yaml",
|
||||
"pyproject.toml": ".pdm.toml, pdm.lock, pyproject.toml",
|
||||
"quasar.conf.js": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, quasar.extensions.json, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
|
||||
"readme*": "authors, backers*, changelog*, citation*, code_of_conduct*, codeowners, contributing*, contributors, copying, credits, governance.md, history.md, license*, maintainers, readme*, security.md, sponsors*",
|
||||
"remix.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, remix.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
|
||||
"rush.json": ".browserslist*, .circleci*, .commitlint*, .cz-config.js, .czrc, .dlint.json, .dprint.json, .editorconfig, .eslint*, .firebase*, .flowconfig, .github*, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .lintstagedrc*, .markdownlint*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .simple-git-hooks*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, apollo.config.*, appveyor*, azure-pipelines*, bower.json, build.config.*, commitlint*, crowdin*, dangerfile*, dlint.json, dprint.json, eslint*, firebase.json, grunt*, gulp*, jenkins*, lerna*, lint-staged*, nest-cli.*, netlify*, nodemon*, npm-shrinkwrap.json, nx.*, package-lock.json, package.nls*.json, phpcs.xml, pm2.*, pnpm*, prettier*, pullapprove*, pyrightconfig.json, release-tasks.sh, release.config.*, renovate*, rollup.config.*, rspack*, simple-git-hooks*, stylelint*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, webpack*, workspace.json, xo.config.*, yarn*",
|
||||
"shims.d.ts": "*.d.ts",
|
||||
"svelte.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, houdini.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, mdsvex.config.js, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vite.config.*, vitest.config.*, webpack.config.*, windi.config.*",
|
||||
"vite.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
|
||||
"vue.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*"
|
||||
"*.ts": "$(capture).test.ts, $(capture).test.tsx, $(capture).spec.ts, $(capture).spec.tsx, $(capture).d.ts",
|
||||
"*.tsx": "$(capture).test.ts, $(capture).test.tsx, $(capture).spec.ts, $(capture).spec.tsx,$(capture).d.ts",
|
||||
"*.env": "$(capture).env.*",
|
||||
"README.md": "README*,CHANGELOG*,LICENSE,CNAME",
|
||||
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,.gitattributes,.gitignore,.gitpod.yml,.npmrc,.browserslistrc,.node-version,.git*,.tazerc.json",
|
||||
"Dockerfile": "Dockerfile,.docker*,docker-entrypoint.sh,build-local-docker*,nginx.conf",
|
||||
"eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,.ls-lint*,cspell.json",
|
||||
"tailwind.config.mjs": "postcss.*"
|
||||
},
|
||||
"commentTranslate.hover.enabled": false,
|
||||
"i18n-ally.keystyle": "nested",
|
||||
"commentTranslate.multiLineMerge": true,
|
||||
"vue.server.hybridMode": true,
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"vue3snippets.enable-compile-vue-file-on-did-save-code": false,
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "vscode.typescript-language-features"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
FROM node:20-slim AS builder
|
||||
|
||||
# --max-old-space-size
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
ENV PATH="$PNPM_HOME:$PATH"
|
||||
ENV NODE_OPTIONS=--max-old-space-size=8192
|
||||
ENV TZ=Asia/Shanghai
|
||||
|
||||
RUN corepack enable
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# copy package.json and pnpm-lock.yaml to workspace
|
||||
COPY . /app
|
||||
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
|
||||
RUN pnpm run build
|
||||
|
||||
RUN echo "Builder Success 🎉"
|
||||
|
||||
FROM nginx:stable-alpine as production
|
||||
|
||||
RUN echo "types { application/javascript js mjs; }" > /etc/nginx/conf.d/mjs.conf
|
||||
COPY --from=builder /app/playground/dist /usr/share/nginx/html
|
||||
|
||||
COPY ./nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
# start nginx
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
20
LICENSE
20
LICENSE
|
@ -1,21 +1,9 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 Soybean
|
||||
Copyright (c) 2024-present, Vben
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.6/source/logo-v1.webp"> </a> <br> <br>
|
||||
|
||||
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
|
||||
|
||||
<h1>Vue Vben Admin</h1>
|
||||
</div>
|
||||
|
||||
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vbenjs_vue-vben-admin&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin) ![codeql](https://github.com/vbenjs/vue-vben-admin/actions/workflows/codeql.yml/badge.svg) ![build](https://github.com/vbenjs/vue-vben-admin/actions/workflows/build.yml/badge.svg) ![ci](https://github.com/vbenjs/vue-vben-admin/actions/workflows/ci.yml/badge.svg) ![deploy](https://github.com/vbenjs/vue-vben-admin/actions/workflows/deploy.yml/badge.svg)
|
||||
|
||||
**日本語** | [English](./README.md) | [中文](./README.zh-CN.md)
|
||||
|
||||
## 紹介
|
||||
|
||||
Vue Vben Adminは、最新の`vue3`、`vite`、`TypeScript`などの主流技術を使用して開発された、無料でオープンソースの中・後端テンプレートです。すぐに使える中・後端のフロントエンドソリューションとして、学習の参考にもなります。
|
||||
|
||||
## アップグレード通知
|
||||
|
||||
これは最新バージョン5.0であり、以前のバージョンとは互換性がありません。新しいプロジェクトを開始する場合は、最新バージョンを使用することをお勧めします。古いバージョンを表示したい場合は、[v2ブランチ](https://github.com/vbenjs/vue-vben-admin/tree/v2)を使用してください。
|
||||
|
||||
## 特徴
|
||||
|
||||
- **最新技術スタック**: Vue 3やViteなどの最先端フロントエンド技術で開発
|
||||
- **TypeScript**: アプリケーション規模のJavaScriptのための言語
|
||||
- **テーマ**: 複数のテーマカラーが利用可能で、カスタマイズオプションも豊富
|
||||
- **国際化**: 完全な内蔵国際化サポート
|
||||
- **権限管理**: 動的ルートベースの権限生成ソリューションを内蔵
|
||||
|
||||
## プレビュー
|
||||
|
||||
- [Vben Admin](https://vben.pro/) - フルバージョンの中国語サイト
|
||||
|
||||
テストアカウント: vben/123456
|
||||
|
||||
<p align="center">
|
||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview1.png">
|
||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview2.png">
|
||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
|
||||
</p>
|
||||
|
||||
### Gitpodを使用
|
||||
|
||||
Gitpod(GitHub用の無料オンライン開発環境)でプロジェクトを開き、すぐにコーディングを開始します。
|
||||
|
||||
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/vbenjs/vue-vben-admin)
|
||||
|
||||
## ドキュメント
|
||||
|
||||
[ドキュメント](https://doc.vben.pro/)
|
||||
|
||||
## インストールと使用
|
||||
|
||||
- プロジェクトコードを取得
|
||||
|
||||
```bash
|
||||
git clone https://github.com/vbenjs/vue-vben-admin.git
|
||||
```
|
||||
|
||||
- 依存関係のインストール
|
||||
|
||||
```bash
|
||||
cd vue-vben-admin
|
||||
|
||||
corepack enable
|
||||
|
||||
pnpm install
|
||||
|
||||
```
|
||||
|
||||
- 実行
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
- ビルド
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## 変更ログ
|
||||
|
||||
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
|
||||
|
||||
## 貢献方法
|
||||
|
||||
ご参加をお待ちしております![Issueを提出](https://github.com/anncwb/vue-vben-admin/issues/new/choose)するか、Pull Requestを送信してください。
|
||||
|
||||
**Pull Request:**
|
||||
|
||||
1. コードをフォーク!
|
||||
2. 自分のブランチを作成: `git checkout -b feat/xxxx`
|
||||
3. 変更をコミット: `git commit -am 'feat(function): add xxxxx'`
|
||||
4. ブランチをプッシュ: `git push origin feat/xxxx`
|
||||
5. `pull request`を送信
|
||||
|
||||
## Git貢献提出規則
|
||||
|
||||
- 参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 規則 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
|
||||
|
||||
- `feat` 新機能の追加
|
||||
- `fix` 問題/バグの修正
|
||||
- `style` コードスタイルに関連し、実行結果に影響しない
|
||||
- `perf` 最適化/パフォーマンス向上
|
||||
- `refactor` リファクタリング
|
||||
- `revert` 変更の取り消し
|
||||
- `test` テスト関連
|
||||
- `docs` ドキュメント/注釈
|
||||
- `chore` 依存関係の更新/スキャフォールディング設定の変更など
|
||||
- `ci` 継続的インテグレーション
|
||||
- `types` 型定義ファイルの変更
|
||||
- `wip` 開発中
|
||||
|
||||
## ブラウザサポート
|
||||
|
||||
ローカル開発には`Chrome 80+`ブラウザを推奨します
|
||||
|
||||
モダンブラウザをサポートし、IEはサポートしません
|
||||
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||
| :-: | :-: | :-: | :-: | :-: |
|
||||
| サポートしない | 最新2バージョン | 最新2バージョン | 最新2バージョン | 最新2バージョン |
|
||||
|
||||
## メンテナー
|
||||
|
||||
[@Vben](https://github.com/anncwb)
|
||||
|
||||
## 寄付
|
||||
|
||||
このプロジェクトが役に立つと思われた場合、作者にコーヒーを一杯おごってサポートを示すことができます!
|
||||
|
||||
![donate](https://unpkg.com/@vbenjs/static-source@0.1.6/source/sponsor.png)
|
||||
|
||||
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
|
||||
|
||||
## 貢献者
|
||||
|
||||
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
|
||||
<img alt="Contributors"
|
||||
src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
|
||||
</a>
|
||||
|
||||
## Discord
|
||||
|
||||
- [Github Discussions](https://github.com/anncwb/vue-vben-admin/discussions)
|
||||
|
||||
## ライセンス
|
||||
|
||||
[MIT © Vben-2020](./LICENSE)
|
170
README.md
170
README.md
|
@ -1,92 +1,148 @@
|
|||
# 前端
|
||||
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.6/source/logo-v1.webp"> </a> <br> <br>
|
||||
|
||||
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
|
||||
|
||||
<h1>Vue Vben Admin</h1>
|
||||
</div>
|
||||
|
||||
## Getting started
|
||||
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vbenjs_vue-vben-admin&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin) ![codeql](https://github.com/vbenjs/vue-vben-admin/actions/workflows/codeql.yml/badge.svg) ![build](https://github.com/vbenjs/vue-vben-admin/actions/workflows/build.yml/badge.svg) ![ci](https://github.com/vbenjs/vue-vben-admin/actions/workflows/ci.yml/badge.svg) ![deploy](https://github.com/vbenjs/vue-vben-admin/actions/workflows/deploy.yml/badge.svg)
|
||||
|
||||
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
|
||||
**English** | [中文](./README.zh-CN.md) | [日本語](./README.ja-JP.md)
|
||||
|
||||
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
|
||||
## Introduction
|
||||
|
||||
## Add your files
|
||||
Vue Vben Admin is a free and open source middle and back-end template. Using the latest `vue3`, `vite`, `TypeScript` and other mainstream technology development, the out-of-the-box middle and back-end front-end solutions can also be used for learning reference.
|
||||
|
||||
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
|
||||
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
|
||||
## Upgrade Notice
|
||||
|
||||
```
|
||||
cd existing_repo
|
||||
git remote add origin https://git.openserver.cn:8089/XinJiang/TheProjectOfFour/kelamayireligongsi/plrl/vue.git
|
||||
git branch -M main
|
||||
git push -uf origin main
|
||||
This is the latest version, 5.0, and it is not compatible with previous versions. If you are starting a new project, it is recommended to use the latest version. If you wish to view the old version, please use the [v2 branch](https://github.com/vbenjs/vue-vben-admin/tree/v2).
|
||||
|
||||
## Feature
|
||||
|
||||
- **Latest Technology Stack**: Developed with cutting-edge front-end technologies like Vue 3 and Vite
|
||||
- **TypeScript**: A language for application-scale JavaScript
|
||||
- **Themes**: Multiple theme colors available with customizable options
|
||||
- **Internationalization**: Comprehensive built-in internationalization support
|
||||
- **Permissions**: Built-in solution for dynamic route-based permission generation
|
||||
|
||||
## Preview
|
||||
|
||||
- [Vben Admin](https://vben.pro/) - Full version Chinese site
|
||||
|
||||
Test Account: vben/123456
|
||||
|
||||
<p align="center">
|
||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview1.png">
|
||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview2.png">
|
||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
|
||||
</p>
|
||||
|
||||
### Use Gitpod
|
||||
|
||||
Open the project in Gitpod (free online dev environment for GitHub) and start coding immediately.
|
||||
|
||||
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/vbenjs/vue-vben-admin)
|
||||
|
||||
## Documentation
|
||||
|
||||
[Document](https://doc.vben.pro/)
|
||||
|
||||
## Install and use
|
||||
|
||||
- Get the project code
|
||||
|
||||
```bash
|
||||
git clone https://github.com/vbenjs/vue-vben-admin.git
|
||||
```
|
||||
|
||||
## Integrate with your tools
|
||||
- Installation dependencies
|
||||
|
||||
- [ ] [Set up project integrations](https://git.openserver.cn:8089/XinJiang/TheProjectOfFour/kelamayireligongsi/plrl/vue/-/settings/integrations)
|
||||
```bash
|
||||
cd vue-vben-admin
|
||||
|
||||
## Collaborate with your team
|
||||
corepack enable
|
||||
|
||||
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
|
||||
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
|
||||
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
|
||||
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
|
||||
- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
|
||||
pnpm install
|
||||
```
|
||||
|
||||
## Test and Deploy
|
||||
- run
|
||||
|
||||
Use the built-in continuous integration in GitLab.
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
|
||||
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
|
||||
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
|
||||
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
|
||||
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
|
||||
- build
|
||||
|
||||
***
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
|
||||
# Editing this README
|
||||
## Change Log
|
||||
|
||||
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
|
||||
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
|
||||
|
||||
## Suggestions for a good README
|
||||
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
|
||||
## How to contribute
|
||||
|
||||
## Name
|
||||
Choose a self-explaining name for your project.
|
||||
You are very welcome to join![Raise an issue](https://github.com/anncwb/vue-vben-admin/issues/new/choose) Or submit a Pull Request。
|
||||
|
||||
## Description
|
||||
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
|
||||
**Pull Request:**
|
||||
|
||||
## Badges
|
||||
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
|
||||
1. Fork code!
|
||||
2. Create your own branch: `git checkout -b feat/xxxx`
|
||||
3. Submit your changes: `git commit -am 'feat(function): add xxxxx'`
|
||||
4. Push your branch: `git push origin feat/xxxx`
|
||||
5. submit`pull request`
|
||||
|
||||
## Visuals
|
||||
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
|
||||
## Git Contribution submission specification
|
||||
|
||||
## Installation
|
||||
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
|
||||
- reference [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) specification ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
|
||||
|
||||
## Usage
|
||||
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
|
||||
- `feat` Add new features
|
||||
- `fix` Fix the problem/BUG
|
||||
- `style` The code style is related and does not affect the running result
|
||||
- `perf` Optimization/performance improvement
|
||||
- `refactor` Refactor
|
||||
- `revert` Undo edit
|
||||
- `test` Test related
|
||||
- `docs` Documentation/notes
|
||||
- `chore` Dependency update/scaffolding configuration modification etc.
|
||||
- `ci` Continuous integration
|
||||
- `types` Type definition file changes
|
||||
- `wip` In development
|
||||
|
||||
## Support
|
||||
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
|
||||
## Browser support
|
||||
|
||||
## Roadmap
|
||||
If you have ideas for releases in the future, it is a good idea to list them in the README.
|
||||
The `Chrome 80+` browser is recommended for local development
|
||||
|
||||
## Contributing
|
||||
State if you are open to contributions and what your requirements are for accepting them.
|
||||
Support modern browsers, not IE
|
||||
|
||||
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||
| :-: | :-: | :-: | :-: | :-: |
|
||||
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
|
||||
|
||||
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
|
||||
## Maintainer
|
||||
|
||||
## Authors and acknowledgment
|
||||
Show your appreciation to those who have contributed to the project.
|
||||
[@Vben](https://github.com/anncwb)
|
||||
|
||||
## Donate
|
||||
|
||||
If you think this project is helpful to you, you can help the author buy a cup of coffee to show your support!
|
||||
|
||||
![donate](https://unpkg.com/@vbenjs/static-source@0.1.6/source/sponsor.png)
|
||||
|
||||
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
|
||||
|
||||
## Contributor
|
||||
|
||||
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
|
||||
<img alt="Contributors"
|
||||
src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
|
||||
</a>
|
||||
|
||||
## Discord
|
||||
|
||||
- [Github Discussions](https://github.com/anncwb/vue-vben-admin/discussions)
|
||||
|
||||
## License
|
||||
For open source projects, say how it is licensed.
|
||||
|
||||
## Project status
|
||||
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
|
||||
[MIT © Vben-2020](./LICENSE)
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.6/source/logo-v1.webp"> </a> <br> <br>
|
||||
|
||||
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
|
||||
|
||||
<h1>Vue Vben Admin</h1>
|
||||
</div>
|
||||
|
||||
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vbenjs_vue-vben-admin&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin) ![codeql](https://github.com/vbenjs/vue-vben-admin/actions/workflows/codeql.yml/badge.svg) ![build](https://github.com/vbenjs/vue-vben-admin/actions/workflows/build.yml/badge.svg) ![ci](https://github.com/vbenjs/vue-vben-admin/actions/workflows/ci.yml/badge.svg) ![deploy](https://github.com/vbenjs/vue-vben-admin/actions/workflows/deploy.yml/badge.svg)
|
||||
|
||||
**中文** | [English](./README.md) | [日本語](./README.ja-JP.md)
|
||||
|
||||
## 简介
|
||||
|
||||
Vue Vben Admin 是 Vue Vben Admin 的升级版本。作为一个免费开源的中后台模板,它采用了最新的 Vue 3、Vite、TypeScript 等主流技术开发,开箱即用,可用于中后台前端开发,也适合学习参考。
|
||||
|
||||
## 升级提示
|
||||
|
||||
该版本为最新版本`5.0`, 与其他版本不兼容,如果你是新项目,建议使用最新版本。如果你想查看旧版本,请使用 [v2 分支](https://github.com/vbenjs/vue-vben-admin/tree/v2)
|
||||
|
||||
## 特性
|
||||
|
||||
- **最新技术栈**:使用 Vue3/vite 等前端前沿技术开发
|
||||
- **TypeScript**: 应用程序级 JavaScript 的语言
|
||||
- **主题**:提供多套主题色彩,可配置自定义主题
|
||||
- **国际化**:内置完善的国际化方案
|
||||
- **权限** 内置完善的动态路由权限生成方案
|
||||
|
||||
## 预览
|
||||
|
||||
- [Vben Admin](https://vben.pro/) - 完整版中文站点
|
||||
|
||||
测试账号: vben/123456
|
||||
|
||||
<p align="center">
|
||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview1.png">
|
||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview2.png">
|
||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
|
||||
</p>
|
||||
|
||||
### 使用 Gitpod
|
||||
|
||||
在 Gitpod(适用于 GitHub 的免费在线开发环境)中打开项目,并立即开始编码.
|
||||
|
||||
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/vbenjs/vue-vben-admin)
|
||||
|
||||
## 文档
|
||||
|
||||
[文档地址](https://doc.vben.pro/)
|
||||
|
||||
## 安装使用
|
||||
|
||||
- 获取项目代码
|
||||
|
||||
```bash
|
||||
git clone https://github.com/vbenjs/vue-vben-admin.git
|
||||
```
|
||||
|
||||
- 安装依赖
|
||||
|
||||
```bash
|
||||
cd vue-vben-admin
|
||||
|
||||
corepack enable
|
||||
|
||||
pnpm install
|
||||
```
|
||||
|
||||
- 运行
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
- 打包
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## 如何贡献
|
||||
|
||||
非常欢迎你的加入![提一个 Issue](https://github.com/anncwb/vue-vben-admin/issues/new/choose) 或者提交一个 Pull Request。
|
||||
|
||||
**Pull Request:**
|
||||
|
||||
1. Fork 代码!
|
||||
2. 创建自己的分支: `git checkout -b feature/xxxx`
|
||||
3. 提交你的修改: `git commit -am 'feat(function): add xxxxx'`
|
||||
4. 推送您的分支: `git push origin feature/xxxx`
|
||||
5. 提交`pull request`
|
||||
|
||||
## Git 贡献提交规范
|
||||
|
||||
- 参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 规范 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
|
||||
|
||||
- `feat` 增加新功能
|
||||
- `fix` 修复问题/BUG
|
||||
- `style` 代码风格相关无影响运行结果的
|
||||
- `perf` 优化/性能提升
|
||||
- `refactor` 重构
|
||||
- `revert` 撤销修改
|
||||
- `test` 测试相关
|
||||
- `docs` 文档/注释
|
||||
- `chore` 依赖更新/脚手架配置修改等
|
||||
- `ci` 持续集成
|
||||
- `types` 类型定义文件更改
|
||||
- `wip` 开发中
|
||||
|
||||
## 浏览器支持
|
||||
|
||||
本地开发推荐使用`Chrome 80+` 浏览器
|
||||
|
||||
支持现代浏览器, 不支持 IE
|
||||
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||
| :-: | :-: | :-: | :-: | :-: |
|
||||
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
|
||||
|
||||
## 维护者
|
||||
|
||||
[@Vben](https://github.com/anncwb)
|
||||
|
||||
## 捐赠
|
||||
|
||||
如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持!
|
||||
|
||||
![donate](https://unpkg.com/@vbenjs/static-source@0.1.6/source/sponsor.png)
|
||||
|
||||
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
|
||||
|
||||
## 更新日志
|
||||
|
||||
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
|
||||
|
||||
## Contributor
|
||||
|
||||
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
|
||||
<img alt="Contributors"
|
||||
src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
|
||||
</a>
|
||||
|
||||
## Discord
|
||||
|
||||
- [Github Discussions](https://github.com/anncwb/vue-vben-admin/discussions)
|
||||
|
||||
## License
|
||||
|
||||
[MIT © Vben-2020](./LICENSE)
|
139
alova.config.ts
139
alova.config.ts
|
@ -1,139 +0,0 @@
|
|||
|
||||
/**
|
||||
* Alova 请求插件配置文件
|
||||
* 作用:自动根据swagger生成对应的api调用函数
|
||||
*/
|
||||
export default {
|
||||
// api生成设置数组,每项代表一个自动生成的规则,包含生成的输入输出目录、规范文件地址等等
|
||||
generator: [
|
||||
// 服务器1
|
||||
{
|
||||
// input参数1:openapi的json文件url地址
|
||||
input: 'http://127.0.0.1:4523/export/openapi/2?version=3.0',
|
||||
|
||||
// input参数2:以当前项目为相对目录的本地地址
|
||||
// input: 'openapi/api.json'
|
||||
|
||||
// input参数3:没有直接指向openapi文件时,是一个文档地址,必须配合platform参数指定文档类型
|
||||
// input: 'http://192.168.5.123:8080'
|
||||
|
||||
// (可选)platform为支持openapi的平台,目前只支持swagger,默认为空
|
||||
// 当指定了此参数后,input字段只需要指定文档的地址而不需要指定到openapi文件
|
||||
platform: 'swagger',
|
||||
|
||||
// 接口文件和类型文件的输出路径,多个generator不能重复的地址,否则生成的代码会相互覆盖
|
||||
output: 'src/api',
|
||||
|
||||
// (可选)指定生成的响应数据的mediaType,以此数据类型来生成200状态码的响应ts格式,默认application/json
|
||||
responseMediaType: 'application/json',
|
||||
|
||||
// (可选)指定生成的请求体数据的bodyMediaType,以此数据类型来生成请求体的ts格式,默认application/json
|
||||
bodyMediaType: 'application/json',
|
||||
|
||||
// (可选)指定生成的api版本,默认为auto,会通过当前项目安装的alova版本判断当前项目的版本,如果生成不正确你也可以自定义指定版本
|
||||
version: 'auto',
|
||||
|
||||
/**
|
||||
* (可选)生成代码的类型,可选值为auto/ts/typescript/module/commonjs,默认为auto,会通过一定规则判断当前项目的类型,如果生成不正确你也可以自定义指定类型:
|
||||
* ts/typescript:意思相同,表示生成ts类型文件
|
||||
* module:生成esModule规范文件
|
||||
* commonjs:表示生成commonjs规范文件
|
||||
*/
|
||||
type: 'typescript',
|
||||
|
||||
/**
|
||||
* 全局导出的api名称,可通过此名称全局范围访问自动生成的api,默认为`Apis`,配置了多个generator时为必填,且不可以重复
|
||||
*/
|
||||
global: 'Apis',
|
||||
|
||||
/**
|
||||
* (可选)过滤或转换生成的api接口函数,返回一个新的apiDescriptor来生成api调用函数,未指定此函数时则不转换apiDescripor对象
|
||||
*/
|
||||
handleApi: (apiDescriptor, log) => {
|
||||
// 返回falsy值表示过滤此api
|
||||
// if (!apiDescriptor.path.startWith('/user')) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// apiDescriptor.parameter = apiDescriptor.parameter.filter(
|
||||
// param => param.in === 'header' && param.name === 'token'
|
||||
// );
|
||||
// delete apiDescriptor.requestBody.id;
|
||||
// apiDescriptor.url = '/app/rl' + apiDescriptor.url;
|
||||
|
||||
/**
|
||||
* 检查字符串数组中的任意一个字符串是否存在于目标字符串中。
|
||||
* @param target - 目标字符串
|
||||
* @param searchStrings - 要检查的字符串数组
|
||||
* @returns 是否至少有一个字符串存在于目标字符串中
|
||||
*/
|
||||
const anyStringExistsInTarget = (target, searchStrings) => {
|
||||
// 提前返回,如果搜索数组为空
|
||||
if (searchStrings.length === 0) return false;
|
||||
|
||||
// 预处理目标字符串,确保只有一次字符串操作
|
||||
const lowerCaseTarget = target.toLowerCase();
|
||||
|
||||
for (const searchString of searchStrings) {
|
||||
if (lowerCaseTarget.includes(searchString.toLowerCase())) {
|
||||
return true; // 只要有一个字符串匹配,立即返回 true
|
||||
}
|
||||
}
|
||||
return false; // 所有字符串都不匹配,返回 false
|
||||
}
|
||||
|
||||
// 接口包含某些参数的时候,需要生成
|
||||
if (anyStringExistsInTarget(apiDescriptor.url, [
|
||||
'/api/core', // 人员相关
|
||||
])) {
|
||||
apiDescriptor.url = '/uc' + apiDescriptor.url;
|
||||
apiDescriptor.tags = ['user']
|
||||
return apiDescriptor;
|
||||
}
|
||||
|
||||
apiDescriptor.url = '/app/rl' + apiDescriptor.url;
|
||||
if (anyStringExistsInTarget(apiDescriptor.url, [
|
||||
'/ccsq', // 出差申请
|
||||
'/meeting', '/addressor', // 会议
|
||||
'/zbgl', // 值班
|
||||
'/dish', '/orderfoods', '/recipe', // 订餐
|
||||
'/officeSuppliesApply', '/officeSuppliesList', '/warehousing', '/inorout', // 办公
|
||||
'/supervise', '/feedback' // 督察督办
|
||||
])) {
|
||||
apiDescriptor.tags = ['erp']
|
||||
return apiDescriptor;
|
||||
}
|
||||
|
||||
if (anyStringExistsInTarget(apiDescriptor.url, [
|
||||
'/contractrefertype', // 合同类别
|
||||
'/contractBaseInfo', //立项
|
||||
'/selectMerchantsBasicInfo', // 选商
|
||||
'/sbCtrBasePt',
|
||||
'/proproviderinfo',
|
||||
'/contractModelInfo'
|
||||
])) {
|
||||
apiDescriptor.tags = ['ht']
|
||||
return apiDescriptor;
|
||||
}
|
||||
|
||||
apiDescriptor.tags = ['common']
|
||||
|
||||
return apiDescriptor;
|
||||
}
|
||||
},
|
||||
],
|
||||
|
||||
// (可选)是否自动更新接口,默认开启,每5分钟检查一次,false时关闭
|
||||
autoUpdate: false
|
||||
|
||||
/* 也可以配置更详细的参数
|
||||
autoUpdate: {
|
||||
// 编辑器开启时更新,默认false
|
||||
launchEditor: true,
|
||||
// 自动更新间隔,单位毫秒
|
||||
interval: 5 * 60 * 1000
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# 应用标题
|
||||
VITE_APP_TITLE=ERP协同办公系统
|
||||
|
||||
# 应用命名空间,用于缓存、store等功能的前缀,确保隔离
|
||||
VITE_APP_NAMESPACE=erp-office
|
|
@ -0,0 +1,7 @@
|
|||
# public path
|
||||
VITE_BASE=/
|
||||
|
||||
# Basic interface address SPA
|
||||
VITE_GLOB_API_URL=/api
|
||||
|
||||
VITE_VISUALIZER=true
|
|
@ -0,0 +1,16 @@
|
|||
# 端口号
|
||||
VITE_PORT=5666
|
||||
|
||||
VITE_BASE=/
|
||||
|
||||
# 接口地址
|
||||
VITE_GLOB_API_URL=/api
|
||||
|
||||
# 是否开启 Nitro Mock服务,true 为开启,false 为关闭
|
||||
VITE_NITRO_MOCK=true
|
||||
|
||||
# 是否打开 devtools,true 为打开,false 为关闭
|
||||
VITE_DEVTOOLS=false
|
||||
|
||||
# 是否注入全局loading
|
||||
VITE_INJECT_APP_LOADING=true
|
|
@ -0,0 +1,16 @@
|
|||
VITE_BASE=/
|
||||
|
||||
# 接口地址
|
||||
VITE_GLOB_API_URL=/api
|
||||
|
||||
# 是否开启压缩,可以设置为 none, brotli, gzip
|
||||
VITE_COMPRESS=none
|
||||
|
||||
# 是否开启 PWA
|
||||
VITE_PWA=false
|
||||
|
||||
# vue-router 的模式
|
||||
VITE_ROUTER_HISTORY=history
|
||||
|
||||
# 是否注入全局loading
|
||||
VITE_INJECT_APP_LOADING=true
|
|
@ -0,0 +1,34 @@
|
|||
<!doctype html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="renderer" content="webkit" />
|
||||
<meta name="description" content="Erp Management System" />
|
||||
<meta name="keywords" content="erp" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
|
||||
/>
|
||||
<!-- 由 vite 注入 VITE_APP_TITLE 变量,在 .env 文件内配置 -->
|
||||
<title><%= VITE_APP_TITLE %></title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<script>
|
||||
// 生产环境下注入百度统计
|
||||
if (window._VBEN_ADMIN_PRO_APP_CONF_) {
|
||||
var _hmt = _hmt || [];
|
||||
(function () {
|
||||
var hm = document.createElement('script');
|
||||
hm.src =
|
||||
'https://hm.baidu.com/hm.js?b38e689f40558f20a9a686d7f6f33edf';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,77 @@
|
|||
{
|
||||
"name": "web-office",
|
||||
"version": "5.1.2",
|
||||
"homepage": "https://vben.pro",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||
"directory": "apps/web-antd"
|
||||
},
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "vben",
|
||||
"email": "ann.vben@gmail.com",
|
||||
"url": "https://github.com/anncwb"
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "pnpm vite build --mode production",
|
||||
"build:analyze": "pnpm vite build --mode analyze",
|
||||
"dev": "pnpm vite --mode development",
|
||||
"dev:prod": "pnpm vite --mode production",
|
||||
"preview": "vite preview",
|
||||
"typecheck": "vue-tsc --noEmit --skipLibCheck"
|
||||
},
|
||||
"imports": {
|
||||
"#/*": "./src/*"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fast-crud/fast-crud": "^1.21.2",
|
||||
"@fast-crud/fast-extends": "^1.21.2",
|
||||
"@fast-crud/ui-antdv4": "^1.21.2",
|
||||
"@fast-crud/ui-interface": "^1.21.2",
|
||||
"@vben-core/shadcn-ui": "workspace:*",
|
||||
"@vben/access": "workspace:*",
|
||||
"@vben/common-ui": "workspace:*",
|
||||
"@vben/constants": "workspace:*",
|
||||
"@vben/hooks": "workspace:*",
|
||||
"@vben/icons": "workspace:*",
|
||||
"@vben/layouts": "workspace:*",
|
||||
"@vben/locales": "workspace:*",
|
||||
"@vben/plugins": "workspace:*",
|
||||
"@vben/preferences": "workspace:*",
|
||||
"@vben/request": "workspace:*",
|
||||
"@vben/stores": "workspace:*",
|
||||
"@vben/styles": "workspace:*",
|
||||
"@vben/types": "workspace:*",
|
||||
"@vben/utils": "workspace:*",
|
||||
"@vueuse/core": "^11.0.3",
|
||||
"alova": "^3.0.14",
|
||||
"ant-design-vue": "^4.2.3",
|
||||
"big.js": "^6.2.1",
|
||||
"dayjs": "^1.11.13",
|
||||
"exceljs": "^4.4.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"pinia": "2.2.2",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"sortablejs": "^1.15.2",
|
||||
"tyme4ts": "^1.1.2",
|
||||
"vue": "^3.4.38",
|
||||
"vue-router": "^4.4.3",
|
||||
"vxe-pc-ui": "^4.1.12",
|
||||
"vxe-table": "^4.7.74",
|
||||
"vxe-table-plugin-antd": "^4.0.8",
|
||||
"vxe-table-plugin-export-xlsx": "^4.0.2",
|
||||
"xe-utils": "^3.5.30"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/big.js": "^6.2.2",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"sass": "^1.77.8",
|
||||
"typescript": "^5.5.4",
|
||||
"unplugin-auto-import": "^0.18.2",
|
||||
"unplugin-vue-components": "^0.27.4",
|
||||
"vite-plugin-lazy-import": "^1.0.7"
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export { default } from '@vben/tailwind-config/postcss';
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
@ -0,0 +1,3 @@
|
|||
pnpm i @fast-crud/fast-crud
|
||||
pnpm i @fast-crud/fast-extends
|
||||
pnpm i @fast-crud/ui-interface
|
|
@ -0,0 +1,73 @@
|
|||
import { baseRequestClient, requestClient } from '#/api/request/index';
|
||||
|
||||
|
||||
export namespace AuthApi {
|
||||
/** 登录接口参数 */
|
||||
export interface LoginParams {
|
||||
password: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
/** 登录接口返回值 */
|
||||
export interface LoginResult {
|
||||
accessToken: string;
|
||||
desc: string;
|
||||
realName: string;
|
||||
userId: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface RefreshTokenResult {
|
||||
data: string;
|
||||
status: number;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
export async function loginApi(data: AuthApi.LoginParams) {
|
||||
return requestClient.post<AuthApi.LoginResult>(
|
||||
'/uc/uaa/validateAccount',
|
||||
data,
|
||||
{
|
||||
transformResponse: (res) => {
|
||||
res = JSON.parse(res);
|
||||
console.log(res);
|
||||
const info = res.data;
|
||||
if (info) {
|
||||
info.accessToken = info.access_token;
|
||||
info.realName = info.display_name;
|
||||
return info
|
||||
}
|
||||
return res;
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新accessToken
|
||||
*/
|
||||
export async function refreshTokenApi() {
|
||||
return baseRequestClient.post<AuthApi.RefreshTokenResult>('/auth/refresh', {
|
||||
withCredentials: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
export async function logoutApi() {
|
||||
return baseRequestClient.post('/uc/uaa/logout', {
|
||||
withCredentials: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户权限码
|
||||
*/
|
||||
export async function getAccessCodesApi() {
|
||||
return requestClient.get<string[]>('/auth/codes');
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export * from './auth';
|
||||
export * from './menu';
|
||||
export * from './user';
|
|
@ -0,0 +1,10 @@
|
|||
import type { RouteRecordStringComponent } from '@vben/types';
|
||||
|
||||
import { requestClient } from '#/api/request/index';
|
||||
|
||||
/**
|
||||
* 获取用户所有菜单
|
||||
*/
|
||||
export async function getAllMenusApi() {
|
||||
return requestClient.get<RouteRecordStringComponent[]>('/menu/all');
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import type { UserInfo } from '@vben/types';
|
||||
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
import { requestClient } from '#/api/request/index';
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
export async function getUserInfoApi() {
|
||||
const accessStore = useAccessStore();
|
||||
return requestClient.post<UserInfo>('/uc/sys/user/checkToken', {
|
||||
token: accessStore.accessToken,
|
||||
});
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
export interface QueryOptions {
|
||||
params?: AnyObject;
|
||||
pathParams?: AnyObject;
|
||||
config?: AnyObject;
|
||||
}
|
||||
|
||||
export interface BodyOptions {
|
||||
params?: AnyObject;
|
||||
data?: AnyObject;
|
||||
pathParams?: AnyObject;
|
||||
config?: AnyObject;
|
||||
}
|
||||
|
||||
export interface RequestOptions {
|
||||
url: string;
|
||||
data?: QueryOptions;
|
||||
}
|
||||
|
||||
export interface MutationOptions {
|
||||
url: string;
|
||||
data?: BodyOptions;
|
||||
}
|
|
@ -0,0 +1,509 @@
|
|||
import { http } from "./request/index"
|
||||
import type { QueryOptions, BodyOptions } from "./global.d"
|
||||
|
||||
export default {
|
||||
|
||||
meeting: {
|
||||
/** 协同办公/会议管理 分页查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/meeting/page", data),
|
||||
/** 协同办公/会议管理 删除会议 */
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/meeting/deletes", data),
|
||||
/** 协同办公/会议管理 会议保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/meeting/save", data),
|
||||
/** 协同办公/会议管理 查看会议台账 */
|
||||
get_list: (data?: QueryOptions) => http.get("/app/meeting/list", data),
|
||||
list: {
|
||||
/** 协同办公/会议管理 会议台账导出 */
|
||||
get_export: (data?: QueryOptions) => http.get("/app/meeting/list/export", data),
|
||||
},
|
||||
},
|
||||
tysq: {
|
||||
zzjg: {
|
||||
yhjbda: {
|
||||
YhjbdaController: {
|
||||
/** 统一授权 未命名接口 */
|
||||
get_yhjbdaGrid: (data?: QueryOptions) => http.get("/app/tysq/zzjg/yhjbda/YhjbdaController/yhjbdaGrid", data),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
dictType: {
|
||||
/** 协同办公/字典表 字典类型查询 */
|
||||
get_list: (data?: QueryOptions) => http.get("/app/dictType/list", data),
|
||||
/** 协同办公/字典表 字典类型保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/dictType/save", data),
|
||||
/** 协同办公/字典表 字典类型删除 */
|
||||
post_delete: (data?: BodyOptions) => http.post("/app/dictType/deletes", data),
|
||||
},
|
||||
uaa: {
|
||||
/** 用户中心 用户登陆 Copy */
|
||||
post_validateAccount: (data?: BodyOptions) => http.post("/uc/uaa/validateAccount", data),
|
||||
},
|
||||
api: {
|
||||
core: {
|
||||
orgemplbc: {
|
||||
employee: {
|
||||
/** 用户中心 获取用户信息(分页) */
|
||||
post_paging: (data?: BodyOptions) => http.post("/uc/api/core/orgemplbc/employee/paging", data),
|
||||
},
|
||||
organization: {
|
||||
RL: {
|
||||
/** 用户中心 根据组织机构id获取员工信息 */
|
||||
get_employee: (data?: QueryOptions) => http.get("/uc/api/core/orgemplbc/organization/RL/employee", data),
|
||||
},
|
||||
/** 用户中心 获取组织结构信息 */
|
||||
post_paging: (data?: BodyOptions) => http.post("/uc/api/core/orgemplbc/organization/paging", data),
|
||||
},
|
||||
/** 用户中心 根据组织机构id和用户信息查询 */
|
||||
post_employee: (data?: BodyOptions) => http.post("/uc/api/core/orgemplbc/employee", data),
|
||||
},
|
||||
},
|
||||
},
|
||||
sys: {
|
||||
user: {
|
||||
/** 用户中心 根据token获取用户信息 */
|
||||
post_checkToken: (data?: BodyOptions) => http.post("/uc/sys/user/checkToken", data),
|
||||
functiontree: {
|
||||
/** 用户中心 获取菜单接口 */
|
||||
get_XTBGXT: (data?: QueryOptions) => http.get("/uc/sys/user/functiontree/XTBGXT", data),
|
||||
/** 统一授权 未命名接口 */
|
||||
get_PLRL: (data?: QueryOptions) => http.get("/uc/sys/user/functiontree/PLRL", data),
|
||||
},
|
||||
},
|
||||
},
|
||||
zbgl: {
|
||||
/** 协同办公/值班管理 值班查询 */
|
||||
get_queryZbInfo: (data?: QueryOptions) => http.get("/app/zbgl/queryZbInfo", data),
|
||||
/** 协同办公/值班管理 保存值班信息 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/zbgl/save", data),
|
||||
/** 协同办公/值班管理 删除值班信息 */
|
||||
get_deletes: (data?: QueryOptions) => http.get("/app/zbgl/deletes", data),
|
||||
/** 协同办公/值班管理 导入值班人员信息 */
|
||||
post_importZbry: (data?: BodyOptions) => http.post("/app/zbgl/importZbry", data),
|
||||
/** 协同办公/值班管理 门户值班信息查询 */
|
||||
get_getDutyInfo: (data?: QueryOptions) => http.get("/app/zbgl/getDutyInfo", data),
|
||||
/** 协同办公/值班管理 导出 */
|
||||
post_export: (data?: BodyOptions) => http.post("/app/zbgl/export", data),
|
||||
},
|
||||
dictData: {
|
||||
/** 协同办公/字典表 字典数据保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/dictData/save", data),
|
||||
/** 合同系统/项目管理 保存 */
|
||||
get_save: (data?: QueryOptions) => http.get("/app/dictData/save", data),
|
||||
/** 合同系统/项目名称管理 查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/dictData/page", data),
|
||||
/** 协同办公/字典表 字典数据删除 */
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/dictData/deletes", data),
|
||||
/** 合同系统/项目管理 删除 */
|
||||
get_deletes: (data?: QueryOptions) => http.get("/app/dictData/deletes", data),
|
||||
},
|
||||
user: {
|
||||
/** 统一授权 获取用户列表 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/user/page", data),
|
||||
},
|
||||
dish: {
|
||||
/** 协同办公/订餐管理/菜谱管理 菜谱查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/dish/page", data),
|
||||
/** 协同办公/订餐管理/菜谱管理 菜谱保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/dish/save", data),
|
||||
/** 协同办公/订餐管理/食谱管理 菜谱删除 */
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/dish/deletes", data),
|
||||
},
|
||||
recipe: {
|
||||
/** 协同办公/订餐管理/食谱管理 食谱查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/recipe/page", data),
|
||||
/** 协同办公/订餐管理/食谱管理 食谱保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/recipe/save", data),
|
||||
/** 协同办公/订餐管理/食谱管理 食谱导出 */
|
||||
get_export: (data?: QueryOptions) => http.get("/app/recipe/export", data),
|
||||
/** 协同办公/订餐管理/食谱管理 批量保存 */
|
||||
post_saveBatch: (data?: BodyOptions) => http.post("/app/recipe/saveBatch", data),
|
||||
/** 协同办公/订餐管理/食谱管理 食谱编辑 */
|
||||
post_edit: (data?: BodyOptions) => http.post("/app/recipe/edit", data),
|
||||
},
|
||||
ccsq: {
|
||||
/** 协同办公/出差申请 出差申请查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/ccsq/page", data),
|
||||
/** 协同办公/出差申请 申请单保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/ccsq/save", data),
|
||||
/** 协同办公/出差申请 申请单删除 */
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/ccsq/deletes", data),
|
||||
/** 协同办公/出差申请 出差送审、审核 */
|
||||
post_audit: (data?: BodyOptions) => http.post("/app/ccsq/audit", data),
|
||||
/** 协同办公/出差申请 退回 */
|
||||
post_turnTask: (data?: BodyOptions) => http.post("/app/ccsq/turnTask", data),
|
||||
/** 协同办公/出差申请 启动流程 */
|
||||
post_startWorkFlow: (data?: BodyOptions) => http.post("/app/ccsq/startWorkFlow", data),
|
||||
/** 协同办公/出差申请 送审 */
|
||||
post_submit: (data?: BodyOptions) => http.post("/app/ccsq/submit", data),
|
||||
/** 协同办公/出差申请 待办 */
|
||||
get_toDoPage: (data?: QueryOptions) => http.get("/app/ccsq/toDoPage", data),
|
||||
/** 协同办公/出差申请 已办 */
|
||||
get_donePage: (data?: QueryOptions) => http.get("/app/ccsq/donePage", data),
|
||||
/** 协同办公/出差申请 获取可退回节点信息 */
|
||||
get_getBackNode: (data?: QueryOptions) => http.get("/app/ccsq/getBackNode", data),
|
||||
|
||||
},
|
||||
orderfood: {
|
||||
/** 协同办公/订餐管理/订餐 订餐加载接口 */
|
||||
get_getOne: (data?: QueryOptions) => http.get("/app/orderfood/getOne", data),
|
||||
/** 协同办公/订餐管理/订餐 订餐保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/orderfood/save", data),
|
||||
/** 协同办公/订餐管理/订餐 取消订餐 */
|
||||
post_cancel: (data?: BodyOptions) => http.post("/app/orderfood/cancel", data),
|
||||
/** 协同办公/订餐管理/订餐 协助取消他人订餐 */
|
||||
post_assistCancel: (data?: BodyOptions) => http.post("/app/orderfood/assistCancel", data),
|
||||
},
|
||||
orderfoods: {
|
||||
/** 协同办公/订餐管理/汇总 部门结算汇总 */
|
||||
get_departmentSummary: (data?: QueryOptions) => http.get("/app/orderfoods/departmentSummary", data),
|
||||
/** 协同办公/订餐管理/汇总 订餐汇总 */
|
||||
get_infoList: (data?: QueryOptions) => http.get("/app/orderfoods/infoList", data),
|
||||
/** 协同办公/订餐管理/汇总 个人结算汇总 */
|
||||
get_personalSummary: (data?: QueryOptions) => http.get("/app/orderfoods/personalSummary", data),
|
||||
infoList: {
|
||||
/** 协同办公/订餐管理/汇总 订餐汇总导出 */
|
||||
get_export: (data?: QueryOptions) => http.get("/app/orderfoods/infoList/export", data),
|
||||
},
|
||||
personalSummary: {
|
||||
/** 协同办公/订餐管理/汇总 个人结算汇总导出 */
|
||||
get_export: (data?: QueryOptions) => http.get("/app/orderfoods/personalSummary/export", data),
|
||||
},
|
||||
departmentSummary: {
|
||||
/** 协同办公/订餐管理/汇总 部门结算汇总导出 */
|
||||
get_export: (data?: QueryOptions) => http.get("/app/orderfoods/departmentSummary/export", data),
|
||||
},
|
||||
/** 协同办公/订餐管理/汇总 结算单 */
|
||||
get_finalStatement: (data?: QueryOptions) => http.get("/app/orderfoods/finalStatement", data),
|
||||
finalStatement: {
|
||||
/** 协同办公/订餐管理/汇总 结算表导出 */
|
||||
get_export: (data?: QueryOptions) => http.get("/app/orderfoods/finalStatement/export", data),
|
||||
},
|
||||
/** 协同办公/订餐管理/汇总 结算操作 */
|
||||
post_balance: (data?: BodyOptions) => http.post("/app/orderfoods/balance", data),
|
||||
},
|
||||
officeSuppliesApply: {
|
||||
/** 协同办公/办公用品/办公用品申请 申请页面查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/officeSuppliesApply/page", data),
|
||||
/** 协同办公/办公用品/办公用品申请 申请保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/officeSuppliesApply/save", data),
|
||||
/** 协同办公/办公用品/办公用品申请 批量审核 */
|
||||
post_audit: (data?: BodyOptions) => http.post("/app/officeSuppliesApply/audit", data),
|
||||
/** 协同办公/办公用品/办公用品申请 批量申请 */
|
||||
post_saveBatch: (data?: BodyOptions) => http.post("/app/officeSuppliesApply/saveBatch", data),
|
||||
/** 协同办公/办公用品/办公用品申请 撤销申请 */
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/officeSuppliesApply/deletes", data),
|
||||
},
|
||||
warehousing: {
|
||||
/** 协同办公/办公用品/入库/出库 入库查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/warehousing/page", data),
|
||||
},
|
||||
inOrOut: {
|
||||
/** 协同办公/办公用品/入库/出库 入库/保存 */
|
||||
post_saveBatch: (data?: BodyOptions) => http.post("/app/inOrOut/saveBatch", data),
|
||||
},
|
||||
supervise: {
|
||||
/** 协同办公/督查督办/立项发起 立项分页查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/supervise/page", data),
|
||||
/** 协同办公/督查督办/立项发起 立项保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/supervise/save", data),
|
||||
/** 协同办公/督查督办/立项发起 立项删除 */
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/supervise/deletes", data),
|
||||
/** 协同办公/督查督办/立项发起 立项提交 */
|
||||
post_audit: (data?: BodyOptions) => http.post("/app/supervise/audit", data),
|
||||
/** 协同办公/督查督办/执行反馈 执行反馈提交 */
|
||||
post_auditFankui: (data?: BodyOptions) => http.post("/app/supervise/auditFankui", data),
|
||||
/** 协同办公/督查督办/报表汇总 统计 */
|
||||
get_huizong: (data?: QueryOptions) => http.get("/app/supervise/huizong", data),
|
||||
/** 协同办公/督查督办/立项发起 更新状态 */
|
||||
post_updateStatus: (data?: BodyOptions) => http.post("/app/supervise/updateStatus", data),
|
||||
},
|
||||
feedback: {
|
||||
/** 协同办公/督查督办/执行反馈 执行反馈待办查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/feedback/page", data),
|
||||
/** 协同办公/督查督办/执行反馈 执行反馈保存,实际修改操作,保存反馈时间,反馈内容,进度 */
|
||||
post_saveUpdate: (data?: BodyOptions) => http.post("/app/feedback/saveUpdate", data),
|
||||
/** 协同办公/督查督办/执行反馈 查询负责部门列表,返回所有的反馈信息 */
|
||||
get_getDepartment: (data?: QueryOptions) => http.get("/app/feedback/getDepartment", data),
|
||||
/** 协同办公/督查督办/执行反馈 分发立项任务 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/feedback/save", data),
|
||||
/** 协同办公/督查督办/执行反馈 执行反馈已办查询 */
|
||||
get_pageDone: (data?: QueryOptions) => http.get("/app/feedback/pageDone", data),
|
||||
},
|
||||
file: {
|
||||
/** 协同办公/文件上传/下载 多文件上传 */
|
||||
post_uploads: (data?: BodyOptions) => http.post("/app/file/uploads", data),
|
||||
},
|
||||
addressor: {
|
||||
/** 协同办公/会议管理/发言人 发言人查询 */
|
||||
get_list: (data?: QueryOptions) => http.get("/app/addressor/list", data),
|
||||
/** 协同办公/会议管理/发言人 发言人批量保存 */
|
||||
post_saveBatch: (data?: BodyOptions) => http.post("/app/addressor/saveBatch", data),
|
||||
/** 协同办公/会议管理/发言人 发言人保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/addressor/save", data),
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/addressor/deletes", data),
|
||||
},
|
||||
officeSuppliesList: {
|
||||
/** 协同办公/办公用品/办公用品清单 分页查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/officeSuppliesList/page", data),
|
||||
/** 协同办公/办公用品/办公用品清单 批量保存 */
|
||||
post_saveBatch: (data?: BodyOptions) => http.post("/app/officeSuppliesList/saveBatch", data),
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/officeSuppliesList/deletes", data),
|
||||
},
|
||||
officeSuppliesApplySum: {
|
||||
/** 协同办公/办公用品 采购汇总 */
|
||||
get_list: (data?: QueryOptions) => http.get("/app/officeSuppliesApplySum/list", data),
|
||||
},
|
||||
autoOrderfoodPeoples: {
|
||||
/** 协同办公/订餐管理/自动订餐人员管理 分页查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/autoOrderfoodPeoples/page", data),
|
||||
/** 协同办公/订餐管理/自动订餐人员管理 批量保存 */
|
||||
post_saveBatch: (data?: BodyOptions) => http.post("/app/autoOrderfoodPeoples/saveBatch", data),
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/autoOrderfoodPeoples/deletes", data),
|
||||
},
|
||||
usercenter: {
|
||||
/** 协同办公 获取菜单 */
|
||||
get_menus: (data?: QueryOptions) => http.get("/app/usercenter/menus", data),
|
||||
},
|
||||
workflow: {
|
||||
/** 协同办公/工作流 待办 */
|
||||
post_queryMyTodoTask: (data?: BodyOptions) => http.post("/app/workflow/queryMyTodoTask", data),
|
||||
/** 协同办公/工作流 已办 */
|
||||
post_getHistoricTaskByUserID: (data?: BodyOptions) => http.post("/app/workflow/getHistoricTaskByUserID", data),
|
||||
},
|
||||
personTask: {
|
||||
/** 合同系统/签订 待办查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/personTask/page", data),
|
||||
/** 合同系统/签订 已办查询 */
|
||||
get_pagePersonTaskOver: (data?: QueryOptions) => http.get("/app/personTask/pagePersonTaskOver", data),
|
||||
/** 合同系统/履行/履行查询 分页合同履行审批查询 */
|
||||
get_pagePerformanceAudit: (data?: QueryOptions) => http.get("/app/personTask/pagePerformanceAudit", data),
|
||||
/** 合同系统/履行/履行提示/申请归档 归档保存 */
|
||||
post_applicationFiling: (data?: BodyOptions) => http.post("/app/personTask/applicationFiling", data),
|
||||
},
|
||||
sbCtrBasePt: {
|
||||
/** 合同系统/申报 合同申报数据查询 */
|
||||
get_QuerySbCtrBase: (data?: QueryOptions) => http.get("/app/sbCtrBasePt/QuerySbCtrBase", data),
|
||||
/** 合同系统/申报 合同申报基本信息加载 */
|
||||
post_page: (data?: BodyOptions) => http.post("/app/sbCtrBasePt/page", data),
|
||||
/** 合同系统/申报 合同申报基本信息保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/sbCtrBasePt/save", data),
|
||||
/** 合同系统/申报 合同申报基本信息删除 */
|
||||
get_deletes: (data?: QueryOptions) => http.get("/app/sbCtrBasePt/deletes", data),
|
||||
/** 合同系统/申报 获取资金渠道 */
|
||||
get_getFundingSource: (data?: QueryOptions) => http.get("/app/sbCtrBasePt/getFundingSource", data),
|
||||
},
|
||||
contractBaseInfo: {
|
||||
/** 合同系统/立项 合同立项保存 */
|
||||
post_apply: (data?: BodyOptions) => http.post("/app/contractBaseInfo/apply", data),
|
||||
/** 合同系统/立项 合同立项查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/contractBaseInfo/page", data),
|
||||
/** 合同系统/立项 删除 */
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/contractBaseInfo/deletes", data),
|
||||
/** 合同系统/立项 单条查询 */
|
||||
get_getOne: (data?: QueryOptions) => http.get("/app/contractBaseInfo/getOne", data),
|
||||
/** 合同系统/立项 提交 */
|
||||
post_submit: (data?: BodyOptions) => http.post("/app/contractBaseInfo/submit", data),
|
||||
/** 合同系统/立项 退回 */
|
||||
post_rollback: (data?: BodyOptions) => http.post("/app/contractBaseInfo/rollback", data),
|
||||
},
|
||||
proProviderInfo: {
|
||||
/** 合同系统/相对人管理 合同相对人查询 */
|
||||
get_Query: (data?: QueryOptions) => http.get("/app/proProviderInfo/Query", data),
|
||||
/** 合同系统/相对人管理 获取币种 */
|
||||
get_getBz: (data?: QueryOptions) => http.get("/app/proProviderInfo/getBz", data),
|
||||
/** 合同系统/相对人管理 保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/proProviderInfo/save", data),
|
||||
/** 合同系统/相对人管理 删除 */
|
||||
get_deletes: (data?: QueryOptions) => http.get("/app/proProviderInfo/deletes", data),
|
||||
/** 合同系统/相对人管理 加载 */
|
||||
post_page: (data?: BodyOptions) => http.post("/app/proProviderInfo/page", data),
|
||||
},
|
||||
contractModelInfo: {
|
||||
/** 合同系统/模板管理 保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/contractModelInfo/save", data),
|
||||
/** 合同系统/模板管理 删除 */
|
||||
get_deletes: (data?: QueryOptions) => http.get("/app/contractModelInfo/deletes", data),
|
||||
/** 合同系统/模板管理 加载 */
|
||||
post_page: (data?: BodyOptions) => http.post("/app/contractModelInfo/page", data),
|
||||
},
|
||||
contractReferType: {
|
||||
/** 合同系统/合同类型参照 查询 */
|
||||
get_list: (data?: QueryOptions) => http.get("/app/contractReferType/list", data),
|
||||
/** 合同系统/合同类型参照 保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/contractReferType/save", data),
|
||||
/** 合同系统/合同类型参照 删除 */
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/contractReferType/deletes", data),
|
||||
},
|
||||
attachment: {
|
||||
/** 文件上传/下载(新) 附件加载 */
|
||||
get_list: (data?: QueryOptions) => http.get("/app/attachment/list", data),
|
||||
/** 文件上传/下载(新) 文件下载 */
|
||||
get_download: (data?: QueryOptions) => http.get("/app/attachment/download/{fileUuid}", data),
|
||||
/** 文件上传/下载(新) 多文件上传 */
|
||||
post_uploads: (data?: BodyOptions) => http.post("/app/attachment/uploads", data),
|
||||
},
|
||||
contractPayment: {
|
||||
/** 合同系统/履行/履行提示/合同付款 获取合同付款信息 */
|
||||
get_queryPaymentInfo: (data?: QueryOptions) => http.get("/app/contractPayment/queryPaymentInfo", data),
|
||||
/** 合同系统/归档/合同归档 历史记录 */
|
||||
get_historyPaymentInfo: (data?: QueryOptions) => http.get("/app/contractPayment/historyPaymentInfo", data),
|
||||
/** 合同系统/履行/履行提示/合同付款 保存付款申请 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/contractPayment/save", data),
|
||||
},
|
||||
selectMerchantsBasicInfo: {
|
||||
/** 合同系统/选商 分页查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/selectMerchantsBasicInfo/page", data),
|
||||
/** 合同系统/选商 选商信息查询(单条) */
|
||||
get_getOne: (data?: QueryOptions) => http.get("/app/selectMerchantsBasicInfo/getOne", data),
|
||||
/** 合同系统/选商 选商信息保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/selectMerchantsBasicInfo/save", data),
|
||||
/** 合同系统/选商 合同选商保存操作(多个对象) */
|
||||
post_saveMultiEntity: (data?: BodyOptions) => http.post("/app/selectMerchantsBasicInfo/saveMultiEntity", data),
|
||||
/** 合同系统/选商 提交 */
|
||||
post_submit: (data?: BodyOptions) => http.post("/app/selectMerchantsBasicInfo/submit", data),
|
||||
/** 合同系统/选商 退回 */
|
||||
post_rollback: (data?: BodyOptions) => http.post("/app/selectMerchantsBasicInfo/rollback", data),
|
||||
},
|
||||
lvxChange: {
|
||||
/** 合同系统/履行/履行提示/合同变更 保存合同变更申请 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/lvxChange/save", data),
|
||||
/** 合同系统/履行/履行提示/合同变更 获取合同变更信息 */
|
||||
get_getContractChangeInfo: (data?: QueryOptions) => http.get("/app/lvxChange/getContractChangeInfo", data),
|
||||
},
|
||||
contractRelieve: {
|
||||
/** 合同系统/履行/履行提示/合同终止(解除) 获取合同终止(解除)信息 */
|
||||
get_getContractRelieveInfo: (data?: QueryOptions) => http.get("/app/contractRelieve/getContractRelieveInfo", data),
|
||||
/** 合同系统/履行/履行提示/合同终止(解除) 保存合同终止信息 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/contractRelieve/save", data),
|
||||
},
|
||||
contractBreach: {
|
||||
/** 合同系统/履行/履行提示/合同违约情况 保存合同违约信息 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/contractBreach/save", data),
|
||||
/** 合同系统/履行/履行提示/合同违约情况 获取合同违约信息 */
|
||||
get_getContractBreachInfo: (data?: QueryOptions) => http.get("/app/contractBreach/getContractBreachInfo", data),
|
||||
},
|
||||
lvxResult: {
|
||||
/** 合同系统/履行/履行结果 履行结果保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/lvxResult/save", data),
|
||||
},
|
||||
contractFiling: {
|
||||
/** 合同系统/履行/履行提示/临时归档 保存临时归档信息 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/contractFiling/save", data),
|
||||
},
|
||||
biddingExpert: {
|
||||
/** 合同系统/选商/选商招标专家 招标专家查询 */
|
||||
get_list: (data?: QueryOptions) => http.get("/app/biddingExpert/list", data),
|
||||
/** 合同系统/选商/选商招标专家 选商招标专家保存 */
|
||||
post_saveBatch: (data?: BodyOptions) => http.post("/app/biddingExpert/saveBatch", data),
|
||||
/** 合同系统/选商/选商招标专家 选商招标专家删除 */
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/biddingExpert/deletes", data),
|
||||
},
|
||||
contractFilingFormal: {
|
||||
/** 合同系统/归档/合同归档 分页查询归档信息 */
|
||||
get_queryContractFiling: (data?: QueryOptions) => http.get("/app/contractFilingFormal/queryContractFiling", data),
|
||||
/** 合同系统/归档/合同归档 获取合同招标选商申请信息 */
|
||||
get_getContractSupplier: (data?: QueryOptions) => http.get("/app/contractFilingFormal/getContractSupplier", data),
|
||||
/** 合同系统/归档/合同归档 保存合同归档 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/contractFilingFormal/save", data),
|
||||
/** 合同系统/归档/合同回档 分页查询 */
|
||||
get_pageArchivedContract: (data?: QueryOptions) => http.get("/app/contractFilingFormal/pageArchivedContract", data),
|
||||
/** 合同系统/归档/合同回档 回档 */
|
||||
post_saveFilingBack: (data?: BodyOptions) => http.post("/app/contractFilingFormal/saveFilingBack", data),
|
||||
},
|
||||
lvxProduct: {
|
||||
/** 合同系统/履行/履行提示/产品或服务 获取合同产品信息 */
|
||||
get_getContractProductInfo: (data?: QueryOptions) => http.get("/app/lvxProduct/getContractProductInfo", data),
|
||||
/** 合同系统/履行/履行提示/产品或服务 累计收款金额 */
|
||||
get_getSumFromProduct: (data?: QueryOptions) => http.get("/app/lvxProduct/getSumFromProduct", data),
|
||||
/** 合同系统/履行/履行提示/产品或服务 历史记录 */
|
||||
get_getListFromHistoryRecord: (data?: QueryOptions) => http.get("/app/lvxProduct/getListFromHistoryRecord", data),
|
||||
/** 合同系统/履行/履行提示/产品或服务 保存合同产品服务 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/lvxProduct/save", data),
|
||||
},
|
||||
qdSign: {
|
||||
/** 合同系统/签订 签订查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/qdSign/page", data),
|
||||
/** 合同系统/签订 获取合同签订信息 */
|
||||
get_getContractSignInfo: (data?: QueryOptions) => http.get("/app/qdSign/getContractSignInfo", data),
|
||||
/** 合同系统/签订 打印签订审批表 */
|
||||
get_createUserListWord: (data?: QueryOptions) => http.get("/app/qdSign/createUserListWord", data),
|
||||
/** 合同系统/签订 打印文本 */
|
||||
get_textPrint: (data?: QueryOptions) => http.get("/app/qdSign/textPrint", data),
|
||||
/** 合同系统/签订 保存送审 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/qdSign/save", data),
|
||||
/** 合同系统/签订 废除 */
|
||||
post_abolish: (data?: BodyOptions) => http.post("/app/qdSign/abolish", data),
|
||||
},
|
||||
flowCenter: {
|
||||
/** 流程中心 启动流程 */
|
||||
post_start: (data?: BodyOptions) => http.post("/app/flowCenter/start", data),
|
||||
/** 流程中心 审核通过 */
|
||||
post_agree: (data?: BodyOptions) => http.post("/app/flowCenter/agree", data),
|
||||
/** 流程中心 审核退回 */
|
||||
post_rollback: (data?: BodyOptions) => http.post("/app/flowCenter/rollback", data),
|
||||
/** 流程中心 获取待办 */
|
||||
post_getTodoList: (data?: BodyOptions) => http.post("/app/flowCenter/getTodoList", data),
|
||||
/** 流程中心 获取已办 */
|
||||
post_doneList: (data?: BodyOptions) => http.post("/app/flowCenter/doneList", data),
|
||||
/** 流程中心 审核撤回 */
|
||||
get_revoke: (data?: QueryOptions) => http.get("/app/flowCenter/revoke", data),
|
||||
/** 流程中心 审核记录 */
|
||||
get_history: (data?: QueryOptions) => http.get("/app/flowCenter/history", data),
|
||||
/** 流程中心 查看流程图 */
|
||||
get_getFlowImg: (data?: QueryOptions) => http.get("/app/flowCenter/getFlowImg", data),
|
||||
/** 流程中心 获取可退回节点 */
|
||||
get_getReturnNode: (data?: QueryOptions) => http.get("/app/flowCenter/getReturnNode", data),
|
||||
/** 流程中心 获取流程节点人员配置信息 */
|
||||
get_getNextNodeUserConfig: (data?: QueryOptions) => http.get("/app/flowCenter/getNextNodeUserConfig", data),
|
||||
/** 流程中心 获取待办数量 */
|
||||
get_getTodoListSize: (data?: QueryOptions) => http.get("/app/flowCenter/getTodoListSize", data),
|
||||
/** 流程中心 获取当前审核节点配置信息 */
|
||||
get_getNodeConfigInfo: (data?: QueryOptions) => http.get("/app/flowCenter/getNodeConfigInfo", data),
|
||||
/** 流程中心 获取下一节点配置信息 */
|
||||
get_getNextNodeConfig: (data?: QueryOptions) => http.get("/app/flowCenter/getNextNodeConfig", data),
|
||||
/** 流程中心 获取流程节点人员配置信息 */
|
||||
post_getFlowNodeUserConfig: (data?: BodyOptions) => http.post("/app/flowCenter/getFlowNodeUserConfig", data),
|
||||
},
|
||||
rl: {
|
||||
moduleParameter: {
|
||||
/** 流程中心/流程规划 保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/rl/moduleParameter/save", data),
|
||||
/** 流程中心/流程规划 查询 */
|
||||
post_page: (data?: BodyOptions) => http.post("/app/rl/moduleParameter/page", data),
|
||||
/** 流程中心/流程规划 删除 */
|
||||
get_deletes: (data?: QueryOptions) => http.get("/app/rl/moduleParameter/deletes", data),
|
||||
/** 流程中心/流程规划 获取节点审核人 */
|
||||
get_getNextNodeUser: (data?: QueryOptions) => http.get("/app/rl/moduleParameter/getNextNodeUser", data),
|
||||
},
|
||||
},
|
||||
dutyCount: {
|
||||
/** 协同办公/订餐管理/值班天数 分页查询 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/dutyCount/page", data),
|
||||
/** 协同办公/订餐管理/值班天数 批量保存 */
|
||||
post_saveBatch: (data?: BodyOptions) => http.post("/app/dutyCount/saveBatch", data),
|
||||
/** 协同办公/订餐管理/值班天数 删除 */
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/dutyCount/deletes", data),
|
||||
},
|
||||
common: {
|
||||
/** 公共 获取请求ip */
|
||||
get_getClientIp: (data?: QueryOptions) => http.get("/app/common/getClientIp", data),
|
||||
},
|
||||
address: {
|
||||
/** 协同办公/订餐管理/订餐地址 查询(分页) */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/address/page", data),
|
||||
/** 协同办公/订餐管理/订餐地址 保存 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/address/save", data),
|
||||
/** 协同办公/订餐管理/订餐地址 删除 */
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/address/deletes", data),
|
||||
},
|
||||
superviseFeedbackRecord: {
|
||||
/** 协同办公/督查督办/反馈记录 保存反馈记录 */
|
||||
post_save: (data?: BodyOptions) => http.post("/app/superviseFeedbackRecord/save", data),
|
||||
/** 协同办公/督查督办/反馈记录 查询反馈记录 */
|
||||
get_page: (data?: QueryOptions) => http.get("/app/superviseFeedbackRecord/page", data),
|
||||
/** 协同办公/督查督办/反馈记录 删除反馈记录 */
|
||||
post_deletes: (data?: BodyOptions) => http.post("/app/superviseFeedbackRecord/deletes", data),
|
||||
},
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
/** BaseUrl: 基础路径 */
|
||||
const BASE_URL: string = '/proxy-adm'
|
||||
const BASE_URL: string = '/api'
|
||||
|
||||
/** AccessTokenField: header 里传accessToken的键名,一般为 Authorization */
|
||||
export const ACCESS_TOKEN_FIELD = 'Token'
|
|
@ -4,10 +4,9 @@
|
|||
* @description: 创建新的请求实例实现
|
||||
*/
|
||||
import { createAlova } from 'alova'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
import fetchAdapter from 'alova/fetch';
|
||||
import vueHook from 'alova/vue';
|
||||
import { ResultEnum } from '@/enums/httpEnum'
|
||||
import { getBaseURL, ACCESS_TOKEN_FIELD } from './config';
|
||||
|
||||
let lock = false
|
||||
|
@ -20,10 +19,12 @@ const alova = createAlova({
|
|||
requestAdapter: fetchAdapter(),
|
||||
beforeRequest: (method) => {
|
||||
// ...原请求前拦截器
|
||||
const userStore = useUserStore()
|
||||
console.log('beforeRequest', userStore.accessToken)
|
||||
const accessStore = useAccessStore();
|
||||
|
||||
// const userStore = useUserStore()
|
||||
// console.log('beforeRequest', userStore.accessToken)
|
||||
// 添加token到请求头
|
||||
method.config.headers[ACCESS_TOKEN_FIELD] = `${userStore.accessToken}`
|
||||
// method.config.headers[ACCESS_TOKEN_FIELD] = `${userStore.accessToken}`
|
||||
},
|
||||
responded: async (response, method) => {
|
||||
let json = await response.json();
|
||||
|
@ -37,7 +38,7 @@ export function getAccessToken(rToken: string): Promise<any> {
|
|||
resolve,
|
||||
reject
|
||||
})
|
||||
const userStore = useUserStore();
|
||||
// const userStore = useUserStore();
|
||||
|
||||
if (!lock) {
|
||||
lock = true
|
||||
|
@ -52,9 +53,9 @@ export function getAccessToken(rToken: string): Promise<any> {
|
|||
console.log(data)
|
||||
// 如果 refreshToken 请求成功,则将新的token存储到本地
|
||||
if (data && data.accessToken) {
|
||||
userStore.setToken(data.accessToken);
|
||||
userStore.setTokenExpiresTime(data.accessExpire)
|
||||
userStore.setRefreshToken(data.refreshToken);
|
||||
// userStore.setToken(data.accessToken);
|
||||
// userStore.setTokenExpiresTime(data.accessExpire)
|
||||
// userStore.setRefreshToken(data.refreshToken);
|
||||
while (promiseResult.length) {
|
||||
// p1.resolve(res.data)
|
||||
promiseResult.shift().resolve(data)
|
||||
|
@ -62,7 +63,7 @@ export function getAccessToken(rToken: string): Promise<any> {
|
|||
lock = false
|
||||
return
|
||||
}
|
||||
userStore.resetStore()
|
||||
// userStore.resetStore()
|
||||
while (promiseResult.length) {
|
||||
// p1.reject(err)
|
||||
promiseResult.shift().reject("身份认证已失效,请重新登录")
|
|
@ -0,0 +1,404 @@
|
|||
/**
|
||||
* 该文件可自行根据业务逻辑进行调整
|
||||
*/
|
||||
import { useAppConfig } from '@vben/hooks';
|
||||
import { preferences } from '@vben/preferences';
|
||||
import {
|
||||
authenticateResponseInterceptor,
|
||||
errorMessageResponseInterceptor,
|
||||
RequestClient,
|
||||
} from '@vben/request';
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { useAuthStore } from '#/store';
|
||||
|
||||
import { refreshTokenApi } from '../core';
|
||||
import { transferResponse } from './transferResponse';
|
||||
import { type QueryOptions, type BodyOptions } from '../global.d';
|
||||
import { merge } from 'lodash-es';
|
||||
|
||||
|
||||
import { createAlova } from 'alova';
|
||||
import fetchAdapter from 'alova/fetch';
|
||||
import vueHook from 'alova/vue';
|
||||
import { ACCESS_TOKEN_FIELD, getBaseURL } from './config';
|
||||
import { createServerTokenAuthentication } from 'alova/client';
|
||||
|
||||
const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
||||
|
||||
function createRequestClient(baseURL: string) {
|
||||
const client = new RequestClient({
|
||||
baseURL,
|
||||
});
|
||||
|
||||
/**
|
||||
* 重新认证逻辑
|
||||
*/
|
||||
async function doReAuthenticate() {
|
||||
console.warn('Access token or refresh token is invalid or expired. ');
|
||||
const accessStore = useAccessStore();
|
||||
const authStore = useAuthStore();
|
||||
accessStore.setAccessToken(null);
|
||||
if (
|
||||
preferences.app.loginExpiredMode === 'modal' &&
|
||||
accessStore.isAccessChecked
|
||||
) {
|
||||
accessStore.setLoginExpired(true);
|
||||
} else {
|
||||
await authStore.logout();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新token逻辑
|
||||
*/
|
||||
async function doRefreshToken() {
|
||||
const accessStore = useAccessStore();
|
||||
const resp = await refreshTokenApi();
|
||||
const newToken = resp.data;
|
||||
accessStore.setAccessToken(newToken);
|
||||
return newToken;
|
||||
}
|
||||
|
||||
function formatToken(token: null | string) {
|
||||
return token ? `Bearer ${token}` : null;
|
||||
}
|
||||
|
||||
// 请求头处理
|
||||
client.addRequestInterceptor({
|
||||
fulfilled: async (config) => {
|
||||
const accessStore = useAccessStore();
|
||||
|
||||
config.headers.Authorization = formatToken(accessStore.accessToken);
|
||||
config.headers.Token = accessStore.accessToken;
|
||||
config.headers['Accept-Language'] = preferences.app.locale;
|
||||
return config;
|
||||
},
|
||||
});
|
||||
|
||||
// response数据解构
|
||||
client.addResponseInterceptor({
|
||||
fulfilled: (response) => {
|
||||
let { data: responseData, status } = response;
|
||||
|
||||
// 统一处理响应数据
|
||||
responseData = transferResponse(responseData);
|
||||
|
||||
console.log('【转换响应】', JSON.parse(JSON.stringify(responseData)));
|
||||
const { code, data, msg } = responseData;
|
||||
if (status >= 200 && status < 400 && code === 0) {
|
||||
return data;
|
||||
}
|
||||
throw new Error(`Error ${status}: ${msg}`);
|
||||
},
|
||||
});
|
||||
|
||||
// token过期的处理
|
||||
client.addResponseInterceptor(
|
||||
authenticateResponseInterceptor({
|
||||
client,
|
||||
doReAuthenticate,
|
||||
doRefreshToken,
|
||||
enableRefreshToken: preferences.app.enableRefreshToken,
|
||||
formatToken,
|
||||
}),
|
||||
);
|
||||
|
||||
// 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
|
||||
client.addResponseInterceptor(
|
||||
errorMessageResponseInterceptor((msg: string) => message.error(msg)),
|
||||
);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
export const requestClient = createRequestClient(apiURL);
|
||||
|
||||
/** 储存过期的token */
|
||||
let expireTokenCache = []
|
||||
|
||||
/** 服务端 Token 校验 */
|
||||
const { onAuthRequired, onResponseRefreshToken } = createServerTokenAuthentication({
|
||||
refreshTokenOnSuccess: {
|
||||
/**
|
||||
* 判断 Token 是否过期
|
||||
* 响应时触发,可获取到response和method,并返回boolean表示token是否过期
|
||||
*/
|
||||
isExpired: async (response, method) => {
|
||||
// 文件下载操作
|
||||
if (method.meta?.responseType === 'blob') {
|
||||
return false
|
||||
}
|
||||
|
||||
const responseClone = response.clone();
|
||||
let data = await responseClone.json()
|
||||
|
||||
// 当服务端返回401时,表示token过期
|
||||
let isExpired = ['401'].includes(data.code);
|
||||
if (isExpired) {
|
||||
console.log('AccessToken已过期', data.code)
|
||||
expireTokenCache.push(method.config.headers[ACCESS_TOKEN_FIELD])
|
||||
}
|
||||
|
||||
return isExpired;
|
||||
},
|
||||
/** 当token过期时触发,在此函数中触发刷新token */
|
||||
handler: async (response, method) => {
|
||||
console.warn('Access token or refresh token is invalid or expired. ');
|
||||
const accessStore = useAccessStore();
|
||||
const authStore = useAuthStore();
|
||||
accessStore.setAccessToken(null);
|
||||
if (
|
||||
preferences.app.loginExpiredMode === 'modal' &&
|
||||
accessStore.isAccessChecked
|
||||
) {
|
||||
accessStore.setLoginExpired(true);
|
||||
} else {
|
||||
await authStore.logout();
|
||||
}
|
||||
throw new Error('登录已过期,请重新登录');
|
||||
// const userStore = useUserStore();
|
||||
// try {
|
||||
// let rToken = userStore.refreshToken;
|
||||
// // 如果没有refreshToken,则跳转登录页
|
||||
// if (!rToken) {
|
||||
// throw new Error('登录已过期,请重新登录');
|
||||
// }
|
||||
// await getAccessToken(rToken)
|
||||
// expireTokenCache = []
|
||||
// } catch (error: any) {
|
||||
// window.$message?.error(error.message);
|
||||
// userStore.resetStore()
|
||||
// throw error;
|
||||
// }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const alovaInstance = createAlova({
|
||||
/** 动态代理配置 */
|
||||
baseURL: getBaseURL(),
|
||||
/** 框架请求适配器 */
|
||||
statesHook: vueHook,
|
||||
requestAdapter: fetchAdapter(),
|
||||
/** 设置缓存状态:不开启 */
|
||||
cacheFor: null,
|
||||
// cacheFor: {
|
||||
// // 统一设置POST的缓存模式
|
||||
// GET: {
|
||||
// mode: 'restore',
|
||||
// expire: 60 * 10 * 1000
|
||||
// },
|
||||
// POST: {
|
||||
// mode: 'restore',
|
||||
// expire: 60 * 10 * 1000
|
||||
// },
|
||||
// // 统一设置HEAD请求的缓存模式
|
||||
// HEAD: 60 * 10 * 1000
|
||||
// },
|
||||
/** 请求拦截器 */
|
||||
beforeRequest: onAuthRequired(method => {
|
||||
|
||||
const accessStore = useAccessStore();
|
||||
|
||||
|
||||
if (accessStore.accessToken) {
|
||||
method.config.headers.Token = accessStore.accessToken;
|
||||
// 统一授权的这个接口需要以Authorization传参,无语 /sys/user/functiontree/XTBGXT
|
||||
method.config.headers.Authorization = `Bearer ${accessStore.accessToken}`;
|
||||
|
||||
}
|
||||
method.config.headers['Accept-Language'] = preferences.app.locale;
|
||||
|
||||
// const userStore = useUserStore()
|
||||
// // 添加token到请求头
|
||||
// if (userStore.accessToken) {
|
||||
// method.config.headers[ACCESS_TOKEN_FIELD] = `Bearer ${userStore.accessToken}`
|
||||
|
||||
|
||||
// method.config.headers["Authorization"] = `Bearer ${userStore.accessToken}`
|
||||
// }
|
||||
|
||||
// method.config.cacheFor = {
|
||||
// // 设置缓存模式为内存模式
|
||||
// mode: 'restore',
|
||||
// // 单位为毫秒
|
||||
// // 当设置为`Infinity`,表示数据永不过期,设置为0或负数时表示不缓存
|
||||
// expire: 60 * 10 * 1000
|
||||
// }
|
||||
// method.config.transform = (rawData, headers) => {
|
||||
// console.log('接口响应', rawData)
|
||||
// return transferResponse(rawData)
|
||||
// }
|
||||
|
||||
}),
|
||||
/** 响应拦截器 */
|
||||
responded: onResponseRefreshToken(async (response, method) => {
|
||||
|
||||
if (method.meta?.responseType === 'blob') {
|
||||
|
||||
let blob = await response.blob();
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
const contentDisposition = response.headers.get('content-disposition');
|
||||
let fileName = 'downloaded-file';
|
||||
if (contentDisposition) {
|
||||
const matches = /filename="?([^"]+)"?/.exec(contentDisposition);
|
||||
if (matches != null && matches[1]) {
|
||||
fileName = decodeURIComponent(matches[1]);
|
||||
}
|
||||
}
|
||||
a.download = fileName;
|
||||
// 触发下载
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
// 移除链接
|
||||
document.body.removeChild(a);
|
||||
window.URL.revokeObjectURL(url);
|
||||
return {
|
||||
blob: blob,
|
||||
url: url,
|
||||
filename: fileName
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if (response.status >= 400) {
|
||||
// throw new Error(response.statusText);
|
||||
// }
|
||||
|
||||
|
||||
let json = await response.json();
|
||||
console.log('【接口】', method.url)
|
||||
console.log('原始响应', JSON.parse(JSON.stringify(json)))
|
||||
|
||||
json = transferResponse(json)
|
||||
console.log('改造响应', JSON.parse(JSON.stringify(json)))
|
||||
|
||||
if (json.code != 0) {
|
||||
if (json.code == '401') {
|
||||
message.error("用户身份过期,请重新登录");
|
||||
// const userStore = useUserStore();
|
||||
// userStore.resetStore();
|
||||
} else {
|
||||
message.error(json.msg || '服务器开小差,请稍后再试');
|
||||
}
|
||||
// 抛出错误或返回reject状态的Promise实例时,此请求将抛出错误
|
||||
throw new Error((json && json.msg) || '出错了');
|
||||
}
|
||||
|
||||
// 解析的响应数据将传给method实例的transformData钩子函数,这些函数将在后续讲解
|
||||
return json.data;
|
||||
})
|
||||
});
|
||||
|
||||
class Http {
|
||||
/**
|
||||
* 适配swagger路径参数,针对于pathParams
|
||||
* 输入参数 "/api/v1/user/{id}",{ pathParams:{ id :1 },params:{ id:2 } }
|
||||
* 输出请求 /api/v1/user/1?id=2
|
||||
*/
|
||||
private replacePathParams(url: string, pathParams?: any): string {
|
||||
if (!pathParams) return url;
|
||||
return url.replace(/{(\w+)}/g, (_, key) => pathParams[key] || `{${key}}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局默认配置
|
||||
* @param customConfig
|
||||
* @returns
|
||||
*/
|
||||
private getConfig(customConfig?: any): any {
|
||||
// 递归属性拷贝
|
||||
return merge({}, {
|
||||
meta: {
|
||||
showLoading: false,
|
||||
showError: false,
|
||||
},
|
||||
}, customConfig);
|
||||
}
|
||||
|
||||
private request(method: string, url: string, data?: BodyOptions | QueryOptions) {
|
||||
let finalUrl = this.replacePathParams(url, data?.pathParams);
|
||||
const config = this.getConfig(data?.config);
|
||||
|
||||
// 当组件使用allowClear属性时,会将数据置为null,导致数据查询失败
|
||||
if (data && data.params) {
|
||||
Object.keys(data.params).forEach(key => {
|
||||
if (data.params[key] === null || data.params[key] === undefined) {
|
||||
delete data.params[key]
|
||||
}
|
||||
})
|
||||
}
|
||||
if (data && data.data) {
|
||||
Object.keys(data.data).forEach(key => {
|
||||
if (data.data[key] === null || data.data[key] === undefined) {
|
||||
delete data.data[key]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let alovaMethod: 'Get' | 'Post' | 'Delete' | 'Put' = 'Get';
|
||||
|
||||
if (method === 'get' || method === 'delete') {
|
||||
if (method === 'get') {
|
||||
alovaMethod = 'Get'
|
||||
}
|
||||
if (method === 'delete') {
|
||||
alovaMethod = 'Delete'
|
||||
}
|
||||
return alovaInstance[alovaMethod](finalUrl, { ...config, params: data?.params });
|
||||
} else {
|
||||
// 处理 params 到 url 的逻辑
|
||||
if (data?.params) {
|
||||
finalUrl = this.appendParamsToUrl(finalUrl, data.params);
|
||||
}
|
||||
if (method === 'post') {
|
||||
alovaMethod = 'Post'
|
||||
}
|
||||
if (method === 'put') {
|
||||
alovaMethod = 'Put'
|
||||
}
|
||||
|
||||
|
||||
return alovaInstance[alovaMethod](finalUrl, data?.data, { ...config });
|
||||
}
|
||||
}
|
||||
|
||||
private appendParamsToUrl(url: string, params: any): string {
|
||||
let queryString = '';
|
||||
for (const key in params) {
|
||||
if (Object.prototype.hasOwnProperty.call(params, key)) {
|
||||
queryString += `${queryString ? '&' : '?'}${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`;
|
||||
}
|
||||
}
|
||||
return url + queryString;
|
||||
}
|
||||
|
||||
get(url: string, data?: QueryOptions) {
|
||||
return this.request('get', url, data);
|
||||
}
|
||||
|
||||
post(url: string, data?: BodyOptions) {
|
||||
return this.request('post', url, data);
|
||||
}
|
||||
|
||||
put(url: string, data?: BodyOptions) {
|
||||
return this.request('put', url, data);
|
||||
}
|
||||
|
||||
patch(url: string, data?: BodyOptions) {
|
||||
return this.request('patch', url, data);
|
||||
}
|
||||
|
||||
delete(url: string, data?: QueryOptions) {
|
||||
return this.request('delete', url, data);
|
||||
}
|
||||
}
|
||||
|
||||
export const http = new Http();
|
||||
|
||||
export const baseRequestClient = new RequestClient({ baseURL: apiURL });
|
|
@ -1,3 +1,4 @@
|
|||
const SUCCESS_CODE = 0;
|
||||
|
||||
/**
|
||||
* 统一相应处理,伪BFF层 很多接口返回的响应信息不统一,防止因后端规范问题导致前端工作量增加!!!!!!!故在此做统一处理
|
||||
|
@ -10,42 +11,45 @@ export function transferResponse(response: any) {
|
|||
// 如果后端直接返回数组,如[xxx]
|
||||
if (Array.isArray(response)) {
|
||||
return {
|
||||
code: import.meta.env.VITE_SERVICE_SUCCESS_CODE,
|
||||
msg: 'Ok',
|
||||
code: SUCCESS_CODE,
|
||||
data: {
|
||||
rows: response
|
||||
}
|
||||
rows: response,
|
||||
},
|
||||
msg: 'Ok',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// 如果后端直接返回数据内容对象,如{xxx},则先进行统一响应包装
|
||||
if (response.code == undefined) {
|
||||
response = {
|
||||
code: import.meta.env.VITE_SERVICE_SUCCESS_CODE,
|
||||
code: SUCCESS_CODE,
|
||||
data: response,
|
||||
msg: 'Ok',
|
||||
data: response
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let { code, msg, data = {}, ...rest } = response;
|
||||
let { code, data = {}, msg, ...rest } = response;
|
||||
|
||||
if (!data) {
|
||||
data = {}
|
||||
data = {};
|
||||
}
|
||||
if (typeof data === 'string') {
|
||||
data = {
|
||||
value: data
|
||||
}
|
||||
value: data,
|
||||
};
|
||||
}
|
||||
// eslint-disable-next-line eqeqeq
|
||||
if (code == 'success') {
|
||||
code = import.meta.env.VITE_SERVICE_SUCCESS_CODE;
|
||||
code = 0;
|
||||
}
|
||||
|
||||
if (code == 'failure' || (msg && msg.includes('token无效'))) {
|
||||
code = 401;
|
||||
}
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
data = {
|
||||
rows: data
|
||||
rows: data,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -69,15 +73,17 @@ export function transferResponse(response: any) {
|
|||
}
|
||||
|
||||
if (response.code == 200 && response.flag === false) {
|
||||
code = 500
|
||||
code = 500;
|
||||
} else if (response.code == '200') {
|
||||
code = 0;
|
||||
}
|
||||
|
||||
return {
|
||||
code,
|
||||
msg,
|
||||
data: {
|
||||
...data,
|
||||
...rest
|
||||
}
|
||||
...rest,
|
||||
},
|
||||
msg,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
import { baseRequestClient, requestClient } from '#/api/request/index';
|
||||
import type { UserInfo } from '@vben/types';
|
||||
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
export namespace AuthApi {
|
||||
/** 登录接口参数 */
|
||||
export interface LoginParams {
|
||||
password: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
/** 登录接口返回值 */
|
||||
export interface LoginResult {
|
||||
accessToken: string;
|
||||
desc: string;
|
||||
realName: string;
|
||||
userId: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface RefreshTokenResult {
|
||||
data: string;
|
||||
status: number;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
export async function loginApi(data: AuthApi.LoginParams) {
|
||||
return requestClient.post<AuthApi.LoginResult>(
|
||||
'/uc/uaa/validateAccount',
|
||||
data,
|
||||
{
|
||||
transformResponse: (res) => {
|
||||
res = JSON.parse(res);
|
||||
console.log(res);
|
||||
const info = res.data;
|
||||
if (info.access_token) {
|
||||
info.accessToken = info.access_token;
|
||||
info.realName = info.display_name;
|
||||
return info
|
||||
}
|
||||
return res;
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新accessToken
|
||||
*/
|
||||
export async function refreshTokenApi() {
|
||||
return baseRequestClient.post<AuthApi.RefreshTokenResult>('/auth/refresh', {
|
||||
withCredentials: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
export async function logoutApi() {
|
||||
return baseRequestClient.post('/uc/uaa/logout', {
|
||||
withCredentials: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户权限码
|
||||
*/
|
||||
export async function getAccessCodesApi() {
|
||||
return requestClient.get<string[]>('/auth/codes');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
export async function getUserInfoApi() {
|
||||
const accessStore = useAccessStore();
|
||||
return requestClient.post<UserInfo>('/uc/sys/user/checkToken', {
|
||||
token: accessStore.accessToken,
|
||||
});
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import type { RouteRecordStringComponent } from '@vben/types';
|
||||
|
||||
import { requestClient } from '#/api/request/index';
|
||||
|
||||
/**
|
||||
* 获取用户所有菜单
|
||||
*/
|
||||
export async function getAllMenusApi() {
|
||||
return requestClient.get<RouteRecordStringComponent[]>('/menu/all');
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
import { useAntdDesignTokens } from "@vben/hooks";
|
||||
import { preferences, usePreferences } from "@vben/preferences";
|
||||
|
||||
import { App, ConfigProvider, theme } from "ant-design-vue";
|
||||
|
||||
import { antdLocale } from "#/locales";
|
||||
import { useDictStore } from "./store/dict";
|
||||
|
||||
defineOptions({ name: "App" });
|
||||
|
||||
const { isDark } = usePreferences();
|
||||
const { tokens } = useAntdDesignTokens();
|
||||
|
||||
const tokenTheme = computed(() => {
|
||||
const algorithm = isDark.value ? [theme.darkAlgorithm] : [theme.defaultAlgorithm];
|
||||
|
||||
// antd 紧凑模式算法
|
||||
if (preferences.app.compact) {
|
||||
algorithm.push(theme.compactAlgorithm);
|
||||
}
|
||||
|
||||
return {
|
||||
algorithm,
|
||||
token: tokens,
|
||||
};
|
||||
});
|
||||
|
||||
const dictStore = useDictStore();
|
||||
if (dictStore.initDict) {
|
||||
dictStore.setDictMap();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ConfigProvider :locale="antdLocale" :theme="tokenTheme">
|
||||
<App>
|
||||
<RouterView />
|
||||
</App>
|
||||
</ConfigProvider>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.vxebasic-table-container {
|
||||
flex: auto;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.ant-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ant-modal-confirm-btns {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.ant-btn__warning {
|
||||
@apply bg-warning text-warning-foreground shadow hover:bg-warning/90;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
@ -0,0 +1,42 @@
|
|||
import { createApp } from 'vue';
|
||||
|
||||
import { registerAccessDirective } from '@vben/access';
|
||||
import { initStores } from '@vben/stores';
|
||||
import '@vben/styles';
|
||||
import '@vben/styles/antd';
|
||||
|
||||
import { setupI18n } from '#/locales';
|
||||
|
||||
import App from './app.vue';
|
||||
import { registerFastCrud } from './plugins/fastCrud';
|
||||
import { registerVxeTable } from './plugins/vxeTable';
|
||||
|
||||
import { router } from './router';
|
||||
import { VbenButton } from '@vben-core/shadcn-ui';
|
||||
|
||||
async function bootstrap(namespace: string) {
|
||||
const app = createApp(App);
|
||||
|
||||
// 国际化 i18n 配置
|
||||
await setupI18n(app);
|
||||
|
||||
// 配置 pinia-tore
|
||||
await initStores(app, { namespace });
|
||||
|
||||
// 安装权限指令
|
||||
registerAccessDirective(app);
|
||||
|
||||
// 配置路由及路由守卫
|
||||
app.use(router);
|
||||
|
||||
// 引入 fast-crud 相关组件
|
||||
registerFastCrud(app);
|
||||
|
||||
registerVxeTable(app)
|
||||
|
||||
app.component('vben-button', VbenButton);
|
||||
|
||||
app.mount('#app');
|
||||
}
|
||||
|
||||
export { bootstrap };
|
|
@ -0,0 +1,94 @@
|
|||
import { dict } from "@fast-crud/fast-crud";
|
||||
import Apis from '#/api'
|
||||
|
||||
export const unitComponentProps = {
|
||||
name: 'fs-dict-tree',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
class: 'min-w-[180px]',
|
||||
showCheckedStrategy: "SHOW_CHILD",
|
||||
dict: dict({
|
||||
isTree: true,
|
||||
async getData(dict, context) {
|
||||
const data = await Apis.api.core.orgemplbc.organization.post_paging({
|
||||
params: {
|
||||
page: 1,
|
||||
size: 1000
|
||||
},
|
||||
data: {
|
||||
subFilter: [
|
||||
{
|
||||
symbol: "like",
|
||||
singleValue: "0001%",
|
||||
key: "ORG_ID",
|
||||
logic: "AND",
|
||||
},
|
||||
],
|
||||
}
|
||||
});
|
||||
data.rows.forEach((item: any) => {
|
||||
item.label = item.ORG_NAME
|
||||
item.value = item.ORG_ID
|
||||
})
|
||||
let treeData = transTree(data.rows);
|
||||
return treeData;
|
||||
},
|
||||
}),
|
||||
}
|
||||
|
||||
export async function getUnitData(params = {}) {
|
||||
const data = await Apis.api.core.orgemplbc.organization.post_paging({
|
||||
params: {
|
||||
page: 1,
|
||||
size: 1000
|
||||
},
|
||||
data: {
|
||||
subFilter: [
|
||||
{
|
||||
symbol: "like",
|
||||
singleValue: "0001%",
|
||||
key: "ORG_ID",
|
||||
logic: "AND",
|
||||
},
|
||||
],
|
||||
}
|
||||
});
|
||||
data.rows.forEach((item: any) => {
|
||||
item.label = item.ORG_NAME
|
||||
item.value = item.ORG_ID
|
||||
})
|
||||
let treeData = transTree(data.rows);
|
||||
return treeData;
|
||||
}
|
||||
|
||||
// 转换树行数据的方法
|
||||
function transTree(list) {
|
||||
// 最终生成的树行结构
|
||||
const _treeData = [];
|
||||
|
||||
// 对传入进来的 数据进行遍历,查找对应的子级
|
||||
list.forEach((item) => {
|
||||
// 给每一项添加子节点
|
||||
// item.children = []
|
||||
item.key = item.ORG_ID;
|
||||
item.label = item.ORG_NAME;
|
||||
// 如果 pid 为空,说明是最顶级,直接放到 _treeData 中即可
|
||||
if (item.ORG_LEVEL == 1) {
|
||||
item.selectable = false
|
||||
_treeData.push(item);
|
||||
}
|
||||
|
||||
// 根据前面的分析,pid 代表的是父级的 id,从而可以进行筛选子级
|
||||
// filter 方法会把满足条件到的每一项,组成一个数组进行返回
|
||||
const children = list.filter((data) => data.PARENT_ID === item.ORG_ID);
|
||||
|
||||
// 如果没有子节点,直接 return 不做任何处理
|
||||
if (!children.length) return;
|
||||
|
||||
// 将返回的子级进行赋值给父级(item)的 children 属性
|
||||
item.children = children;
|
||||
});
|
||||
|
||||
// 将最终生成的数据返回出去
|
||||
return _treeData;
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
<template>
|
||||
<template v-if="props.selectable">
|
||||
<div v-for="(dict, index) in dicts" :key="index" @click="handleClick(dict)"
|
||||
:class="{ 'cursor-pointer': selectable }">
|
||||
<a-tag :color="getTagColor(dict)" :round="!multiple">
|
||||
{{ dict[labelField] }}
|
||||
</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else-if="Array.isArray(value)" class="flex flex-row flex-wrap">
|
||||
<template v-for="(dict, index) in dicts" :key="index">
|
||||
<div v-if="selectedValues.includes(dict.value)" class="mb-1">
|
||||
<a-tag>
|
||||
{{ dict[labelField] }}
|
||||
</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<template v-else>
|
||||
<!-- <a-tag :color="dictData?.colorType || ''">
|
||||
{{ (dictData && dictData[labelField]) || value }}
|
||||
</a-tag> -->
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import { Tag, Space } from "ant-design-vue";
|
||||
import { getDictOpts } from "#/utils/dict";
|
||||
import type { DictDataType } from "#/utils/dict";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
type?: string;
|
||||
options: DictDataType[];
|
||||
value?: string | number | boolean | Array<string | number | boolean>;
|
||||
icon?: string;
|
||||
multiple?: boolean;
|
||||
selectable?: boolean;
|
||||
labelField?: string;
|
||||
valueField?: string;
|
||||
}>(),
|
||||
{
|
||||
type: "",
|
||||
options: () => [],
|
||||
multiple: false,
|
||||
selectable: false,
|
||||
labelField: "label",
|
||||
valueField: "value",
|
||||
value: "",
|
||||
icon: "",
|
||||
}
|
||||
);
|
||||
|
||||
const emit = defineEmits(["update:value", "tag-click"]);
|
||||
|
||||
const dictData = ref<DictDataType | null>(null);
|
||||
const selectedValues = ref<Array<string | number>>(
|
||||
Array.isArray(props.value) ? props.value : []
|
||||
);
|
||||
|
||||
const dicts = computed(() => {
|
||||
return props.type ? getDictOpts(props.type) : props.options;
|
||||
});
|
||||
|
||||
const handleClick = (dict: DictDataType) => {
|
||||
emit("tag-click", dict);
|
||||
if (props.selectable) {
|
||||
if (props.multiple) {
|
||||
const index = selectedValues.value.indexOf(dict.value);
|
||||
if (index === -1) {
|
||||
selectedValues.value.push(dict.value);
|
||||
} else {
|
||||
selectedValues.value.splice(index, 1);
|
||||
}
|
||||
emit("update:value", selectedValues.value);
|
||||
} else {
|
||||
emit("update:value", dict.value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getTagColor = (dict: DictDataType) => {
|
||||
return (props.multiple && selectedValues.value.includes(dict.value)) ||
|
||||
(!props.multiple && props.value == dict.value)
|
||||
? "blue"
|
||||
: "";
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1 @@
|
|||
export { default as DictTag } from './dict-tag.vue';
|
|
@ -1,51 +1,45 @@
|
|||
import { h } from 'vue';
|
||||
import dayjs from 'dayjs';
|
||||
import { NButton, NTag, NTooltip } from 'naive-ui';
|
||||
import { isArray, isString } from '@/utils/is';
|
||||
import { DictTag } from '@/components/DictTag';
|
||||
import { Button, Tag } from 'ant-design-vue';
|
||||
import { isArray, isString } from 'lodash-es';
|
||||
import { DictTag } from '#/components/dict-tag';
|
||||
// import { Icon } from '@/components/Icon';
|
||||
// import { JsonPreview } from '@/components/CodeEditor';
|
||||
import TableImg from '../components/TableImg.vue';
|
||||
import { getDictOpts } from '@/utils/dict';
|
||||
|
||||
import { Tooltip } from 'ant-design-vue'
|
||||
import { getDictOpts } from '#/utils/dict';
|
||||
export const useRender = {
|
||||
/**
|
||||
* 渲染图片
|
||||
*
|
||||
* @param text 图片地址
|
||||
* @returns image标签
|
||||
*/
|
||||
renderImg: (text: string, props?: AnyObject) => {
|
||||
if (text) {
|
||||
if (isArray(text)) return h(TableImg, { imgList: text, ...props });
|
||||
else if (isString(text)) return h(TableImg, { imgList: [text], ...props });
|
||||
}
|
||||
return '';
|
||||
},
|
||||
// renderImg: (text: string) => {
|
||||
// if (text) {
|
||||
// if (isArray(text)) return h(TableImg, { imgList: text });
|
||||
// else if (isString(text)) return h(TableImg, { imgList: [text] });
|
||||
// }
|
||||
// return '';
|
||||
// },
|
||||
/**
|
||||
* 渲染链接
|
||||
*
|
||||
* @param url 链接地址
|
||||
* @param text 文字说明
|
||||
* @returns link 按钮
|
||||
*/
|
||||
renderLink: (url: string, text?: string) => {
|
||||
if (url) return h(NButton, { text: true, type: 'info', href: url, target: '_blank' }, () => text || '');
|
||||
if (url) return h(Button, { type: 'link', href: url, target: '_blank' }, () => text || '');
|
||||
|
||||
return '';
|
||||
},
|
||||
/**
|
||||
* 渲染文本,将text与val 拼接到一起
|
||||
*
|
||||
* @param text 文本1
|
||||
* @param val 文本2
|
||||
* @returns 文本1 + 文本2
|
||||
*/
|
||||
renderText(text, val) {
|
||||
if (text != undefined) return h('div', `${text} ${val}`);
|
||||
return h('div', '');
|
||||
renderText: (text: string, val: string) => {
|
||||
if (text) return `${text} ${val}`;
|
||||
else return '';
|
||||
},
|
||||
|
||||
/**
|
||||
* 渲染多行文本
|
||||
* @param text
|
||||
|
@ -59,7 +53,7 @@ export const useRender = {
|
|||
classArr.push('line-clamp-' + params?.maxLine)
|
||||
}
|
||||
return h(
|
||||
NTooltip,
|
||||
Tooltip,
|
||||
{ trigger: 'hover' },
|
||||
{
|
||||
trigger: () => h('span', { class: classArr.join(' ') }, text),
|
||||
|
@ -71,34 +65,31 @@ export const useRender = {
|
|||
},
|
||||
/**
|
||||
* 渲染标签
|
||||
*
|
||||
* @param text 标签文本
|
||||
* @param color 标签颜色
|
||||
* @returns 标签
|
||||
*/
|
||||
renderTag: (text: string | number, color?: string) => {
|
||||
if (color) return h(NTag, { type: color }, () => text);
|
||||
return h(NTag, {}, () => text);
|
||||
if (color) return h(Tag, { color }, () => text);
|
||||
else return h(Tag, {}, () => text);
|
||||
},
|
||||
/**
|
||||
* 渲染多标签
|
||||
*
|
||||
* @param texts 文本
|
||||
* @returns 多标签
|
||||
*/
|
||||
renderTags: (texts: string[]) => {
|
||||
if (texts) {
|
||||
return h('div', null, [
|
||||
texts.map(text => {
|
||||
return h(NTag, null, () => text);
|
||||
})
|
||||
texts.map((text) => {
|
||||
return h(Tag, null, () => text);
|
||||
}),
|
||||
]);
|
||||
}
|
||||
return '';
|
||||
},
|
||||
/**
|
||||
* 渲染日期
|
||||
*
|
||||
* @param text 日期
|
||||
* @param format 格式化
|
||||
* @returns 格式化后日期
|
||||
|
@ -107,11 +98,10 @@ export const useRender = {
|
|||
if (!text) return '';
|
||||
|
||||
if (!format) return dayjs(text).format('YYYY-MM-DD HH:mm:ss');
|
||||
return dayjs(text).format(format);
|
||||
else return dayjs(text).format(format);
|
||||
},
|
||||
/**
|
||||
* 渲染字典
|
||||
*
|
||||
* @param text 字典值
|
||||
* @param dictType 字典类型
|
||||
* @returns 字典标签
|
||||
|
@ -140,14 +130,13 @@ export const useRender = {
|
|||
// },
|
||||
/**
|
||||
* 使用JsonPreview组件 方便预览JSON
|
||||
*
|
||||
* @param json json字符串/obj
|
||||
* @returns 能转为json返回JsonPreview 否则返回自身
|
||||
*/
|
||||
// renderJsonPreview: (json: any) => {
|
||||
// if (!json) return '';
|
||||
// if (typeof json === 'object') return h(JsonPreview, { data: json });
|
||||
//
|
||||
|
||||
// if (typeof json === 'string') {
|
||||
// try {
|
||||
// const data = JSON.parse(json);
|
||||
|
@ -156,5 +145,5 @@ export const useRender = {
|
|||
// return json;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
};
|
|
@ -1,13 +1,13 @@
|
|||
import { merge } from "lodash-es";
|
||||
import { ref, computed } from "vue";
|
||||
import { VxeGridInstance, VxeGridProps } from "vxe-table";
|
||||
import { ref } from "vue";
|
||||
import { type VxeGridInstance, type VxeGridProps } from "vxe-table";
|
||||
|
||||
export function useVxeTable(props: {
|
||||
ref: string,
|
||||
}) {
|
||||
|
||||
|
||||
const xGridRef = ref<VxeGridInstance<AnyObject>>();
|
||||
const xGridRef = ref<VxeGridInstance<any>>();
|
||||
|
||||
return {
|
||||
xGridRef,
|
|
@ -0,0 +1,164 @@
|
|||
<script lang="ts" setup>
|
||||
import type { NotificationItem } from "@vben/layouts";
|
||||
|
||||
import { computed, ref } from "vue";
|
||||
import { storeToRefs, useAccessStore } from "@vben/stores";
|
||||
// import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
|
||||
|
||||
import { AuthenticationLoginExpiredModal } from "@vben/common-ui";
|
||||
import { BasicLayout, LockScreen, Notification, UserDropdown } from "@vben/layouts";
|
||||
import { preferences } from "@vben/preferences";
|
||||
import { useUserStore } from "@vben/stores";
|
||||
import { BookOpenText, CircleHelp, PhUserCircle } from "@vben/icons";
|
||||
|
||||
import { useAuthStore } from "#/store";
|
||||
import { useRouter } from "vue-router";
|
||||
const router = useRouter();
|
||||
|
||||
const notifications = ref<NotificationItem[]>([
|
||||
// {
|
||||
// avatar: "https://avatar.vercel.sh/vercel.svg?text=VB",
|
||||
// date: "3小时前",
|
||||
// isRead: true,
|
||||
// message: "描述信息描述信息描述信息",
|
||||
// title: "收到了 14 份新周报",
|
||||
// },
|
||||
// {
|
||||
// avatar: "https://avatar.vercel.sh/1",
|
||||
// date: "刚刚",
|
||||
// isRead: false,
|
||||
// message: "描述信息描述信息描述信息",
|
||||
// title: "朱偏右 回复了你",
|
||||
// },
|
||||
// {
|
||||
// avatar: "https://avatar.vercel.sh/1",
|
||||
// date: "2024-01-01",
|
||||
// isRead: false,
|
||||
// message: "描述信息描述信息描述信息",
|
||||
// title: "曲丽丽 评论了你",
|
||||
// },
|
||||
// {
|
||||
// avatar: "https://avatar.vercel.sh/satori",
|
||||
// date: "1天前",
|
||||
// isRead: false,
|
||||
// message: "描述信息描述信息描述信息",
|
||||
// title: "代办提醒",
|
||||
// },
|
||||
]);
|
||||
|
||||
const userStore = useUserStore();
|
||||
const authStore = useAuthStore();
|
||||
const accessStore = useAccessStore();
|
||||
const showDot = computed(() => notifications.value.some((item) => !item.isRead));
|
||||
|
||||
const menus = computed(() => [
|
||||
{
|
||||
handler: () => {
|
||||
router.push("/user/center");
|
||||
},
|
||||
icon: PhUserCircle,
|
||||
text: "个人中心",
|
||||
},
|
||||
// {
|
||||
// handler: () => {
|
||||
// openWindow(VBEN_GITHUB_URL, {
|
||||
// target: '_blank',
|
||||
// });
|
||||
// },
|
||||
// icon: MdiGithub,
|
||||
// text: 'GitHub',
|
||||
// },
|
||||
// {
|
||||
// handler: () => {
|
||||
// openWindow(`${VBEN_GITHUB_URL}/issues`, {
|
||||
// target: '_blank',
|
||||
// });
|
||||
// },
|
||||
// icon: CircleHelp,
|
||||
// text: $t('widgets.qa'),
|
||||
// },
|
||||
]);
|
||||
|
||||
const { loginLoading } = storeToRefs(authStore);
|
||||
|
||||
const avatar = computed(() => {
|
||||
return userStore.userInfo?.avatar ?? preferences.app.defaultAvatar;
|
||||
});
|
||||
|
||||
async function handleLogout() {
|
||||
await authStore.logout(false);
|
||||
}
|
||||
|
||||
function handleNoticeClear() {
|
||||
notifications.value = [];
|
||||
}
|
||||
|
||||
function handleMakeAll() {
|
||||
notifications.value.forEach((item) => (item.isRead = true));
|
||||
}
|
||||
|
||||
function handleViewAll() {
|
||||
console.log("viewAll");
|
||||
router.push("/user/todo");
|
||||
}
|
||||
|
||||
const isDev = import.meta.env.DEV;
|
||||
const value = ref(localStorage.getItem("@@@proxy_type") || ""); // /zp
|
||||
function handleMenuClick(e) {
|
||||
console.log(e);
|
||||
if (e.key == "pro") {
|
||||
localStorage.setItem("@@@proxy_type", "");
|
||||
} else {
|
||||
localStorage.setItem("@@@proxy_type", "/" + e.key);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BasicLayout @clear-preferences-and-logout="handleLogout">
|
||||
<template #user-dropdown>
|
||||
<UserDropdown
|
||||
:avatar
|
||||
:description="userStore.userInfo?.belongOrgName"
|
||||
:menus
|
||||
:tag-text="userStore.userInfo?.gwmc"
|
||||
:text="userStore.userInfo?.displayName"
|
||||
@logout="handleLogout"
|
||||
/>
|
||||
</template>
|
||||
<template #notification>
|
||||
<a-dropdown v-if="isDev">
|
||||
<template #overlay>
|
||||
<a-menu @click="handleMenuClick" selectable>
|
||||
<a-menu-item key="pro"> 正式 </a-menu-item>
|
||||
<a-menu-item key="czg"> czg </a-menu-item>
|
||||
<a-menu-item key="zp"> zp </a-menu-item>
|
||||
<a-menu-item key="zzz"> zzz </a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button> {{ value ? "代理" + value : "代理切换" }} </a-button>
|
||||
</a-dropdown>
|
||||
|
||||
<Notification
|
||||
:dot="showDot"
|
||||
:notifications="notifications"
|
||||
@clear="handleNoticeClear"
|
||||
@make-all="handleMakeAll"
|
||||
@view-all="handleViewAll"
|
||||
/>
|
||||
</template>
|
||||
<template #extra>
|
||||
<AuthenticationLoginExpiredModal
|
||||
v-model:open="accessStore.loginExpired"
|
||||
:avatar
|
||||
:loading="loginLoading"
|
||||
password-placeholder=""
|
||||
username-placeholder=""
|
||||
@submit="authStore.authLogin"
|
||||
/>
|
||||
</template>
|
||||
<template #lock-screen>
|
||||
<LockScreen :avatar :text="userStore.userInfo?.displayName" @to-login="handleLogout" />
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
|
@ -0,0 +1,8 @@
|
|||
const BasicLayout = () => import('./basic.vue');
|
||||
|
||||
const IFrameView = () => import('@vben/layouts').then((m) => m.IFrameView);
|
||||
|
||||
const AuthPageLayout = () =>
|
||||
import('@vben/layouts').then((m) => m.AuthPageLayout);
|
||||
|
||||
export { AuthPageLayout, BasicLayout, IFrameView };
|
|
@ -0,0 +1,3 @@
|
|||
# locale
|
||||
|
||||
每个app使用的国际化可能不同,这里用于扩展国际化的功能,例如扩展 dayjs、antd组件库的多语言切换,以及app本身的国际化文件。
|
|
@ -0,0 +1,94 @@
|
|||
import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales';
|
||||
import type { Locale } from 'ant-design-vue/es/locale';
|
||||
|
||||
import type { App } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { $t, setupI18n as coreSetup, loadLocalesMap } from '@vben/locales';
|
||||
import { preferences } from '@vben/preferences';
|
||||
|
||||
import antdEnLocale from 'ant-design-vue/es/locale/en_US';
|
||||
import antdDefaultLocale from 'ant-design-vue/es/locale/zh_CN';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const antdLocale = ref<Locale>(antdDefaultLocale);
|
||||
|
||||
const modules = import.meta.glob('./langs/*.json');
|
||||
|
||||
const localesMap = loadLocalesMap(modules);
|
||||
|
||||
/**
|
||||
* 加载应用特有的语言包
|
||||
* 这里也可以改造为从服务端获取翻译数据
|
||||
* @param lang
|
||||
*/
|
||||
async function loadMessages(lang: SupportedLanguagesType) {
|
||||
const [appLocaleMessages] = await Promise.all([
|
||||
localesMap[lang]?.(),
|
||||
loadThirdPartyMessage(lang),
|
||||
]);
|
||||
return appLocaleMessages?.default;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载第三方组件库的语言包
|
||||
* @param lang
|
||||
*/
|
||||
async function loadThirdPartyMessage(lang: SupportedLanguagesType) {
|
||||
await Promise.all([loadAntdLocale(lang), loadDayjsLocale(lang)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载dayjs的语言包
|
||||
* @param lang
|
||||
*/
|
||||
async function loadDayjsLocale(lang: SupportedLanguagesType) {
|
||||
let locale;
|
||||
switch (lang) {
|
||||
case 'zh-CN': {
|
||||
locale = await import('dayjs/locale/zh-cn');
|
||||
break;
|
||||
}
|
||||
case 'en-US': {
|
||||
locale = await import('dayjs/locale/en');
|
||||
break;
|
||||
}
|
||||
// 默认使用英语
|
||||
default: {
|
||||
locale = await import('dayjs/locale/en');
|
||||
}
|
||||
}
|
||||
if (locale) {
|
||||
dayjs.locale(locale);
|
||||
} else {
|
||||
console.error(`Failed to load dayjs locale for ${lang}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载antd的语言包
|
||||
* @param lang
|
||||
*/
|
||||
async function loadAntdLocale(lang: SupportedLanguagesType) {
|
||||
switch (lang) {
|
||||
case 'zh-CN': {
|
||||
antdLocale.value = antdDefaultLocale;
|
||||
break;
|
||||
}
|
||||
case 'en-US': {
|
||||
antdLocale.value = antdEnLocale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
|
||||
await coreSetup(app, {
|
||||
defaultLocale: preferences.app.locale,
|
||||
loadMessages,
|
||||
missingWarn: !import.meta.env.PROD,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
export { $t, antdLocale, setupI18n };
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"page": {
|
||||
"demos": {
|
||||
"title": "Demos",
|
||||
"antd": "Ant Design Vue"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"page": {
|
||||
"demos": {
|
||||
"title": "演示",
|
||||
"antd": "Ant Design Vue"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
import { initPreferences } from '@vben/preferences';
|
||||
import { unmountGlobalLoading } from '@vben/utils';
|
||||
|
||||
import { overridesPreferences } from './preferences';
|
||||
|
||||
/**
|
||||
* 应用初始化完成之后再进行页面加载渲染
|
||||
*/
|
||||
async function initApplication() {
|
||||
// name用于指定项目唯一标识
|
||||
// 用于区分不同项目的偏好设置以及存储数据的key前缀以及其他一些需要隔离的数据
|
||||
const env = import.meta.env.PROD ? 'prod' : 'dev';
|
||||
const appVersion = import.meta.env.VITE_APP_VERSION;
|
||||
const namespace = `${import.meta.env.VITE_APP_NAMESPACE}-${appVersion}-${env}`;
|
||||
|
||||
// app偏好设置初始化
|
||||
await initPreferences({
|
||||
namespace,
|
||||
overrides: overridesPreferences,
|
||||
});
|
||||
|
||||
// 启动应用并挂载
|
||||
// vue应用主要逻辑及视图
|
||||
const { bootstrap } = await import('./bootstrap');
|
||||
await bootstrap(namespace);
|
||||
|
||||
// 移除并销毁loading
|
||||
unmountGlobalLoading();
|
||||
}
|
||||
|
||||
initApplication();
|
|
@ -0,0 +1,21 @@
|
|||
import type { App } from 'vue';
|
||||
|
||||
import FastCrud from '@fast-crud/fast-crud';
|
||||
import ui from '@fast-crud/ui-antdv4';
|
||||
import Antdv from 'ant-design-vue';
|
||||
import { requestClient } from '#/api/request/index';
|
||||
import '@fast-crud/fast-crud/dist/style.css';
|
||||
import '@fast-crud/ui-antdv4/dist/style.css';
|
||||
|
||||
export function registerFastCrud(app: App) {
|
||||
app.use(Antdv);
|
||||
app.use(ui);
|
||||
app.use(FastCrud, {
|
||||
async dictRequest(dict) {
|
||||
//通过字段组件中配置的dict.url获取远程字典数据
|
||||
let res = await requestClient.get('/app/dictData/page');
|
||||
console.log(res)
|
||||
return res.rows;
|
||||
},
|
||||
});
|
||||
}
|
|
@ -0,0 +1,202 @@
|
|||
import type { App } from 'vue';
|
||||
|
||||
import VXETable from 'vxe-table'
|
||||
|
||||
import {
|
||||
VxeTable,
|
||||
VxeColumn,
|
||||
VxeColgroup,
|
||||
VxeGrid,
|
||||
VxeToolbar
|
||||
} from 'vxe-table'
|
||||
|
||||
import VxeUI from 'vxe-pc-ui'
|
||||
|
||||
import {
|
||||
|
||||
VxeAlert,
|
||||
VxeAnchor,
|
||||
VxeAnchorLink,
|
||||
VxeBreadcrumb,
|
||||
VxeBreadcrumbItem,
|
||||
VxeButton,
|
||||
VxeButtonGroup,
|
||||
VxeCalendar,
|
||||
VxeCard,
|
||||
VxeCarousel,
|
||||
VxeCheckbox,
|
||||
VxeCheckboxGroup,
|
||||
VxeCol,
|
||||
VxeCollapse,
|
||||
VxeCollapsePane,
|
||||
VxeDatePicker,
|
||||
VxeDrawer,
|
||||
VxeForm,
|
||||
VxeFormDesign,
|
||||
VxeFormGather,
|
||||
VxeFormItem,
|
||||
VxeFormView,
|
||||
VxeIcon,
|
||||
VxeIconPicker,
|
||||
VxeImage,
|
||||
VxeImageGroup,
|
||||
VxeImagePreview,
|
||||
VxeInput,
|
||||
VxeLayoutAside,
|
||||
VxeLayoutBody,
|
||||
VxeLayoutContainer,
|
||||
VxeLayoutFooter,
|
||||
VxeLayoutHeader,
|
||||
VxeLink,
|
||||
VxeListDesign,
|
||||
VxeListView,
|
||||
VxeList,
|
||||
VxeLoading,
|
||||
VxeMenu,
|
||||
VxeModal,
|
||||
VxeNumberInput,
|
||||
VxeOptgroup,
|
||||
VxeOption,
|
||||
VxePager,
|
||||
VxePasswordInput,
|
||||
VxePrintPageBreak,
|
||||
VxePrint,
|
||||
VxePulldown,
|
||||
VxeRadio,
|
||||
VxeRadioButton,
|
||||
VxeRadioGroup,
|
||||
VxeRow,
|
||||
VxeSelect,
|
||||
VxeSwitch,
|
||||
VxeTabPane,
|
||||
VxeTabs,
|
||||
VxeTag,
|
||||
VxeText,
|
||||
VxeTextarea,
|
||||
VxeTip,
|
||||
VxeTooltip,
|
||||
VxeTree,
|
||||
VxeTreeSelect,
|
||||
VxeUpload
|
||||
} from 'vxe-pc-ui'
|
||||
|
||||
import VXETablePluginExportXLSX from 'vxe-table-plugin-export-xlsx'
|
||||
import ExcelJS from 'exceljs'
|
||||
|
||||
import VXETablePluginAntd from 'vxe-table-plugin-antd'
|
||||
|
||||
// 导入主题变量,也可以重写主题变量
|
||||
import 'vxe-pc-ui/lib/style.css'
|
||||
import 'vxe-table/lib/style.css'
|
||||
import 'vxe-table/styles/cssvar.scss'
|
||||
import 'vxe-pc-ui/styles/cssvar.scss'
|
||||
|
||||
// VxeUI.setTheme('dark')
|
||||
|
||||
VxeUI.component(VxeAlert)
|
||||
VxeUI.component(VxeAnchor)
|
||||
VxeUI.component(VxeAnchorLink)
|
||||
VxeUI.component(VxeBreadcrumb)
|
||||
VxeUI.component(VxeBreadcrumbItem)
|
||||
VxeUI.component(VxeButton)
|
||||
VxeUI.component(VxeButtonGroup)
|
||||
VxeUI.component(VxeCalendar)
|
||||
VxeUI.component(VxeCard)
|
||||
VxeUI.component(VxeCarousel)
|
||||
VxeUI.component(VxeCheckbox)
|
||||
VxeUI.component(VxeCheckboxGroup)
|
||||
VxeUI.component(VxeCol)
|
||||
VxeUI.component(VxeCollapse)
|
||||
VxeUI.component(VxeCollapsePane)
|
||||
VxeUI.component(VxeDatePicker)
|
||||
VxeUI.component(VxeDrawer)
|
||||
VxeUI.component(VxeForm)
|
||||
VxeUI.component(VxeFormDesign)
|
||||
VxeUI.component(VxeFormGather)
|
||||
VxeUI.component(VxeFormItem)
|
||||
VxeUI.component(VxeFormView)
|
||||
VxeUI.component(VxeIcon)
|
||||
VxeUI.component(VxeIconPicker)
|
||||
VxeUI.component(VxeImage)
|
||||
VxeUI.component(VxeImageGroup)
|
||||
VxeUI.component(VxeImagePreview)
|
||||
VxeUI.component(VxeInput)
|
||||
VxeUI.component(VxeLayoutAside)
|
||||
VxeUI.component(VxeLayoutBody)
|
||||
VxeUI.component(VxeLayoutContainer)
|
||||
VxeUI.component(VxeLayoutFooter)
|
||||
VxeUI.component(VxeLayoutHeader)
|
||||
VxeUI.component(VxeLink)
|
||||
VxeUI.component(VxeListDesign)
|
||||
VxeUI.component(VxeListView)
|
||||
VxeUI.component(VxeList)
|
||||
VxeUI.component(VxeLoading)
|
||||
VxeUI.component(VxeMenu)
|
||||
VxeUI.component(VxeModal)
|
||||
VxeUI.component(VxeNumberInput)
|
||||
VxeUI.component(VxeOptgroup)
|
||||
VxeUI.component(VxeOption)
|
||||
VxeUI.component(VxePager)
|
||||
VxeUI.component(VxePasswordInput)
|
||||
VxeUI.component(VxePrintPageBreak)
|
||||
VxeUI.component(VxePrint)
|
||||
VxeUI.component(VxePulldown)
|
||||
VxeUI.component(VxeRadio)
|
||||
VxeUI.component(VxeRadioButton)
|
||||
VxeUI.component(VxeRadioGroup)
|
||||
VxeUI.component(VxeRow)
|
||||
VxeUI.component(VxeSelect)
|
||||
VxeUI.component(VxeSwitch)
|
||||
VxeUI.component(VxeTabPane)
|
||||
VxeUI.component(VxeTabs)
|
||||
VxeUI.component(VxeTag)
|
||||
VxeUI.component(VxeText)
|
||||
VxeUI.component(VxeTextarea)
|
||||
VxeUI.component(VxeTip)
|
||||
VxeUI.component(VxeTooltip)
|
||||
VxeUI.component(VxeTree)
|
||||
VxeUI.component(VxeTreeSelect)
|
||||
VxeUI.component(VxeUpload)
|
||||
|
||||
VxeUI.component(VxeTable)
|
||||
VxeUI.component(VxeColumn)
|
||||
VxeUI.component(VxeColgroup)
|
||||
VxeUI.component(VxeGrid)
|
||||
VxeUI.component(VxeToolbar)
|
||||
|
||||
VXETable.use(VXETablePluginAntd)
|
||||
|
||||
VXETable.use(VXETablePluginExportXLSX, {
|
||||
ExcelJS
|
||||
})
|
||||
|
||||
VXETable.setConfig({
|
||||
zIndex: 9999,
|
||||
grid: {
|
||||
size: 'mini',
|
||||
proxyConfig: {
|
||||
props: {
|
||||
result: 'data.rows',
|
||||
total: 'data.total',
|
||||
},
|
||||
},
|
||||
toolbarConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
|
||||
pager: {
|
||||
background: true,
|
||||
pageSize: 50,
|
||||
pageSizes: [50, 100, 300, 500, 1000],
|
||||
layouts: ['PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'Sizes', 'FullJump', 'Total'],
|
||||
},
|
||||
})
|
||||
export function registerVxeTable(app: App) {
|
||||
app.use(VxeUI)
|
||||
app.use(VxeTable)
|
||||
app.use(VxeColumn)
|
||||
app.use(VxeColgroup)
|
||||
app.use(VxeGrid)
|
||||
app.use(VxeToolbar)
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import { defineOverridesPreferences } from '@vben/preferences';
|
||||
|
||||
/**
|
||||
* @description 项目配置文件
|
||||
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
||||
*/
|
||||
export const overridesPreferences = defineOverridesPreferences({
|
||||
// overrides
|
||||
app: {
|
||||
name: import.meta.env.VITE_APP_TITLE,
|
||||
},
|
||||
});
|
|
@ -0,0 +1,42 @@
|
|||
import type {
|
||||
ComponentRecordType,
|
||||
GenerateMenuAndRoutesOptions,
|
||||
} from '@vben/types';
|
||||
|
||||
import { generateAccessible } from '@vben/access';
|
||||
import { preferences } from '@vben/preferences';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { getAllMenusApi } from '#/api/system/menu';
|
||||
import { BasicLayout, IFrameView } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const forbiddenComponent = () => import('#/views/_core/fallback/forbidden.vue');
|
||||
|
||||
async function generateAccess(options: GenerateMenuAndRoutesOptions) {
|
||||
const pageMap: ComponentRecordType = import.meta.glob('../views/**/*.vue');
|
||||
|
||||
const layoutMap: ComponentRecordType = {
|
||||
BasicLayout,
|
||||
IFrameView,
|
||||
};
|
||||
|
||||
return await generateAccessible(preferences.app.accessMode, {
|
||||
...options,
|
||||
fetchMenuListAsync: async () => {
|
||||
message.loading({
|
||||
content: `${$t('common.loadingMenu')}...`,
|
||||
duration: 1.5,
|
||||
});
|
||||
return await getAllMenusApi();
|
||||
},
|
||||
// 可以指定没有权限跳转403页面
|
||||
forbiddenComponent,
|
||||
// 如果 route.meta.menuVisibleWithForbidden = true
|
||||
layoutMap,
|
||||
pageMap,
|
||||
});
|
||||
}
|
||||
|
||||
export { generateAccess };
|
|
@ -0,0 +1,240 @@
|
|||
import type { Router } from 'vue-router';
|
||||
|
||||
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
|
||||
import { preferences } from '@vben/preferences';
|
||||
import { useAccessStore, useUserStore } from '@vben/stores';
|
||||
import { startProgress, stopProgress } from '@vben/utils';
|
||||
|
||||
import { useTitle } from '@vueuse/core';
|
||||
|
||||
import { $t } from '#/locales';
|
||||
import { coreRouteNames, dynamicRoutes } from '#/router/routes';
|
||||
import { useAuthStore } from '#/store';
|
||||
import Apis from '#/api';
|
||||
import { generateAccess } from './access';
|
||||
|
||||
/**
|
||||
* 通用守卫配置
|
||||
* @param router
|
||||
*/
|
||||
function setupCommonGuard(router: Router) {
|
||||
// 记录已经加载的页面
|
||||
const loadedPaths = new Set<string>();
|
||||
|
||||
router.beforeEach(async (to) => {
|
||||
to.meta.loaded = loadedPaths.has(to.path);
|
||||
|
||||
// 页面加载进度条
|
||||
if (!to.meta.loaded && preferences.transition.progress) {
|
||||
startProgress();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
router.afterEach((to) => {
|
||||
// 记录页面是否加载,如果已经加载,后续的页面切换动画等效果不在重复执行
|
||||
|
||||
if (preferences.tabbar.enable) {
|
||||
loadedPaths.add(to.path);
|
||||
}
|
||||
|
||||
// 关闭页面加载进度条
|
||||
if (preferences.transition.progress) {
|
||||
stopProgress();
|
||||
}
|
||||
|
||||
// 动态修改标题
|
||||
if (preferences.app.dynamicTitle) {
|
||||
const { title } = to.meta;
|
||||
// useTitle(`${$t(title)} - ${preferences.app.name}`);
|
||||
useTitle(`${$t(title)} - ${preferences.app.name}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 匹配路径
|
||||
* permission.path = "/xx/edit" 但route.path = "/xx/edit/:id?" 这种情况,其中id可以为任意值,如meetingId roleId等,
|
||||
*/
|
||||
function matchPaths(routePath, permissionPath) {
|
||||
const routeParts = routePath.split('/');
|
||||
const permissionParts = permissionPath.split('/');
|
||||
|
||||
if (permissionParts.length > routeParts.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return routeParts.every((part, index) => {
|
||||
return part === permissionParts[index] || part.startsWith(':');
|
||||
});
|
||||
}
|
||||
|
||||
// 过滤路由,只保留第三个数据源配置的路由
|
||||
function filterRoutesByPermissions(routes, permissions, staticRouteKeys) {
|
||||
const filteredRoutes = [];
|
||||
for (let route of routes) {
|
||||
console.log('[ route ] >', route)
|
||||
console.log('[ permission.path ] >', permissions)
|
||||
|
||||
const permission = permissions.find(permission =>
|
||||
matchPaths(route.path, permission.path)
|
||||
);
|
||||
const isStaticRoute = staticRouteKeys.includes(route.name);
|
||||
|
||||
if (permission || isStaticRoute) {
|
||||
const newRoute = { ...route };
|
||||
if (permission) {
|
||||
newRoute.meta = {
|
||||
...newRoute.meta,
|
||||
title: permission.name,
|
||||
};
|
||||
if (permission.order) {
|
||||
newRoute.meta.order = permission.order
|
||||
}
|
||||
|
||||
}
|
||||
if (route.children) {
|
||||
newRoute.children = filterRoutesByPermissions(route.children, permissions, staticRouteKeys);
|
||||
}
|
||||
filteredRoutes.push(newRoute);
|
||||
console.log(JSON.parse(JSON.stringify(filteredRoutes)));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return filteredRoutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限访问守卫配置
|
||||
* @param router
|
||||
*/
|
||||
function setupAccessGuard(router: Router) {
|
||||
router.beforeEach(async (to, from) => {
|
||||
const accessStore = useAccessStore();
|
||||
const userStore = useUserStore();
|
||||
const authStore = useAuthStore();
|
||||
|
||||
// 基本路由,这些路由不需要进入权限拦截
|
||||
if (coreRouteNames.includes(to.name as string)) {
|
||||
if (to.path === LOGIN_PATH && accessStore.accessToken) {
|
||||
return decodeURIComponent(
|
||||
(to.query?.redirect as string) || DEFAULT_HOME_PATH,
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// accessToken 检查
|
||||
if (!accessStore.accessToken) {
|
||||
// 明确声明忽略权限访问权限,则可以访问
|
||||
if (to.meta.ignoreAccess) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 没有访问权限,跳转登录页面
|
||||
if (to.fullPath !== LOGIN_PATH) {
|
||||
return {
|
||||
path: LOGIN_PATH,
|
||||
// 如不需要,直接删除 query
|
||||
query: { redirect: encodeURIComponent(to.fullPath) },
|
||||
// 携带当前跳转的页面,登录后重新跳转该页面
|
||||
replace: true,
|
||||
};
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
// 是否已经生成过动态路由
|
||||
if (accessStore.isAccessChecked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 生成路由表
|
||||
// 当前登录用户拥有的角色标识列表
|
||||
const userInfo = userStore.userInfo || (await authStore.fetchUserInfo());
|
||||
const userRoles = userInfo.roles ?? [];
|
||||
|
||||
// debugger
|
||||
|
||||
// 二开,从统一授权获取菜单key值,遍历本地所有菜单进行添加
|
||||
|
||||
let staticRouteKeys = ["Dashboard", "home", "User", "UserCenter", "UserTodo","IFrame","MeetingStandingBook","MeetingStart","DutyStandingBook","ContractInfo"];
|
||||
|
||||
let r = await Apis.sys.user.functiontree.get_XTBGXT()
|
||||
let originRouters = r.rows[0].children;
|
||||
// 提取数据的函数
|
||||
const extractData = (input: any[]) => {
|
||||
const result: any[] = [];
|
||||
function traverse(node: any) {
|
||||
if (node.id && node.name && node.remark) {
|
||||
result.push({
|
||||
path: node.remark,
|
||||
name: node.name,
|
||||
order: node.showOrder || 0,
|
||||
});
|
||||
}
|
||||
if (node.children && node.children.length > 0) {
|
||||
for (const child of node.children) {
|
||||
traverse(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const node of input) {
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
console.log('originRouters', originRouters)
|
||||
originRouters = extractData(originRouters);
|
||||
console.log('originRouters', originRouters)
|
||||
|
||||
let finalRoutes = filterRoutesByPermissions(dynamicRoutes, originRouters, staticRouteKeys);
|
||||
|
||||
console.log(originRouters)
|
||||
console.log('finalRoutes', finalRoutes)
|
||||
|
||||
console.log('dynamicRoutes', dynamicRoutes)
|
||||
console.log('userInfo', userInfo)
|
||||
|
||||
if (userInfo.accountId == 'Admin.itl'|| userInfo._isSkip) {
|
||||
finalRoutes = dynamicRoutes;
|
||||
}
|
||||
|
||||
console.log(userInfo)
|
||||
|
||||
|
||||
// 生成菜单和路由
|
||||
const { accessibleMenus, accessibleRoutes } = await generateAccess({
|
||||
roles: userRoles,
|
||||
router,
|
||||
// 则会在菜单中显示,但是访问会被重定向到403
|
||||
routes: finalRoutes,
|
||||
});
|
||||
// 保存菜单信息和路由信息
|
||||
accessStore.setAccessMenus(accessibleMenus);
|
||||
accessStore.setAccessRoutes(accessibleRoutes);
|
||||
accessStore.setIsAccessChecked(true);
|
||||
const redirectPath = (from.query.redirect ?? to.fullPath) as string;
|
||||
|
||||
return {
|
||||
...router.resolve(decodeURIComponent(redirectPath)),
|
||||
replace: true,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目守卫配置
|
||||
* @param router
|
||||
*/
|
||||
function createRouterGuard(router: Router) {
|
||||
/** 通用 */
|
||||
setupCommonGuard(router);
|
||||
/** 权限访问 */
|
||||
setupAccessGuard(router);
|
||||
}
|
||||
|
||||
export { createRouterGuard };
|
|
@ -0,0 +1,32 @@
|
|||
import {
|
||||
createRouter,
|
||||
createWebHashHistory,
|
||||
createWebHistory,
|
||||
} from 'vue-router';
|
||||
|
||||
import { resetStaticRoutes } from '@vben/utils';
|
||||
|
||||
import { createRouterGuard } from './guard';
|
||||
import { routes } from './routes';
|
||||
|
||||
/**
|
||||
* @zh_CN 创建vue-router实例
|
||||
*/
|
||||
const router = createRouter({
|
||||
history:
|
||||
import.meta.env.VITE_ROUTER_HISTORY === 'hash'
|
||||
? createWebHashHistory(import.meta.env.VITE_BASE)
|
||||
: createWebHistory(import.meta.env.VITE_BASE),
|
||||
// 应该添加到路由的初始路由列表。
|
||||
routes,
|
||||
scrollBehavior: () => ({ left: 0, top: 0 }),
|
||||
// 是否应该禁止尾部斜杠。
|
||||
// strict: true,
|
||||
});
|
||||
|
||||
const resetRoutes = () => resetStaticRoutes(router, routes);
|
||||
|
||||
// 创建路由守卫
|
||||
createRouterGuard(router);
|
||||
|
||||
export { resetRoutes, router };
|
|
@ -0,0 +1,144 @@
|
|||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { DEFAULT_HOME_PATH } from '@vben/constants';
|
||||
|
||||
import { AuthPageLayout, BasicLayout, IFrameView } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
import Login from '#/views/_core/authentication/login.vue';
|
||||
|
||||
/** 全局404页面 */
|
||||
const fallbackNotFoundRoute: RouteRecordRaw = {
|
||||
component: () => import('#/views/_core/fallback/not-found.vue'),
|
||||
meta: {
|
||||
hideInBreadcrumb: true,
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
title: '404',
|
||||
},
|
||||
name: 'FallbackNotFound',
|
||||
path: '/:path(.*)*',
|
||||
};
|
||||
|
||||
/** 基本路由,这些路由是必须存在的 */
|
||||
const coreRoutes: RouteRecordRaw[] = [
|
||||
{
|
||||
meta: {
|
||||
title: 'Root',
|
||||
},
|
||||
name: 'Root',
|
||||
path: '/',
|
||||
redirect: DEFAULT_HOME_PATH,
|
||||
},
|
||||
{
|
||||
component: AuthPageLayout,
|
||||
meta: {
|
||||
title: 'Authentication',
|
||||
},
|
||||
name: 'Authentication',
|
||||
path: '/auth',
|
||||
children: [
|
||||
{
|
||||
name: 'Login',
|
||||
path: 'login',
|
||||
component: Login,
|
||||
meta: {
|
||||
title: $t('page.core.login'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'CodeLogin',
|
||||
path: 'code-login',
|
||||
component: () => import('#/views/_core/authentication/code-login.vue'),
|
||||
meta: {
|
||||
title: $t('page.core.codeLogin'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'QrCodeLogin',
|
||||
path: 'qrcode-login',
|
||||
component: () =>
|
||||
import('#/views/_core/authentication/qrcode-login.vue'),
|
||||
meta: {
|
||||
title: $t('page.core.qrcodeLogin'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ForgetPassword',
|
||||
path: 'forget-password',
|
||||
component: () =>
|
||||
import('#/views/_core/authentication/forget-password.vue'),
|
||||
meta: {
|
||||
title: $t('page.core.forgetPassword'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Register',
|
||||
path: 'register',
|
||||
component: () => import('#/views/_core/authentication/register.vue'),
|
||||
meta: {
|
||||
title: $t('page.core.register'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
component: IFrameView,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: 210,
|
||||
title: 'iframe',
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
},
|
||||
name: 'IFrame',
|
||||
path: '/iframe',
|
||||
children: [
|
||||
{
|
||||
name: 'MeetingStandingBook',
|
||||
path: '/iframe/meeting/standing-book',
|
||||
component: () => import('#/views/meeting/standing-book/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '供热公司网络生产会议系统-会议查询篇',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'MeetingStart',
|
||||
path: '/iframe/meeting/start/:id?',
|
||||
component: () => import('#/views/meeting/start/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '会议发起',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'DutyStandingBook',
|
||||
path: '/iframe/duty/standing-book',
|
||||
component: () => import('#/views/duty/standing-book/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '值班信息栏',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractInfo',
|
||||
path: '/iframe/contract/info',
|
||||
component: () => import('#/views/contract/iframe-info/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同明细信息',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export { coreRoutes, fallbackNotFoundRoute };
|
|
@ -0,0 +1,31 @@
|
|||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { mergeRouteModules, traverseTreeValues } from '@vben/utils';
|
||||
|
||||
import { coreRoutes, fallbackNotFoundRoute } from './core';
|
||||
|
||||
const dynamicRouteFiles = import.meta.glob('./modules/**/*.ts', {
|
||||
eager: true,
|
||||
});
|
||||
|
||||
// 有需要可以自行打开注释,并创建文件夹
|
||||
// const externalRouteFiles = import.meta.glob('./external/**/*.ts', { eager: true });
|
||||
|
||||
/** 动态路由 */
|
||||
const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles);
|
||||
|
||||
/** 外部路由列表,访问这些页面可以不需要Layout,可能用于内嵌在别的系统 */
|
||||
// const externalRoutes: RouteRecordRaw[] = mergeRouteModules(externalRouteFiles);
|
||||
const externalRoutes: RouteRecordRaw[] = [];
|
||||
|
||||
/** 路由列表,由基本路由+静态路由组成 */
|
||||
const routes: RouteRecordRaw[] = [
|
||||
...coreRoutes,
|
||||
...externalRoutes,
|
||||
fallbackNotFoundRoute,
|
||||
];
|
||||
|
||||
/** 基本路由列表,这些路由不需要进入权限拦截 */
|
||||
const coreRouteNames = traverseTreeValues(coreRoutes, (route) => route.name);
|
||||
|
||||
export { coreRouteNames, dynamicRoutes, routes };
|
|
@ -0,0 +1,438 @@
|
|||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: 2000,
|
||||
title: '合同管理',
|
||||
},
|
||||
name: 'Contract',
|
||||
path: '/contract',
|
||||
children: [
|
||||
{
|
||||
name: 'ContractConfig',
|
||||
path: '/contract/config',
|
||||
component: () => import('#/views/contract/config/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同配置',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractApproval',
|
||||
path: '/contract/approval',
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同立项',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractApprovalEdit',
|
||||
path: '/contract/approval/edit/:id?',
|
||||
beforeEnter: (e) => {
|
||||
if (e.params.id && e.params.id === ':id') {
|
||||
e.params.id = ''
|
||||
e.fullPath = '/contract/approval/edit'
|
||||
}
|
||||
},
|
||||
component: () => import('#/views/contract/approval/edit/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '立项申报',
|
||||
activePath: '/contract/approval/edit/:id?'
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractApprovalTodo',
|
||||
path: '/contract/approval/todo',
|
||||
component: () => import('#/views/contract/approval/todo/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '立项提示',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractApprovalList',
|
||||
path: '/contract/approval/list',
|
||||
component: () => import('#/views/contract/approval/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '立项查询',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractApprovalSigningBasis',
|
||||
path: '/contract/approval/signing-basis',
|
||||
component: () => import('#/views/contract/approval/signing-basis/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '签约依据维护',
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'ContractBusiness',
|
||||
path: '/contract/business',
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同选商',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractBusiness',
|
||||
path: '/contract/business/edit/:id?',
|
||||
beforeEnter: (e) => {
|
||||
if (e.params.id && e.params.id === ':id') {
|
||||
e.params.id = ''
|
||||
e.fullPath = '/contract/business/edit'
|
||||
}
|
||||
},
|
||||
component: () => import('#/views/contract/business/edit/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '选商填报',
|
||||
activePath: '/contract/business/edit/:id?'
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractBusinessTodo',
|
||||
path: '/contract/business/todo',
|
||||
component: () => import('#/views/contract/business/todo/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '选商提示',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractBusinessList',
|
||||
path: '/contract/business/list',
|
||||
component: () => import('#/views/contract/business/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '选商查询',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'ContractDeclaration',
|
||||
path: '/contract/declaration',
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同申报',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractDeclarationTodo',
|
||||
path: '/contract/declaration/todo',
|
||||
component: () => import('#/views/contract/declaration/todo/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '申报提示',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractDeclarationList',
|
||||
path: '/contract/declaration/list',
|
||||
component: () => import('#/views/contract/declaration/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '申报查询',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractDeclarationPrint',
|
||||
path: '/contract/declaration/print',
|
||||
component: () => import('#/views/contract/declaration/print/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同打印',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'ContractAudit',
|
||||
path: '/contract/audit',
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同审批',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractAuditTodo',
|
||||
path: '/contract/audit/todo',
|
||||
component: () => import('#/views/contract/audit/todo/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '审批提示',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractAuditList',
|
||||
path: '/contract/audit/list',
|
||||
component: () => import('#/views/contract/audit/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '审批查询',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'ContractSign',
|
||||
path: '/contract/sign',
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同签订',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractSignTodo',
|
||||
path: '/contract/sign/todo',
|
||||
component: () => import('#/views/contract/sign/todo/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '签订提示',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractSignList',
|
||||
path: '/contract/sign/list',
|
||||
component: () => import('#/views/contract/sign/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '签订查询',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'ContractPerform',
|
||||
path: '/contract/perform',
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同履行',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractPerformTodo',
|
||||
path: '/contract/perform/todo',
|
||||
component: () => import('#/views/contract/perform/todo/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '履行提示',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractPerformList',
|
||||
path: '/contract/perform/list',
|
||||
component: () => import('#/views/contract/perform/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '履行查询',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractPerformResult',
|
||||
path: '/contract/perform/result',
|
||||
component: () => import('#/views/contract/perform/result/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '履行结果填报',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractPerformTemporaryArchive',
|
||||
path: '/contract/perform/temporary-archive',
|
||||
component: () => import('#/views/contract/perform/temporary-archive/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '临时归档',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'ContractArchive',
|
||||
path: '/contract/archive',
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同归档',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractArchiveTodoArchive',
|
||||
path: '/contract/archive/todo/archive',
|
||||
component: () => import('#/views/contract/archive/todo/archive.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同归档',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractArchiveTodoRetracement',
|
||||
path: '/contract/archive/todo/retracement',
|
||||
component: () => import('#/views/contract/archive/todo/retracement.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同回档',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractArchiveList',
|
||||
path: '/contract/archive/list',
|
||||
component: () => import('#/views/contract/archive/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '归档查询',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'ContractSignAuthorization',
|
||||
path: '/contract/sign-authorization',
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '签约授权管理',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractSignAuthorizationEdit',
|
||||
path: '/contract/sign-authorization/edit/:id?',
|
||||
beforeEnter: (e) => {
|
||||
if (e.params.id && e.params.id === ':id') {
|
||||
e.params.id = ''
|
||||
e.fullPath = '/contract/sign-authorization/edit'
|
||||
}
|
||||
},
|
||||
component: () => import('#/views/contract/sign-authorization/edit/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '签约授权申报',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractSignAuthorizationList',
|
||||
path: '/contract/sign-authorization/list',
|
||||
component: () => import('#/views/contract/sign-authorization/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '签约授权查询',
|
||||
},
|
||||
},
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'ContractCompany',
|
||||
path: '/contract/company',
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同相对人',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractCompanyEdit',
|
||||
path: '/contract/company/edit/:id?',
|
||||
beforeEnter: (e) => {
|
||||
if (e.params.id && e.params.id === ':id') {
|
||||
e.params.id = ''
|
||||
e.fullPath = '/contract/company/edit'
|
||||
}
|
||||
},
|
||||
component: () => import('#/views/contract/company/edit/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '相对人录入维护',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractCompanyList',
|
||||
path: '/contract/company/list',
|
||||
component: () => import('#/views/contract/company/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '相对人查询',
|
||||
},
|
||||
},
|
||||
|
||||
],
|
||||
},
|
||||
// {
|
||||
// name: 'ContractStatistic',
|
||||
// path: '/contract/statistic',
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '统计分析',
|
||||
// },
|
||||
// children: [
|
||||
// {
|
||||
// name: 'ContractStatisticAnalysis',
|
||||
// path: '/contract/statistic/analysis',
|
||||
// beforeEnter: (e) => {
|
||||
// if (e.params.id && e.params.id === ':id') {
|
||||
// e.params.id = ''
|
||||
// e.fullPath = '/contract/company/edit'
|
||||
// }
|
||||
// },
|
||||
// component: () => import('#/views/contract/company/edit/index.vue'),
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '统计分析',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: 'ContractStatisticAbrogateList',
|
||||
// path: '/contract/statistic/abrogate-list',
|
||||
// component: () => import('#/views/contract/company/list/index.vue'),
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '废除查询',
|
||||
// },
|
||||
// },
|
||||
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// name: 'ContractPrint',
|
||||
// path: '/contract/statistic',
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '统计分析',
|
||||
// },
|
||||
// children: [
|
||||
// {
|
||||
// name: 'ContractPrintBusiness',
|
||||
// path: '/contract/print/business',
|
||||
// component: () => import('#/views/contract/company/edit/index.vue'),
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '统计分析',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: 'ContractPrintAbrogateList',
|
||||
// path: '/contract/print/abrogate-list',
|
||||
// component: () => import('#/views/contract/company/list/index.vue'),
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '废除查询',
|
||||
// },
|
||||
// },
|
||||
|
||||
// ],
|
||||
// },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
|
@ -0,0 +1,49 @@
|
|||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: -1,
|
||||
title: '首页',
|
||||
},
|
||||
name: 'Dashboard',
|
||||
path: '/home',
|
||||
children: [
|
||||
{
|
||||
name: 'home',
|
||||
path: '/home',
|
||||
component: () => import('#/views/dashboard/home/index.vue'),
|
||||
meta: {
|
||||
affixTab: true,
|
||||
hideInMenu: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '首页',
|
||||
},
|
||||
},
|
||||
// {
|
||||
// name: 'Analytics',
|
||||
// path: '/analytics',
|
||||
// component: () => import('#/views/dashboard/analytics/index.vue'),
|
||||
// meta: {
|
||||
// affixTab: true,
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: $t('page.dashboard.analytics'),
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: 'Workspace',
|
||||
// path: '/workspace',
|
||||
// component: () => import('#/views/dashboard/workspace/index.vue'),
|
||||
// meta: {
|
||||
// title: $t('page.dashboard.workspace'),
|
||||
// },
|
||||
// },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
|
@ -0,0 +1,276 @@
|
|||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: 110,
|
||||
title: '督查督办',
|
||||
},
|
||||
name: 'Supervise',
|
||||
path: '/supervise',
|
||||
children: [
|
||||
{
|
||||
name: 'SuperviseEdit',
|
||||
path: '/supervise/edit/:id?',
|
||||
beforeEnter: (e) => {
|
||||
if (e.params.id && e.params.id === ':id') {
|
||||
e.params.id = ''
|
||||
e.fullPath = '/supervise/edit'
|
||||
}
|
||||
},
|
||||
component: () => import('#/views/supervise/edit/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '立项填报',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'SuperviseList',
|
||||
path: '/supervise/list',
|
||||
component: () => import('#/views/supervise/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '立项查询',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'SuperviseFeedback',
|
||||
path: '/supervise/feedback',
|
||||
component: () => import('#/views/supervise/feedback/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '执行与反馈',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'SuperviseSummary',
|
||||
path: '/supervise/summary',
|
||||
component: () => import('#/views/supervise/summary/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '报表汇总',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: 210,
|
||||
title: '会议管理',
|
||||
},
|
||||
name: 'Meeting',
|
||||
path: '/meeting',
|
||||
children: [
|
||||
{
|
||||
name: 'MeetingEdit',
|
||||
path: '/meeting/edit/:id?',
|
||||
beforeEnter: (e) => {
|
||||
if (e.params.id && e.params.id === ':id') {
|
||||
e.params.id = ''
|
||||
e.fullPath = '/meeting/edit'
|
||||
}
|
||||
},
|
||||
component: () => import('#/views/meeting/edit/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '会议填报',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'MeetingList',
|
||||
path: '/meeting/list',
|
||||
component: () => import('#/views/meeting/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '会议查询',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: 300,
|
||||
title: '出差管理',
|
||||
},
|
||||
name: 'BussinessTrip',
|
||||
path: '/bussiness-trip',
|
||||
children: [
|
||||
{
|
||||
name: 'BussinessTripEdit',
|
||||
path: '/bussiness-trip/edit/:id?',
|
||||
beforeEnter: (e) => {
|
||||
if (e.params.id && e.params.id === ':id') {
|
||||
e.params.id = ''
|
||||
e.fullPath = '/bussiness-trip/edit'
|
||||
}
|
||||
},
|
||||
component: () => import('#/views/bussiness-trip/edit/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '出差填报',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'BussinessTripTodo',
|
||||
path: '/bussiness-trip/todo',
|
||||
component: () => import('#/views/bussiness-trip/todo/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '出差提示',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'BussinessTripList',
|
||||
path: '/bussiness-trip/list',
|
||||
component: () => import('#/views/bussiness-trip/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '出差查询',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: 400,
|
||||
title: '办公用品管理',
|
||||
},
|
||||
name: 'OfficeSupplies',
|
||||
path: '/office-supplies',
|
||||
children: [
|
||||
{
|
||||
name: 'OfficeSuppliesApply',
|
||||
path: '/office-supplies/apply',
|
||||
component: () => import('#/views/office-supplies/apply/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '用品申请',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'OfficeSuppliesSettle',
|
||||
path: '/office-supplies/settle',
|
||||
component: () => import('#/views/office-supplies/settle/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '结算清单',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'OfficeSuppliesAudit',
|
||||
path: '/office-supplies/audit',
|
||||
component: () => import('#/views/office-supplies/audit/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '用品审核',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'OfficeSuppliesInventory',
|
||||
path: '/office-supplies/inventory',
|
||||
component: () => import('#/views/office-supplies/inventory/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '用品库存',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: 300,
|
||||
title: '值班管理',
|
||||
},
|
||||
name: 'Duty',
|
||||
path: '/duty/list',
|
||||
children: [
|
||||
{
|
||||
name: 'DutyList',
|
||||
path: '/duty/list',
|
||||
component: () => import('#/views/duty/list/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '值班管理',
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: 300,
|
||||
title: '订餐管理',
|
||||
},
|
||||
name: 'canteen',
|
||||
path: '/canteen',
|
||||
children: [
|
||||
{
|
||||
name: 'canteen_config',
|
||||
path: '/canteen/config',
|
||||
component: () => import('#/views/canteen/config/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '订餐配置',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'canteen_orderfood',
|
||||
path: '/canteen/orderfood',
|
||||
component: () => import('#/views/canteen/orderfood/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '订餐',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'canteen_recipe',
|
||||
path: '/canteen/recipe',
|
||||
component: () => import('#/views/canteen/recipe/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '食谱',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'canteen_collect',
|
||||
path: '/canteen/collect',
|
||||
component: () => import('#/views/canteen/collect/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '订餐汇总',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'canteen_statistics',
|
||||
path: '/canteen/statistics',
|
||||
component: () => import('#/views/canteen/statistics/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '订餐统计',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
|
@ -0,0 +1,29 @@
|
|||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: 10,
|
||||
title: '系统管理',
|
||||
},
|
||||
name: 'System',
|
||||
path: '/system',
|
||||
children: [
|
||||
{
|
||||
name: 'Dict',
|
||||
path: '/system/dict',
|
||||
component: () => import('#/views/system/dict/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '字典管理',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
|
@ -0,0 +1,51 @@
|
|||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: -1,
|
||||
title: '用户中心',
|
||||
},
|
||||
name: 'User',
|
||||
path: '/user',
|
||||
children: [
|
||||
{
|
||||
name: 'UserTodo',
|
||||
path: '/user/todo',
|
||||
component: () => import('#/views/user-center/todo/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '消息通知',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'UserCenter',
|
||||
path: '/user/center',
|
||||
component: () => import('#/views/user-center/center/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '个人中心',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'About',
|
||||
path: '/about',
|
||||
component: () => import('#/views/_core/about/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '关于',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
|
@ -0,0 +1,131 @@
|
|||
import type { LoginAndRegisterParams } from '@vben/common-ui';
|
||||
import type { UserInfo } from '@vben/types';
|
||||
|
||||
import { ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
|
||||
import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
|
||||
|
||||
import { notification } from 'ant-design-vue';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
import { getUserInfoApi, loginApi } from '#/api/system/auth';
|
||||
|
||||
import { $t } from '#/locales';
|
||||
|
||||
export const useAuthStore = defineStore('auth', () => {
|
||||
const accessStore = useAccessStore();
|
||||
const userStore = useUserStore();
|
||||
const router = useRouter();
|
||||
|
||||
const loginLoading = ref(false);
|
||||
let loginInfo = localStorage.getItem('loginInfo') || '{}';
|
||||
/**
|
||||
* 异步处理登录操作
|
||||
* Asynchronously handle the login process
|
||||
* @param params 登录表单数据
|
||||
*/
|
||||
async function authLogin(
|
||||
params: LoginAndRegisterParams,
|
||||
onSuccess?: () => Promise<void> | void,
|
||||
) {
|
||||
// 异步处理用户登录操作并获取 accessToken
|
||||
let userInfo: null | UserInfo = null;
|
||||
try {
|
||||
loginLoading.value = true;
|
||||
if(params.username == 'Admin.itl' || params._isSkip){
|
||||
}else{
|
||||
params.username = params.username + '.RL'
|
||||
}
|
||||
|
||||
const loginRes = await loginApi({
|
||||
...params,
|
||||
appId: 'PLRL',
|
||||
appName: 'ERP管理系统',
|
||||
appSecret: 'r1og4wiyrrvr4qvw2aafhgvy',
|
||||
});
|
||||
console.log(loginRes);
|
||||
if (params._isSkip) {
|
||||
loginRes._isSkip = params._isSkip
|
||||
}
|
||||
|
||||
loginInfo = JSON.stringify(loginRes);
|
||||
localStorage.setItem('loginInfo', loginInfo);
|
||||
|
||||
const { accessToken } = loginRes;
|
||||
// 如果成功获取到 accessToken
|
||||
if (accessToken) {
|
||||
accessStore.setAccessToken(accessToken);
|
||||
|
||||
// 获取用户信息并存储到 accessStore 中
|
||||
const [fetchUserInfoResult] = await Promise.all([fetchUserInfo()]);
|
||||
|
||||
userInfo = fetchUserInfoResult;
|
||||
if (params._isSkip) {
|
||||
userInfo._isSkip = params._isSkip
|
||||
}
|
||||
userStore.setUserInfo(userInfo);
|
||||
|
||||
if (accessStore.loginExpired) {
|
||||
accessStore.setLoginExpired(false);
|
||||
} else {
|
||||
onSuccess
|
||||
? await onSuccess?.()
|
||||
: await router.push(userInfo.homePath || DEFAULT_HOME_PATH);
|
||||
}
|
||||
|
||||
if (userInfo?.realName) {
|
||||
notification.success({
|
||||
description: `${$t('authentication.loginSuccessDesc')}:${userInfo?.realName}`,
|
||||
duration: 3,
|
||||
message: $t('authentication.loginSuccess'),
|
||||
});
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
loginLoading.value = false;
|
||||
}
|
||||
|
||||
return {
|
||||
userInfo,
|
||||
};
|
||||
}
|
||||
|
||||
async function logout(redirect: boolean = true) {
|
||||
// await logoutApi();
|
||||
resetAllStores();
|
||||
accessStore.setLoginExpired(false);
|
||||
|
||||
// 回登陆页带上当前路由地址
|
||||
await router.replace({
|
||||
path: LOGIN_PATH,
|
||||
query: redirect
|
||||
? {
|
||||
redirect: encodeURIComponent(router.currentRoute.value.fullPath),
|
||||
}
|
||||
: {},
|
||||
});
|
||||
}
|
||||
|
||||
async function fetchUserInfo() {
|
||||
let userInfo: null | UserInfo = null;
|
||||
userInfo = await getUserInfoApi();
|
||||
userInfo = { ...JSON.parse(loginInfo), ...userInfo }
|
||||
userStore.setUserInfo(userInfo);
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
function $reset() {
|
||||
localStorage.removeItem('loginInfo');
|
||||
loginLoading.value = false;
|
||||
}
|
||||
|
||||
return {
|
||||
$reset,
|
||||
authLogin,
|
||||
fetchUserInfo,
|
||||
loginLoading,
|
||||
logout,
|
||||
};
|
||||
});
|
|
@ -1,8 +1,8 @@
|
|||
import { defineStore } from 'pinia';
|
||||
import { computed, ref } from 'vue';
|
||||
import { getDictDataList } from '@/api/system/dict';
|
||||
import { store } from '@/store';
|
||||
import dataModule from '@/utils/dict/static.data'
|
||||
// import { getDictDataList } from '@/api/system/dict';
|
||||
import Apis from '#/api'
|
||||
import dataModule from '#/utils/dict/static.data'
|
||||
|
||||
const DICT_STORAGE_KEY = 'DICT_KEY';
|
||||
|
||||
|
@ -38,7 +38,7 @@ export const useDictStore = defineStore(
|
|||
*/
|
||||
const setDictMap = async (): Promise<boolean> => {
|
||||
try {
|
||||
const data = await getDictDataList({ pageNum: 1, pageSize: 10000 });
|
||||
const data = await Apis.dictData.get_page({ params: { pageNum: 1, pageSize: 10000 } });
|
||||
const dictDataMap: Record<string, DictDataVO[]> = {};
|
||||
|
||||
// 处理静态字典数据
|
||||
|
@ -159,6 +159,10 @@ export const useDictStore = defineStore(
|
|||
return info.label;
|
||||
};
|
||||
|
||||
function $reset() {
|
||||
// loginLoading.value = false;
|
||||
}
|
||||
|
||||
return {
|
||||
initDict,
|
||||
dictMap,
|
||||
|
@ -170,14 +174,8 @@ export const useDictStore = defineStore(
|
|||
getDictData,
|
||||
getDictInfo,
|
||||
getDictDataInfo,
|
||||
getDictDataLabel
|
||||
getDictDataLabel,
|
||||
$reset
|
||||
};
|
||||
},
|
||||
{
|
||||
persist: true
|
||||
}
|
||||
);
|
||||
|
||||
export function useDictStoreWithOut() {
|
||||
return useDictStore(store);
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export * from './auth';
|
||||
export * from './dict'
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
/** 数据字典工具类 */
|
||||
import { useDictStoreWithOut } from '@/store/modules/dict';
|
||||
import { useDictStore } from '#/store/dict';
|
||||
|
||||
export * from './shared';
|
||||
|
||||
const dictStore = useDictStoreWithOut();
|
||||
const dictStore = useDictStore();
|
||||
|
||||
/**
|
||||
* 获取 dictType 对应的数据字典数组
|
||||
|
@ -80,7 +80,7 @@ export function getDictObj(dictType: string, value: any): DictDataType | null {
|
|||
export function getDictDefaultObj(dictType: string): DictDataType | null {
|
||||
const dictOptions: DictDataType[] = getDictDatas(dictType);
|
||||
if (dictOptions) {
|
||||
return dictOptions.find((dict: DictDataType) => dict.isDefault === true) || dictOptions[0];
|
||||
return dictOptions.find((dict: DictDataType) => dict.isDefault == '1') || dictOptions[0];
|
||||
} else {
|
||||
return null;
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
import { message, type UploadProps } from "ant-design-vue";
|
||||
import Apis from '#/api';
|
||||
|
||||
export class FileUploader {
|
||||
|
||||
|
||||
fileList = [] as UploadProps['fileList'];
|
||||
uploading = false;
|
||||
constructor(params: any) {
|
||||
|
||||
}
|
||||
|
||||
select = async (fileUuids: string) => {
|
||||
return new Promise<void>(async (resolve, reject) => {
|
||||
Apis.attachment.get_list({
|
||||
params: { uuid: fileUuids }
|
||||
}).then((data) => {
|
||||
let files = [] as UploadProps['fileList'];
|
||||
for (const element of data.rows) {
|
||||
files?.push({
|
||||
uid: element.fileUuid,
|
||||
name: element.fileName,
|
||||
status: 'done',
|
||||
url: element.fileUrl,
|
||||
})
|
||||
}
|
||||
resolve(files)
|
||||
}).catch(e => {
|
||||
reject()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
remove: UploadProps['onRemove'] = file => {
|
||||
if (this.fileList) {
|
||||
const index = this.fileList.indexOf(file);
|
||||
const newFileList = this.fileList.slice();
|
||||
newFileList.splice(index, 1);
|
||||
this.fileList = newFileList;
|
||||
}
|
||||
};
|
||||
|
||||
upload = async (files?: UploadProps['fileList'], data?: any) => {
|
||||
return new Promise<void>(async (resolve, reject) => {
|
||||
if (this.fileList) {
|
||||
const formData = new FormData();
|
||||
|
||||
if (data && Object.keys(data).length) {
|
||||
Object.keys(data).forEach((key) => {
|
||||
formData.append(key, data[key]);
|
||||
});
|
||||
}
|
||||
|
||||
let file = files ? files : this.fileList;
|
||||
let alreadyUploaded = [] as string[];
|
||||
file.forEach((file: UploadProps['fileList'][number]) => {
|
||||
if (file.originFileObj) {
|
||||
formData.append('files', file.originFileObj as any);
|
||||
} else {
|
||||
alreadyUploaded.push(file.uid)
|
||||
}
|
||||
});
|
||||
this.uploading = true;
|
||||
|
||||
// You can use any AJAX library you like
|
||||
try {
|
||||
|
||||
this.fileList = [];
|
||||
this.uploading = false;
|
||||
let files = []
|
||||
for (const element of alreadyUploaded) {
|
||||
files.push({
|
||||
fileUuid: element,
|
||||
})
|
||||
}
|
||||
|
||||
const filesCount = formData.getAll('files').length;
|
||||
if (filesCount > 0) {
|
||||
let data = await Apis.attachment.post_uploads({
|
||||
data: formData,
|
||||
})
|
||||
files = files.concat(data.rows)
|
||||
message.success('上传成功.');
|
||||
}
|
||||
resolve(files || [])
|
||||
|
||||
} catch (error) {
|
||||
this.uploading = false;
|
||||
reject()
|
||||
message.error('上传失败.');
|
||||
} finally {
|
||||
this.uploading = false;
|
||||
}
|
||||
|
||||
}
|
||||
reject()
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,45 +1,7 @@
|
|||
import { h, unref } from 'vue';
|
||||
import type { App, Component, Plugin } from 'vue';
|
||||
import { NIcon, NTag } from 'naive-ui';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { deepClone } from '@vue/devtools-shared';
|
||||
import { PageEnum } from '@/enums/pageEnum';
|
||||
import { isObject } from './is';
|
||||
/** render 图标 */
|
||||
export function renderIcon(icon) {
|
||||
return () => h(NIcon, null, { default: () => h(icon) });
|
||||
}
|
||||
/** font 图标(Font class) */
|
||||
export function renderFontClassIcon(icon: string, iconName = 'iconfont') {
|
||||
return () => h('span', { class: [iconName, icon] });
|
||||
}
|
||||
/** font 图标(Unicode) */
|
||||
export function renderUnicodeIcon(icon: string, iconName = 'iconfont') {
|
||||
return () => h('span', { class: [iconName], innerHTML: icon });
|
||||
}
|
||||
/** font svg 图标 */
|
||||
export function renderfontsvg(icon) {
|
||||
return () =>
|
||||
h(NIcon, null, {
|
||||
default: () => h('svg', { class: `icon`, 'aria-hidden': 'true' }, h('use', { 'xlink:href': `#${icon}` }))
|
||||
});
|
||||
}
|
||||
import { cloneDeep, isObject } from 'lodash-es';
|
||||
|
||||
/** render new Tag */
|
||||
const newTagColors = { color: '#f90', textColor: '#fff', borderColor: '#f90' };
|
||||
export function renderNew(type = 'warning', text = 'New', color: object = newTagColors) {
|
||||
return () =>
|
||||
h(
|
||||
NTag as any,
|
||||
{
|
||||
type,
|
||||
round: true,
|
||||
size: 'small',
|
||||
color
|
||||
},
|
||||
{ default: () => text }
|
||||
);
|
||||
}
|
||||
|
||||
/** 递归组装菜单格式 */
|
||||
export function generatorMenu(routerMap: Array<any>) {
|
||||
|
@ -110,16 +72,6 @@ export function isRootRouter(item) {
|
|||
return item.meta?.alwaysShow != true && item?.children?.filter(item => !item?.meta?.hidden)?.length === 1;
|
||||
}
|
||||
|
||||
/** 排除Router */
|
||||
export function filterRouter(routerMap: Array<any>) {
|
||||
return routerMap.filter(item => {
|
||||
return (
|
||||
(item.meta?.hidden || false) != true &&
|
||||
!['/:path(.*)*', '/', PageEnum.REDIRECT, PageEnum.BASE_LOGIN].includes(item.path)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export const withInstall = <T extends Component>(component: T, alias?: string) => {
|
||||
const comp = component as any;
|
||||
comp.install = (app: App) => {
|
||||
|
@ -218,7 +170,7 @@ export function isUrl(url: string) {
|
|||
* @returns {Array} treeData 树形结构
|
||||
*/
|
||||
export function arrayToTree(originalArrayData, treeProps) {
|
||||
const arrayData = deepClone(originalArrayData);
|
||||
const arrayData = cloneDeep(originalArrayData);
|
||||
let { id = '_id', parent_id = 'parent_id', children = 'children', deleteParentId = false, need_field } = treeProps;
|
||||
const result = [];
|
||||
const temp = {};
|
|
@ -0,0 +1,3 @@
|
|||
# \_core
|
||||
|
||||
此目录包含应用程序正常运行所需的基本视图。这些视图是应用程序布局中使用的视图。
|
|
@ -0,0 +1,9 @@
|
|||
<script lang="ts" setup>
|
||||
import { About } from '@vben/common-ui';
|
||||
|
||||
defineOptions({ name: 'About' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<About />
|
||||
</template>
|
|
@ -0,0 +1,30 @@
|
|||
<script lang="ts" setup>
|
||||
import type { LoginCodeParams } from '@vben/common-ui';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { AuthenticationCodeLogin } from '@vben/common-ui';
|
||||
import { LOGIN_PATH } from '@vben/constants';
|
||||
|
||||
defineOptions({ name: 'CodeLogin' });
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
/**
|
||||
* 异步处理登录操作
|
||||
* Asynchronously handle the login process
|
||||
* @param values 登录表单数据
|
||||
*/
|
||||
async function handleLogin(values: LoginCodeParams) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(values);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthenticationCodeLogin
|
||||
:loading="loading"
|
||||
:login-path="LOGIN_PATH"
|
||||
@submit="handleLogin"
|
||||
/>
|
||||
</template>
|
|
@ -0,0 +1,23 @@
|
|||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { AuthenticationForgetPassword } from '@vben/common-ui';
|
||||
import { LOGIN_PATH } from '@vben/constants';
|
||||
|
||||
defineOptions({ name: 'ForgetPassword' });
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
function handleSubmit(value: string) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('reset email:', value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthenticationForgetPassword
|
||||
:loading="loading"
|
||||
:login-path="LOGIN_PATH"
|
||||
@submit="handleSubmit"
|
||||
/>
|
||||
</template>
|
|
@ -0,0 +1,37 @@
|
|||
<script lang="ts" setup>
|
||||
import { AuthenticationLogin } from "@vben/common-ui";
|
||||
|
||||
import { useAuthStore } from "#/store";
|
||||
|
||||
defineOptions({ name: "Login" });
|
||||
|
||||
const authStore = useAuthStore();
|
||||
|
||||
const isDev = import.meta.env.DEV;
|
||||
function mockLogin(username: string, password: string, isSkip: boolean = true) {
|
||||
authStore.authLogin({
|
||||
username,
|
||||
password,
|
||||
_isSkip: isSkip,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthenticationLogin
|
||||
:loading="authStore.loginLoading"
|
||||
password-placeholder=""
|
||||
username-placeholder=""
|
||||
@submit="authStore.authLogin"
|
||||
/>
|
||||
|
||||
<div v-if="isDev">
|
||||
<p class="text-center">快速登录</p>
|
||||
<a-space>
|
||||
<a-button @click="mockLogin('Admin.itl', 'ABC123')">超级管理员</a-button>
|
||||
<a-button @click="mockLogin('zhangxs.itl', 'Rlgs!6243910')">zxs</a-button>
|
||||
<a-button @click="mockLogin('zengp.itl', 'Rlgs!6243910')">zp</a-button>
|
||||
<a-button @click="mockLogin('rlqym', 'Rlgs!6243910', false)">rlqym</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,10 @@
|
|||
<script lang="ts" setup>
|
||||
import { AuthenticationQrCodeLogin } from '@vben/common-ui';
|
||||
import { LOGIN_PATH } from '@vben/constants';
|
||||
|
||||
defineOptions({ name: 'QrCodeLogin' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthenticationQrCodeLogin :login-path="LOGIN_PATH" />
|
||||
</template>
|
|
@ -0,0 +1,25 @@
|
|||
<script lang="ts" setup>
|
||||
import type { LoginAndRegisterParams } from '@vben/common-ui';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { AuthenticationRegister } from '@vben/common-ui';
|
||||
import { LOGIN_PATH } from '@vben/constants';
|
||||
|
||||
defineOptions({ name: 'Register' });
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
function handleSubmit(value: LoginAndRegisterParams) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('register submit:', value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthenticationRegister
|
||||
:loading="loading"
|
||||
:login-path="LOGIN_PATH"
|
||||
@submit="handleSubmit"
|
||||
/>
|
||||
</template>
|
|
@ -0,0 +1,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { Fallback } from '@vben/common-ui';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Fallback status="coming-soon" />
|
||||
</template>
|
|
@ -0,0 +1,9 @@
|
|||
<script lang="ts" setup>
|
||||
import { Fallback } from '@vben/common-ui';
|
||||
|
||||
defineOptions({ name: 'Fallback403Demo' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Fallback status="403" />
|
||||
</template>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue