第一次上传
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
# 表示所有文件适用
|
||||
[*]
|
||||
charset = utf-8 # 设置文件字符集为 utf-8
|
||||
end_of_line = lf # 控制换行类型(lf | cr | crlf)
|
||||
indent_style = space # 缩进风格(tab | space)
|
||||
indent_size = 2 # 缩进大小
|
||||
insert_final_newline = true # 始终在文件末尾插入一个新行
|
||||
|
||||
# 表示仅 md 文件适用以下规则
|
||||
[*.md]
|
||||
max_line_length = off # 关闭最大行长度限制
|
||||
trim_trailing_whitespace = false # 关闭末尾空格修剪
|
||||
@@ -0,0 +1,16 @@
|
||||
# 应用端口
|
||||
VITE_APP_PORT=8090
|
||||
# 项目名称
|
||||
VITE_APP_TITLE=代理平台管理后台
|
||||
# 代理前缀
|
||||
VITE_APP_BASE_API=/dev-api
|
||||
|
||||
# 接口地址
|
||||
# VITE_APP_API_URL=https://api.youlai.tech # 线上
|
||||
VITE_APP_API_URL=http://localhost:8000 # 本地
|
||||
|
||||
# 启用 Mock 服务(true:开启 false:关闭)
|
||||
VITE_MOCK_DEV_SERVER=false
|
||||
|
||||
# 多租户开关(true:开启 false:关闭)
|
||||
VITE_APP_TENANT_ENABLED=false
|
||||
@@ -0,0 +1,7 @@
|
||||
# 代理前缀
|
||||
VITE_APP_BASE_API = '/prod-api'
|
||||
# 项目名称
|
||||
VITE_APP_TITLE=代理平台管理后台
|
||||
|
||||
# 多租户开关(true/false)
|
||||
VITE_APP_TENANT_ENABLED=false
|
||||
@@ -0,0 +1,316 @@
|
||||
{
|
||||
"globals": {
|
||||
"Component": true,
|
||||
"ComponentPublicInstance": true,
|
||||
"ComputedRef": true,
|
||||
"EffectScope": true,
|
||||
"ElMessage": true,
|
||||
"ElMessageBox": true,
|
||||
"ElNotification": true,
|
||||
"InjectionKey": true,
|
||||
"PropType": true,
|
||||
"Ref": true,
|
||||
"VNode": true,
|
||||
"asyncComputed": true,
|
||||
"autoResetRef": true,
|
||||
"computed": true,
|
||||
"computedAsync": true,
|
||||
"computedEager": true,
|
||||
"computedInject": true,
|
||||
"computedWithControl": true,
|
||||
"controlledComputed": true,
|
||||
"controlledRef": true,
|
||||
"createApp": true,
|
||||
"createEventHook": true,
|
||||
"createGlobalState": true,
|
||||
"createInjectionState": true,
|
||||
"createReactiveFn": true,
|
||||
"createReusableTemplate": true,
|
||||
"createSharedComposable": true,
|
||||
"createTemplatePromise": true,
|
||||
"createUnrefFn": true,
|
||||
"customRef": true,
|
||||
"debouncedRef": true,
|
||||
"debouncedWatch": true,
|
||||
"defineAsyncComponent": true,
|
||||
"defineComponent": true,
|
||||
"eagerComputed": true,
|
||||
"effectScope": true,
|
||||
"extendRef": true,
|
||||
"getCurrentInstance": true,
|
||||
"getCurrentScope": true,
|
||||
"h": true,
|
||||
"ignorableWatch": true,
|
||||
"inject": true,
|
||||
"isDefined": true,
|
||||
"isProxy": true,
|
||||
"isReactive": true,
|
||||
"isReadonly": true,
|
||||
"isRef": true,
|
||||
"makeDestructurable": true,
|
||||
"markRaw": true,
|
||||
"nextTick": true,
|
||||
"onActivated": true,
|
||||
"onBeforeMount": true,
|
||||
"onBeforeUnmount": true,
|
||||
"onBeforeUpdate": true,
|
||||
"onClickOutside": true,
|
||||
"onDeactivated": true,
|
||||
"onErrorCaptured": true,
|
||||
"onKeyStroke": true,
|
||||
"onLongPress": true,
|
||||
"onMounted": true,
|
||||
"onRenderTracked": true,
|
||||
"onRenderTriggered": true,
|
||||
"onScopeDispose": true,
|
||||
"onServerPrefetch": true,
|
||||
"onStartTyping": true,
|
||||
"onUnmounted": true,
|
||||
"onUpdated": true,
|
||||
"pausableWatch": true,
|
||||
"provide": true,
|
||||
"reactify": true,
|
||||
"reactifyObject": true,
|
||||
"reactive": true,
|
||||
"reactiveComputed": true,
|
||||
"reactiveOmit": true,
|
||||
"reactivePick": true,
|
||||
"readonly": true,
|
||||
"ref": true,
|
||||
"refAutoReset": true,
|
||||
"refDebounced": true,
|
||||
"refDefault": true,
|
||||
"refThrottled": true,
|
||||
"refWithControl": true,
|
||||
"resolveComponent": true,
|
||||
"resolveRef": true,
|
||||
"resolveUnref": true,
|
||||
"shallowReactive": true,
|
||||
"shallowReadonly": true,
|
||||
"shallowRef": true,
|
||||
"syncRef": true,
|
||||
"syncRefs": true,
|
||||
"templateRef": true,
|
||||
"throttledRef": true,
|
||||
"throttledWatch": true,
|
||||
"toRaw": true,
|
||||
"toReactive": true,
|
||||
"toRef": true,
|
||||
"toRefs": true,
|
||||
"toValue": true,
|
||||
"triggerRef": true,
|
||||
"tryOnBeforeMount": true,
|
||||
"tryOnBeforeUnmount": true,
|
||||
"tryOnMounted": true,
|
||||
"tryOnScopeDispose": true,
|
||||
"tryOnUnmounted": true,
|
||||
"unref": true,
|
||||
"unrefElement": true,
|
||||
"until": true,
|
||||
"useActiveElement": true,
|
||||
"useAnimate": true,
|
||||
"useArrayDifference": true,
|
||||
"useArrayEvery": true,
|
||||
"useArrayFilter": true,
|
||||
"useArrayFind": true,
|
||||
"useArrayFindIndex": true,
|
||||
"useArrayFindLast": true,
|
||||
"useArrayIncludes": true,
|
||||
"useArrayJoin": true,
|
||||
"useArrayMap": true,
|
||||
"useArrayReduce": true,
|
||||
"useArraySome": true,
|
||||
"useArrayUnique": true,
|
||||
"useAsyncQueue": true,
|
||||
"useAsyncState": true,
|
||||
"useAttrs": true,
|
||||
"useBase64": true,
|
||||
"useBattery": true,
|
||||
"useBluetooth": true,
|
||||
"useBreakpoints": true,
|
||||
"useBroadcastChannel": true,
|
||||
"useBrowserLocation": true,
|
||||
"useCached": true,
|
||||
"useClipboard": true,
|
||||
"useCloned": true,
|
||||
"useColorMode": true,
|
||||
"useConfirmDialog": true,
|
||||
"useCounter": true,
|
||||
"useCssModule": true,
|
||||
"useCssVar": true,
|
||||
"useCssVars": true,
|
||||
"useCurrentElement": true,
|
||||
"useCycleList": true,
|
||||
"useDark": true,
|
||||
"useDateFormat": true,
|
||||
"useDebounce": true,
|
||||
"useDebounceFn": true,
|
||||
"useDebouncedRefHistory": true,
|
||||
"useDeviceMotion": true,
|
||||
"useDeviceOrientation": true,
|
||||
"useDevicePixelRatio": true,
|
||||
"useDevicesList": true,
|
||||
"useDisplayMedia": true,
|
||||
"useDocumentVisibility": true,
|
||||
"useDraggable": true,
|
||||
"useDropZone": true,
|
||||
"useElementBounding": true,
|
||||
"useElementByPoint": true,
|
||||
"useElementHover": true,
|
||||
"useElementSize": true,
|
||||
"useElementVisibility": true,
|
||||
"useEventBus": true,
|
||||
"useEventListener": true,
|
||||
"useEventSource": true,
|
||||
"useEyeDropper": true,
|
||||
"useFavicon": true,
|
||||
"useFetch": true,
|
||||
"useFileDialog": true,
|
||||
"useFileSystemAccess": true,
|
||||
"useFocus": true,
|
||||
"useFocusWithin": true,
|
||||
"useFps": true,
|
||||
"useFullscreen": true,
|
||||
"useGamepad": true,
|
||||
"useGeolocation": true,
|
||||
"useIdle": true,
|
||||
"useImage": true,
|
||||
"useInfiniteScroll": true,
|
||||
"useIntersectionObserver": true,
|
||||
"useInterval": true,
|
||||
"useIntervalFn": true,
|
||||
"useKeyModifier": true,
|
||||
"useLastChanged": true,
|
||||
"useLocalStorage": true,
|
||||
"useMagicKeys": true,
|
||||
"useManualRefHistory": true,
|
||||
"useMediaControls": true,
|
||||
"useMediaQuery": true,
|
||||
"useMemoize": true,
|
||||
"useMemory": true,
|
||||
"useMounted": true,
|
||||
"useMouse": true,
|
||||
"useMouseInElement": true,
|
||||
"useMousePressed": true,
|
||||
"useMutationObserver": true,
|
||||
"useNavigatorLanguage": true,
|
||||
"useNetwork": true,
|
||||
"useNow": true,
|
||||
"useObjectUrl": true,
|
||||
"useOffsetPagination": true,
|
||||
"useOnline": true,
|
||||
"usePageLeave": true,
|
||||
"useParallax": true,
|
||||
"useParentElement": true,
|
||||
"usePerformanceObserver": true,
|
||||
"usePermission": true,
|
||||
"usePointer": true,
|
||||
"usePointerLock": true,
|
||||
"usePointerSwipe": true,
|
||||
"usePreferredColorScheme": true,
|
||||
"usePreferredContrast": true,
|
||||
"usePreferredDark": true,
|
||||
"usePreferredLanguages": true,
|
||||
"usePreferredReducedMotion": true,
|
||||
"usePrevious": true,
|
||||
"useRafFn": true,
|
||||
"useRefHistory": true,
|
||||
"useResizeObserver": true,
|
||||
"useScreenOrientation": true,
|
||||
"useScreenSafeArea": true,
|
||||
"useScriptTag": true,
|
||||
"useScroll": true,
|
||||
"useScrollLock": true,
|
||||
"useSessionStorage": true,
|
||||
"useShare": true,
|
||||
"useSlots": true,
|
||||
"useSorted": true,
|
||||
"useSpeechRecognition": true,
|
||||
"useSpeechSynthesis": true,
|
||||
"useStepper": true,
|
||||
"useStorage": true,
|
||||
"useStorageAsync": true,
|
||||
"useStyleTag": true,
|
||||
"useSupported": true,
|
||||
"useSwipe": true,
|
||||
"useTemplateRefsList": true,
|
||||
"useTextDirection": true,
|
||||
"useTextSelection": true,
|
||||
"useTextareaAutosize": true,
|
||||
"useThrottle": true,
|
||||
"useThrottleFn": true,
|
||||
"useThrottledRefHistory": true,
|
||||
"useTimeAgo": true,
|
||||
"useTimeout": true,
|
||||
"useTimeoutFn": true,
|
||||
"useTimeoutPoll": true,
|
||||
"useTimestamp": true,
|
||||
"useTitle": true,
|
||||
"useToNumber": true,
|
||||
"useToString": true,
|
||||
"useToggle": true,
|
||||
"useTransition": true,
|
||||
"useUrlSearchParams": true,
|
||||
"useUserMedia": true,
|
||||
"useVModel": true,
|
||||
"useVModels": true,
|
||||
"useVibrate": true,
|
||||
"useVirtualList": true,
|
||||
"useWakeLock": true,
|
||||
"useWebNotification": true,
|
||||
"useWebSocket": true,
|
||||
"useWebWorker": true,
|
||||
"useWebWorkerFn": true,
|
||||
"useWindowFocus": true,
|
||||
"useWindowScroll": true,
|
||||
"useWindowSize": true,
|
||||
"watch": true,
|
||||
"watchArray": true,
|
||||
"watchAtMost": true,
|
||||
"watchDebounced": true,
|
||||
"watchDeep": true,
|
||||
"watchEffect": true,
|
||||
"watchIgnorable": true,
|
||||
"watchImmediate": true,
|
||||
"watchOnce": true,
|
||||
"watchPausable": true,
|
||||
"watchPostEffect": true,
|
||||
"watchSyncEffect": true,
|
||||
"watchThrottled": true,
|
||||
"watchTriggerable": true,
|
||||
"watchWithFilter": true,
|
||||
"useRoute": true,
|
||||
"useRouter": true,
|
||||
"storeToRefs": true,
|
||||
"whenever": true,
|
||||
"DirectiveBinding": true,
|
||||
"ExtractDefaultPropTypes": true,
|
||||
"ExtractPropTypes": true,
|
||||
"ExtractPublicPropTypes": true,
|
||||
"MaybeRef": true,
|
||||
"MaybeRefOrGetter": true,
|
||||
"WritableComputedRef": true,
|
||||
"acceptHMRUpdate": true,
|
||||
"createPinia": true,
|
||||
"defineStore": true,
|
||||
"getActivePinia": true,
|
||||
"injectLocal": true,
|
||||
"mapActions": true,
|
||||
"mapGetters": true,
|
||||
"mapState": true,
|
||||
"mapStores": true,
|
||||
"mapWritableState": true,
|
||||
"onBeforeRouteLeave": true,
|
||||
"onBeforeRouteUpdate": true,
|
||||
"onWatcherCleanup": true,
|
||||
"provideLocal": true,
|
||||
"setActivePinia": true,
|
||||
"setMapStoreSuffix": true,
|
||||
"useClipboardItems": true,
|
||||
"useI18n": true,
|
||||
"useId": true,
|
||||
"useLink": true,
|
||||
"useModel": true,
|
||||
"useTemplateRef": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto eol=lf
|
||||
|
||||
# Source files
|
||||
*.ts text eol=lf
|
||||
*.tsx text eol=lf
|
||||
*.js text eol=lf
|
||||
*.jsx text eol=lf
|
||||
*.vue text eol=lf
|
||||
*.mjs text eol=lf
|
||||
*.cjs text eol=lf
|
||||
|
||||
# Config files
|
||||
*.json text eol=lf
|
||||
*.yml text eol=lf
|
||||
*.yaml text eol=lf
|
||||
|
||||
# Styling
|
||||
*.css text eol=lf
|
||||
*.scss text eol=lf
|
||||
*.less text eol=lf
|
||||
|
||||
# Documentation
|
||||
*.md text eol=lf
|
||||
|
||||
# Shell scripts
|
||||
*.sh text eol=lf
|
||||
@@ -0,0 +1,37 @@
|
||||
# Dependencies
|
||||
node_modules/
|
||||
|
||||
# Build output
|
||||
dist/
|
||||
dist-ssr/
|
||||
stats.html
|
||||
|
||||
# Local env files
|
||||
*.local
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Editor directories and files
|
||||
.idea/
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
!.vscode/settings.json
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Lint cache
|
||||
.eslintcache
|
||||
.stylelintcache
|
||||
|
||||
# Lock files (use pnpm)
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
# Local history
|
||||
.history
|
||||
@@ -0,0 +1 @@
|
||||
npx --no-install commitlint --edit $1
|
||||
@@ -0,0 +1 @@
|
||||
npm run lint:lint-staged
|
||||
@@ -0,0 +1,12 @@
|
||||
dist
|
||||
node_modules
|
||||
public
|
||||
.husky
|
||||
.vscode
|
||||
.idea
|
||||
*.sh
|
||||
*.md
|
||||
|
||||
src/assets
|
||||
stats.html
|
||||
pnpm-lock.yaml
|
||||
@@ -0,0 +1,41 @@
|
||||
# 在单参数箭头函数中始终添加括号
|
||||
arrowParens: "always"
|
||||
# JSX 多行元素的闭合标签另起一行
|
||||
bracketSameLine: false
|
||||
# 对象字面量中的括号之间添加空格
|
||||
bracketSpacing: true
|
||||
# 自动格式化嵌入的代码(如 Markdown 和 HTML 内的代码)
|
||||
embeddedLanguageFormatting: "auto"
|
||||
# 忽略 HTML 空白敏感度,将空白视为非重要内容
|
||||
htmlWhitespaceSensitivity: "ignore"
|
||||
# 不插入 @prettier 的 pragma 注释
|
||||
insertPragma: false
|
||||
# 在 JSX 中使用双引号
|
||||
jsxSingleQuote: false
|
||||
# 每行代码的最大长度限制为 100 字符
|
||||
printWidth: 100
|
||||
# 在 Markdown 中保留原有的换行格式
|
||||
proseWrap: "preserve"
|
||||
# 仅在必要时添加对象属性的引号
|
||||
quoteProps: "as-needed"
|
||||
# 不要求文件开头插入 @prettier 的 pragma 注释
|
||||
requirePragma: false
|
||||
# 在语句末尾添加分号
|
||||
semi: true
|
||||
# 使用双引号而不是单引号
|
||||
singleQuote: false
|
||||
# 缩进使用 2 个空格
|
||||
tabWidth: 2
|
||||
# 在多行元素的末尾添加逗号(ES5 支持的对象、数组等)
|
||||
trailingComma: "es5"
|
||||
# 使用空格而不是制表符缩进
|
||||
useTabs: false
|
||||
# Vue 文件中的 <script> 和 <style> 不增加额外的缩进
|
||||
vueIndentScriptAndStyle: false
|
||||
# 根据系统自动检测换行符
|
||||
endOfLine: "auto"
|
||||
# 对 HTML 文件应用特定格式化规则
|
||||
overrides:
|
||||
- files: "*.html"
|
||||
options:
|
||||
parser: "html"
|
||||
@@ -0,0 +1,11 @@
|
||||
dist
|
||||
node_modules
|
||||
public
|
||||
.husky
|
||||
.vscode
|
||||
.idea
|
||||
*.sh
|
||||
*.md
|
||||
|
||||
src/assets
|
||||
stats.html
|
||||
@@ -0,0 +1,38 @@
|
||||
module.exports = {
|
||||
extends: [
|
||||
"stylelint-config-recommended",
|
||||
"stylelint-config-recommended-scss",
|
||||
"stylelint-config-recommended-vue/scss",
|
||||
"stylelint-config-html/vue",
|
||||
"stylelint-config-recess-order",
|
||||
],
|
||||
|
||||
plugins: [
|
||||
"stylelint-prettier", // 统一代码风格,格式冲突时以 Prettier 规则为准
|
||||
],
|
||||
overrides: [
|
||||
{
|
||||
files: ["**/*.{vue,html}"],
|
||||
customSyntax: "postcss-html",
|
||||
},
|
||||
{
|
||||
files: ["**/*.{css,scss}"],
|
||||
customSyntax: "postcss-scss",
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
"prettier/prettier": true, // 强制执行 Prettier 格式化规则(需配合 .prettierrc 配置文件)
|
||||
"no-empty-source": null, // 允许空的样式文件
|
||||
"declaration-property-value-no-unknown": null, // 允许非常规数值格式 ,如 height: calc(100% - 50)
|
||||
// 允许使用未知伪类
|
||||
"selector-pseudo-class-no-unknown": [
|
||||
true,
|
||||
{
|
||||
ignorePseudoClasses: ["global", "export", "deep"],
|
||||
},
|
||||
],
|
||||
// 允许使用未知伪元素
|
||||
"at-rule-no-unknown": null, // 禁用默认的未知 at-rule 检查
|
||||
"scss/at-rule-no-unknown": true, // 启用 SCSS 特定的 at-rule 检查
|
||||
},
|
||||
};
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"vue.volar",
|
||||
"antfu.unocss",
|
||||
"lokalise.i18n-ally",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode",
|
||||
"stylelint.vscode-stylelint",
|
||||
"editorconfig.editorconfig"
|
||||
]
|
||||
}
|
||||
Vendored
+71
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"typescript.tsdk": "./node_modules/typescript/lib",
|
||||
"npm.packageManager": "pnpm",
|
||||
"editor.tabSize": 2,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.quickSuggestions": {
|
||||
"other": true,
|
||||
"comments": true,
|
||||
"strings": true
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": "explicit",
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.fixAll.stylelint": "explicit"
|
||||
},
|
||||
"files.eol": "\n",
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/*.log": true,
|
||||
"**/*.log*": true,
|
||||
"**/bower_components": true,
|
||||
"**/dist": true,
|
||||
"**/elehukouben": true,
|
||||
"**/.git": true,
|
||||
"**/.gitignore": true,
|
||||
"**/.svn": true,
|
||||
"**/.DS_Store": true,
|
||||
"**/.idea": true,
|
||||
"**/.vscode": false,
|
||||
"**/yarn.lock": true,
|
||||
"**/tmp": true,
|
||||
"out": true,
|
||||
"dist": true,
|
||||
"node_modules": true,
|
||||
"CHANGELOG.md": true,
|
||||
"examples": true,
|
||||
"res": true,
|
||||
"screenshots": true,
|
||||
"yarn-error.log": true,
|
||||
"**/.yarn": true
|
||||
},
|
||||
"files.exclude": {
|
||||
"**/.cache": true,
|
||||
"**/.editorconfig": true,
|
||||
"**/.eslintcache": true,
|
||||
"**/bower_components": true,
|
||||
"**/.idea": true,
|
||||
"**/tmp": true,
|
||||
"**/.git": true,
|
||||
"**/.svn": true,
|
||||
"**/.hg": true,
|
||||
"**/CVS": true,
|
||||
"**/.DS_Store": 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
|
||||
},
|
||||
"i18n-ally.localesPaths": [
|
||||
"src/lang/package"
|
||||
],
|
||||
"scss.lint.unknownAtRules": "ignore",
|
||||
"i18n-ally.keystyle": "nested"
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021-present 有来开源组织
|
||||
|
||||
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 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,213 @@
|
||||
<div align="center">
|
||||
<img alt="vue3-element-admin" width="80" height="80" src="./src/assets/images/logo.png">
|
||||
<h1>vue3-element-admin</h1>
|
||||
|
||||
<img src="https://img.shields.io/badge/Vue-3.5.22-brightgreen.svg"/>
|
||||
<img src="https://img.shields.io/badge/Vite-7.3.0-green.svg"/>
|
||||
<img src="https://img.shields.io/badge/Element Plus-2.3.2-blue.svg"/>
|
||||
<img src="https://img.shields.io/badge/license-MIT-green.svg"/>
|
||||
<a href="https://gitee.com/youlaiorg" target="_blank">
|
||||
<img src="https://img.shields.io/badge/Author-%E6%9C%89%E6%9D%A5%E5%BC%80%E6%BA%90%E7%BB%84%E7%BB%87-orange.svg"/>
|
||||
</a>
|
||||
|
||||
<a href="https://gitee.com/youlaiorg/vue3-element-admin" target="_blank">
|
||||
<img alt="有来技术" src="https://gitee.com/youlaiorg/vue3-element-admin/badge/star.svg"/>
|
||||
</a>
|
||||
<a href="https://github.com/youlaitech/vue3-element-admin" target="_blank">
|
||||
<img alt="有来技术" src="https://img.shields.io/github/stars/youlaitech/vue3-element-admin.svg?style=social&label=Stars"/>
|
||||
</a>
|
||||
<a href="https://gitcode.com/youlai/vue3-element-admin" target="_blank">
|
||||
<img alt="有来技术" src="https://gitcode.com/youlai/vue3-element-admin/star/badge.svg"/>
|
||||
</a>
|
||||
|
||||
<a href="https://atomgit.com/youlai/vue3-element-admin" target="_blank">
|
||||
<img alt="有来技术" src="https://atomgit.com/youlai/vue3-element-admin/star/2025top.svg"/>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||

|
||||
|
||||
<div align="center">
|
||||
<a target="_blank" href="https://vue.youlai.tech">🖥️ Live Preview</a> | <a target="_blank" href="https://app.youlai.tech">📲 Mobile Preview</a> | <a target="_blank" href="https://juejin.cn/post/7228990409909108793">📑 Documentation</a>| <a target="_blank" href="https://www.youlai.tech//vue3-element-admin">🌐 Official Website</a> | <a href="./README.md">💬 中文</a> | <a href="./README.en-US.md">💬 English</a>
|
||||
</div>
|
||||
|
||||
## Introduction
|
||||
|
||||
[vue3-element-admin](https://gitcode.com/youlai/vue3-element-admin) is a minimalist enterprise-level admin frontend template built with Vue3, Vite7, TypeScript, and Element-Plus. It comes with a Java backend [youlai-boot](https://gitee.com/youlaiorg/youlai-boot), a multi-tenant Java backend [youlai-boot-tenant](https://gitee.com/youlaiorg/youlai-boot-tenant), and a Node backend [youlai-nest](https://gitee.com/youlaiorg/youlai-nest). A simplified version [vue3-element-template](https://gitee.com/youlaiorg/vue3-element-template) and a JavaScript version [vue3-element-admin-js](https://gitee.com/youlaiorg/vue3-element-admin) are also available.
|
||||
|
||||
## Project Features
|
||||
|
||||
- **Simple and Easy-to-use**: Upgraded version of [vue-element-admin](https://gitee.com/panjiachen/vue-element-admin) for Vue3, with minimal encapsulation and easy to get started.
|
||||
- **Data Interaction**: Support for `Mock` data and [online API documentation](https://www.apifox.cn/apidoc/shared-195e783f-4d85-4235-a038-eec696de4ea5), with accompanying [Java](https://gitee.com/youlaiorg/youlai-boot) and [Node](https://gitee.com/youlaiorg/youlai-nest) backend source code.
|
||||
|
||||
- **System Functions**: Provides user management, role management, menu management, department management, dictionary management, and other functional modules.
|
||||
- **Permission Management**: Supports dynamic routing, button permissions, role permissions, and data permissions.
|
||||
|
||||
- **Multi-tenant**: Supports multi-tenant mode and tenant isolation.
|
||||
|
||||
- **Infrastructure**: Provides internationalization, multiple layouts, dark mode, full screen, watermark, API documentation, and code generator functionality.
|
||||
- **Continuous Updates**: Project is continuously updated with real-time updates of tools and dependencies.
|
||||
|
||||
## Project Screenshots
|
||||
|
||||
🖥️ **Dashboard**
|
||||
|
||||

|
||||
|
||||
⚡**API Documentation**
|
||||
|
||||

|
||||
|
||||
📲 **Mobile Version**
|
||||
|
||||

|
||||
|
||||
## Project Source Code
|
||||
|
||||
| Project | Gitee | Github | GitCode |
|
||||
| ------------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
||||
| vue3-element-admin ✅ | [vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin) | [vue3-element-admin](https://github.com/youlaitech/vue3-element-admin) | [vue3-element-admin](https://gitcode.com/youlai/vue3-element-admin) |
|
||||
| vue3-element-admin JS Version | [vue3-element-admin-js](https://gitee.com/youlaiorg/vue3-element-admin-js) | [vue3-element-admin-js](https://github.com/youlaitech/vue3-element-admin-js) | [vue3-element-admin-js](https://gitcode.com/youlai/vue3-element-admin-js) |
|
||||
| vue3-element-admin Lite Version | [vue3-element-template](https://gitee.com/youlaiorg/vue3-element-template) | [vue3-element-template](https://github.com/youlaitech/vue3-element-template) | [vue3-element-template](https://gitcode.com/youlai/vue3-element-template) |
|
||||
| vue-uniapp-admin Mobile Version | [vue-uniapp-admin](https://gitee.com/youlaiorg/vue-uniapp-admin) | [vue-uniapp-admin](https://github.com/youlaitech/vue-uniapp-admin) | [vue-uniapp-admin](https://gitcode.com/youlai/vue-uniapp-admin) |
|
||||
| Java Backend | [youlai-boot](https://gitee.com/youlaiorg/youlai-boot) | [youlai-boot](https://github.com/haoxianrui/youlai-boot.git) | [youlai-boot](https://gitcode.com/youlai/youlai-boot.git) |
|
||||
| Java Multi-tenant Backend | [youlai-boot-tenant](https://gitee.com/youlaiorg/youlai-boot-tenant) | - | - |
|
||||
| Node Backend | [youlai-nest](https://gitee.com/youlaiorg/youlai-nest) | [youlai-nest](https://github.com/haoxianrui/youlai-nest.git) | [youlai-nest](https://gitcode.com/youlai/youlai-nest.git) |
|
||||
|
||||
## Development Guide
|
||||
|
||||
| Name | Link |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Video Tutorial | [https://www.bilibili.com/video/BV1eFUuYyEFj](https://www.bilibili.com/video/BV1eFUuYyEFj) |
|
||||
| Project Setup | [Building a Backend Management System from Scratch with Vue3, Vite, TypeScript, and Element-Plus](https://blog.csdn.net/u013737132/article/details/130191394) |
|
||||
| Official Documentation | [https://www.youlai.tech/vue3-element-admin/](https://www.youlai.tech/vue3-element-admin/) |
|
||||
| Code Standards | [ESLint V9 + Prettier + Stylelint + EditorConfig for Standardized and Unified Frontend Code Style](https://youlai.blog.csdn.net/article/details/145608723) |
|
||||
| Commit Standards | [Husky + Lint-staged + Commitlint + Commitizen + cz-git for Git Commit Standards](https://youlai.blog.csdn.net/article/details/145615236) |
|
||||
| API Documentation | [https://www.apifox.cn/apidoc/shared-195e783f-4d85-4235-a038-eec696de4ea5](https://www.apifox.cn/apidoc/shared-195e783f-4d85-4235-a038-eec696de4ea5) |
|
||||
|
||||
## Project Setup
|
||||
|
||||
- **Environment Preparation**
|
||||
|
||||
| Type | Requirement | Notes |
|
||||
| ------------------- | ------------------------------------------------------------ | ---------------------------------------- |
|
||||
| **Node.js** | `^20.19.0` or `>=22.12.0` | LTS is recommended (even major versions) |
|
||||
| **Package Manager** | `pnpm >= 8.0.0` | This project uses pnpm |
|
||||
| **IDE** | [Visual Studio Code](https://code.visualstudio.com/Download) | Recommended Vue/TypeScript extensions |
|
||||
|
||||
- **Quick Start**
|
||||
|
||||
```bash
|
||||
# Clone repository
|
||||
git clone https://gitee.com/youlaiorg/vue3-element-admin.git
|
||||
|
||||
# Change directory
|
||||
cd vue3-element-admin
|
||||
|
||||
# Install pnpm
|
||||
npm install pnpm -g
|
||||
|
||||
# Set mirror source (optional)
|
||||
pnpm config set registry https://registry.npmmirror.com
|
||||
|
||||
# Install dependencies
|
||||
pnpm install
|
||||
|
||||
# Start development server
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
## Project Deployment
|
||||
|
||||
After executing the `pnpm run build` command, the project will be bundled and a `dist` directory will be generated. Next, upload the files from the `dist` directory to the `/usr/share/nginx/html` directory on your server and configure Nginx for reverse proxy.
|
||||
|
||||
```bash
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
Here is an example Nginx configuration:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
# Reverse proxy configuration
|
||||
location /prod-api/ {
|
||||
# Please replace api.youlai.tech with your backend API address, and keep the trailing slash /
|
||||
proxy_pass http://api.youlai.tech/;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For more detailed information, please refer to this article: [Nginx Installation and Configuration](https://blog.csdn.net/u013737132/article/details/145667694).
|
||||
|
||||
## Local Mock
|
||||
|
||||
The project supports both online and local Mock interfaces. By default, it uses online interfaces. To switch to Mock interfaces, modify the `VITE_MOCK_DEV_SERVER` value in the `.env.development` file to `true`.
|
||||
|
||||
## Backend API
|
||||
|
||||
> If you have a basic understanding of Java development, follow these steps to convert online API to local backend API and create an enterprise-level full-stack development environment to help you on your full-stack journey.
|
||||
|
||||
1. Get the backend source code based on `Java` and `SpringBoot` from [youlai-boot](https://gitee.com/youlaiorg/youlai-boot.git).
|
||||
2. Follow the instructions in the backend project's README.md to [set up and run locally](https://gitee.com/youlaiorg/youlai-boot#%E9%A1%B9%E7%9B%AE%E8%BF%90%E8%A1%8C).
|
||||
3. Modify the value of `VITE_APP_API_URL` in the `.env.development` file, changing it from https://api.youlai.tech to http://localhost:8989.
|
||||
|
||||
## Notes
|
||||
|
||||
- **Auto import plugin is disabled by default**
|
||||
|
||||
Component type declarations have been automatically generated for the template project. If you add and use new components, follow the instructions in the screenshot to enable automatic generation. After automatic generation is complete, remember to set it back to `false` to avoid conflicts.
|
||||
|
||||

|
||||
|
||||
- **Blank page when accessing the project**
|
||||
|
||||
Try upgrading your browser, as older browser engines may not support certain new JavaScript syntax, such as optional chaining operator `?.`.
|
||||
|
||||
- **Project synchronization with repository updates**
|
||||
|
||||
After synchronizing the project with repository updates, it is recommended to run `pnpm install` to update dependencies before starting.
|
||||
|
||||
- **Red highlight on project components, functions, and imports**
|
||||
|
||||
Restart VSCode to try again.
|
||||
|
||||
- **Other issues**
|
||||
|
||||
If you have any other issues or suggestions, please open an [ISSUE](https://gitee.com/youlaiorg/vue3-element-admin/issues/new).
|
||||
|
||||
## Commit Conventions
|
||||
|
||||
Execute `pnpm run commit` to invoke interactive git commit and complete the information input and selection according to the prompts.
|
||||
|
||||

|
||||
|
||||
## Project Statistics
|
||||
|
||||

|
||||
|
||||
Thanks to all the contributors!
|
||||
感谢所有的贡献者!
|
||||
|
||||
[](https://github.com/youlaitech/vue3-element-admin/graphs/contributors)
|
||||
|
||||
## Special Thanks
|
||||
|
||||
- Thanks to the [GitCode](https://gitcode.com/) official [G-Star](https://gitcode.com/g-star) certification
|
||||

|
||||
|
||||
## Community
|
||||
|
||||
① Follow the "Youlai Tech" WeChat Official Account, click the **Group Chat** menu to get the QR code (this measure is taken to prevent ads from entering the group, thanks for your understanding and support).
|
||||
|
||||
② Directly add WeChat **`haoxianrui`** with a note indicating "Frontend/Backend/Full Stack".
|
||||
|
||||

|
||||
+209
@@ -0,0 +1,209 @@
|
||||
<div align="center">
|
||||
<img alt="vue3-element-admin" width="80" height="80" src="./src/assets/images/logo.png">
|
||||
<h1>vue3-element-admin</h1>
|
||||
|
||||
<img src="https://img.shields.io/badge/Vue-3.5.30-brightgreen.svg"/>
|
||||
<img src="https://img.shields.io/badge/Vite-8.0.0-green.svg"/>
|
||||
<img src="https://img.shields.io/badge/Element Plus-2.13.6-blue.svg"/>
|
||||
<img src="https://img.shields.io/badge/license-MIT-green.svg"/>
|
||||
|
||||
<a href="https://gitee.com/youlaiorg/vue3-element-admin" target="_blank">
|
||||
<img alt="有来技术" src="https://gitee.com/youlaiorg/vue3-element-admin/badge/star.svg"/>
|
||||
</a>
|
||||
<a href="https://github.com/youlaitech/vue3-element-admin" target="_blank">
|
||||
<img alt="有来技术" src="https://img.shields.io/github/stars/youlaitech/vue3-element-admin.svg?style=social&label=Stars"/>
|
||||
</a>
|
||||
<a href="https://gitcode.com/youlai/vue3-element-admin" target="_blank">
|
||||
<img alt="有来技术" src="https://gitcode.com/youlai/vue3-element-admin/star/badge.svg"/>
|
||||
</a>
|
||||
|
||||
<a href="https://atomgit.com/youlai/vue3-element-admin" target="_blank">
|
||||
<img alt="有来技术" src="https://atomgit.com/youlai/vue3-element-admin/star/2025top.svg"/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||

|
||||
|
||||
<div align="center">
|
||||
<a target="_blank" href="https://vue.youlai.tech">🖥️ 在线预览</a> | <a target="_blank" href="https://app.youlai.tech">📲 移动端预览</a> | <a target="_blank" href="https://juejin.cn/post/7228990409909108793">📑 阅读文档</a>| <a target="_blank" href="https://www.youlai.tech//vue3-element-admin">🌐 官网</a> | <a href="./README.en-US.md">💬 English
|
||||
</div>
|
||||
|
||||
## 项目简介
|
||||
|
||||
[vue3-element-admin](https://gitcode.com/youlai/vue3-element-admin) 基于 Vue3、Vite、TypeScript 和 Element-Plus 搭建的极简开箱即用企业级后台管理前端模板。 配套 Java 后端 [youlai-boot](https://gitee.com/youlaiorg/youlai-boot)、多租户后端 [youlai-boot-tenant](https://gitee.com/youlaiorg/youlai-boot-tenant) 和 Node 后端 [youlai-nest](https://gitee.com/youlaiorg/youlai-nest) 。 提供开发简版[vue3-element-template](https://gitee.com/youlaiorg/vue3-element-template) 和 JS 版本[vue3-element-admin-js](https://gitee.com/youlaiorg/vue3-element-admin) 供开发者快速开发。
|
||||
|
||||
## 项目特色
|
||||
|
||||
- **简洁易用**:基于 [vue-element-admin](https://gitee.com/panjiachen/vue-element-admin) 升级的 Vue3 版本,无过渡封装 ,易上手。
|
||||
- **数据交互**: 支持 `Mock` 数据和[线上接口文档](https://www.apifox.cn/apidoc/shared-195e783f-4d85-4235-a038-eec696de4ea5),并提供配套的 [Java](https://gitee.com/youlaiorg/youlai-boot) 和 [Node](https://gitee.com/youlaiorg/youlai-nest) 后端源码。
|
||||
|
||||
- **系统功能:** 提供用户管理、角色管理、菜单管理、部门管理、字典管理、系统配置、通知公告等功能模块。
|
||||
- **权限管理:** 支持动态路由、按钮权限、角色权限和数据权限等多种权限管理方式。
|
||||
|
||||
- **多租户:** 支持多租户模式与租户隔离。
|
||||
|
||||
- **基础设施:** 提供国际化、多布局、暗黑模式、全屏、水印、接口文档和代码生成器等功能。
|
||||
- **持续更新**:项目持续开源更新,实时更新工具和依赖。
|
||||
|
||||
## 项目截图
|
||||
|
||||
🖥️ **控制台**
|
||||
|
||||

|
||||
|
||||
⚡**接口文档**
|
||||
|
||||

|
||||
|
||||
📲 **移动端**
|
||||
|
||||

|
||||
|
||||
## 项目源码
|
||||
|
||||
| 项目 | Gitee | Github | GitCode |
|
||||
| ------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
||||
| vue3-element-admin ✅ | [vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin) | [vue3-element-admin](https://github.com/youlaitech/vue3-element-admin) | [vue3-element-admin](https://gitcode.com/youlai/vue3-element-admin) |
|
||||
| vue3-element-admin JS版 | [vue3-element-admin-js](https://gitee.com/youlaiorg/vue3-element-admin-js) | [vue3-element-admin-js](https://github.com/youlaitech/vue3-element-admin-js) | [vue3-element-admin-js](https://gitcode.com/youlai/vue3-element-admin-js) |
|
||||
| vue3-element-admin 精简版 | [vue3-element-template](https://gitee.com/youlaiorg/vue3-element-template) | [vue3-element-template](https://github.com/youlaitech/vue3-element-template) | [vue3-element-template](https://gitcode.com/youlai/vue3-element-template) |
|
||||
| vue-uniapp-admin 移动版 | [vue-uniapp-admin](https://gitee.com/youlaiorg/vue-uniapp-admin) | [vue-uniapp-admin](https://github.com/youlaitech/vue-uniapp-admin) | [vue-uniapp-admin](https://gitcode.com/youlai/vue-uniapp-admin) |
|
||||
| Java 后端 | [youlai-boot](https://gitee.com/youlaiorg/youlai-boot) | [youlai-boot](https://github.com/haoxianrui/youlai-boot.git) | [youlai-boot](https://gitcode.com/youlai/youlai-boot.git) |
|
||||
| Java 多租户后端 | [youlai-boot-tenant](https://gitee.com/youlaiorg/youlai-boot-tenant) | - | - |
|
||||
| Node 后端 | [youlai-nest](https://gitee.com/youlaiorg/youlai-nest) | [youlai-nest](https://github.com/haoxianrui/youlai-nest.git) | [youlai-nest](https://gitcode.com/youlai/youlai-nest.git) |
|
||||
|
||||
## 开发指南
|
||||
|
||||
| 名称 | 地址 |
|
||||
| -------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 视频教程 | [https://www.bilibili.com/video/BV1eFUuYyEFj](https://www.bilibili.com/video/BV1eFUuYyEFj) |
|
||||
| 项目搭建 | [基于 Vue3 + Vite + TypeScript + Element-Plus 从0到1搭建后台管理系统](https://blog.csdn.net/u013737132/article/details/130191394) |
|
||||
| 官方文档 | [https://www.youlai.tech/vue3-element-admin](https://www.youlai.tech/vue3-element-admin/) |
|
||||
| 代码规范 | [ESLint V9 + Prettier + Stylelint + EditorConfig 约束和统一前端代码规范](https://youlai.blog.csdn.net/article/details/145608723) |
|
||||
| 提交规范 | [Husky + Lint-staged + Commitlint + Commitizen + cz-git 配置 Git 提交规范](https://youlai.blog.csdn.net/article/details/145615236) |
|
||||
| 接口文档 | [https://www.apifox.cn](https://www.apifox.cn/apidoc/shared-195e783f-4d85-4235-a038-eec696de4ea5) |
|
||||
|
||||
## 项目启动
|
||||
|
||||
- **环境准备**
|
||||
|
||||
| 环境类型 | 版本要求 | 备注 |
|
||||
| ------------ | ------------------------------------------------------------ | --------------------------------- |
|
||||
| **Node.js** | `^20.19.0` 或 `>=22.12.0` | 推荐使用 LTS 版本(主版本为偶数) |
|
||||
| **包管理器** | `pnpm >= 8.0.0` | 项目使用 pnpm 作为包管理器 |
|
||||
| **开发工具** | [Visual Studio Code](https://code.visualstudio.com/Download) | 推荐安装 Vue、TypeScript 相关插件 |
|
||||
|
||||
- **快速开始**
|
||||
|
||||
```bash
|
||||
# 克隆代码
|
||||
git clone https://gitee.com/youlaiorg/vue3-element-admin.git
|
||||
|
||||
# 切换目录
|
||||
cd vue3-element-admin
|
||||
|
||||
# 安装 pnpm
|
||||
npm install pnpm -g
|
||||
|
||||
# 设置镜像源(可忽略)
|
||||
pnpm config set registry https://registry.npmmirror.com
|
||||
|
||||
# 安装依赖
|
||||
pnpm install
|
||||
|
||||
# 启动运行
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
## 项目部署
|
||||
|
||||
执行 `pnpm run build` 命令后,项目将被打包并生成 `dist` 目录。接下来,将 `dist` 目录下的文件上传到服务器 `/usr/share/nginx/html` 目录下,并配置 Nginx 进行反向代理。
|
||||
|
||||
```bash
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
以下是 Nginx 的配置示例:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
# 反向代理配置
|
||||
location /prod-api/ {
|
||||
# 请将 api.youlai.tech 替换为您的后端 API 地址,并注意保留后面的斜杠 /
|
||||
proxy_pass http://api.youlai.tech/;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
更多详细信息,请参考这篇文章:[Nginx 安装和配置](https://blog.csdn.net/u013737132/article/details/145667694)。
|
||||
|
||||
## 本地Mock
|
||||
|
||||
项目同时支持在线和本地 Mock 接口,默认使用线上接口,如需替换为 Mock 接口,修改文件 `.env.development` 的 `VITE_MOCK_DEV_SERVER` 为 `true` **即可**。
|
||||
|
||||
## 后端接口
|
||||
|
||||
> 如果您具备Java开发基础,按照以下步骤将在线接口转为本地后端接口,创建企业级前后端分离开发环境,助您走向全栈之路。
|
||||
|
||||
1. 获取基于 `Java` 和 `SpringBoot` 开发的后端 [youlai-boot](https://gitee.com/youlaiorg/youlai-boot.git) 源码。
|
||||
2. 根据后端工程的说明文档 [README.md](https://gitee.com/youlaiorg/youlai-boot#%E9%A1%B9%E7%9B%AE%E8%BF%90%E8%A1%8C) 完成本地启动。
|
||||
3. 修改 `.env.development` 文件中的 `VITE_APP_API_URL` 的值,将其从 https://api.youlai.tech 更改为 http://localhost:8989 即可。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- **自动导入插件自动生成默认关闭**
|
||||
|
||||
模板项目的组件类型声明已自动生成。如果添加和使用新的组件,请按照图示方法开启自动生成。在自动生成完成后,记得将其设置为 `false`,避免重复执行引发冲突。
|
||||
|
||||

|
||||
|
||||
- **项目启动浏览器访问空白**
|
||||
|
||||
请升级浏览器尝试,低版本浏览器内核可能不支持某些新的 JavaScript 语法,比如可选链操作符 `?.`。
|
||||
|
||||
- **项目同步仓库更新升级**
|
||||
|
||||
项目同步仓库更新升级之后,建议 `pnpm install` 安装更新依赖之后启动 。
|
||||
|
||||
- **项目组件、函数和引用爆红**
|
||||
|
||||
重启 VSCode 尝试
|
||||
|
||||
- **其他问题**
|
||||
|
||||
如果有其他问题或者建议,建议 [ISSUE](https://gitee.com/youlaiorg/vue3-element-admin/issues/new)
|
||||
|
||||
## 提交规范
|
||||
|
||||
执行 `pnpm run commit` 唤起 git commit 交互,根据提示完成信息的输入和选择。
|
||||
|
||||

|
||||
|
||||
## 项目统计
|
||||
|
||||

|
||||
|
||||
Thanks to all the contributors!
|
||||
感谢所有的贡献者!
|
||||
|
||||
[](https://github.com/youlaitech/vue3-element-admin/graphs/contributors)
|
||||
|
||||
## 特别感谢
|
||||
|
||||
- 感谢 [GitCode](https://gitcode.com/) 官方的 [G-Star](https://gitcode.com/g-star) 认证
|
||||

|
||||
|
||||
## 加群交流
|
||||
|
||||
① 关注「有来技术」公众号,点击菜单 **交流群** 获取加群二维码(此举防止广告进群,感谢理解和支持)。
|
||||
|
||||
② 直接添加微信 **`haoxianrui`** 备注「前端/后端/全栈」。
|
||||
|
||||

|
||||
@@ -0,0 +1,93 @@
|
||||
module.exports = {
|
||||
// 继承的规则
|
||||
extends: ["@commitlint/config-conventional"],
|
||||
// 自定义规则
|
||||
rules: {
|
||||
// @see https://commitlint.js.org/#/reference-rules
|
||||
|
||||
// 提交类型枚举,git提交type必须是以下类型
|
||||
"type-enum": [
|
||||
2,
|
||||
"always",
|
||||
[
|
||||
"feat", // 新增功能
|
||||
"fix", // 修复缺陷
|
||||
"docs", // 文档变更
|
||||
"style", // 代码格式(不影响功能,例如空格、分号等格式修正)
|
||||
"refactor", // 代码重构(不包括 bug 修复、功能新增)
|
||||
"perf", // 性能优化
|
||||
"test", // 添加疏漏测试或已有测试改动
|
||||
"build", // 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)
|
||||
"ci", // 修改 CI 配置、脚本
|
||||
"revert", // 回滚 commit
|
||||
"chore", // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)
|
||||
"wip", // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)
|
||||
],
|
||||
],
|
||||
"subject-case": [0], // subject大小写不做校验
|
||||
},
|
||||
|
||||
prompt: {
|
||||
messages: {
|
||||
type: "选择你要提交的类型 :",
|
||||
scope: "选择一个提交范围(可选):",
|
||||
customScope: "请输入自定义的提交范围 :",
|
||||
subject: "填写简短精炼的变更描述 :\n",
|
||||
body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n',
|
||||
breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n',
|
||||
footerPrefixesSelect: "选择关联issue前缀(可选):",
|
||||
customFooterPrefix: "输入自定义issue前缀 :",
|
||||
footer: "列举关联issue (可选) 例如: #31, #I3244 :\n",
|
||||
generatingByAI: "正在通过 AI 生成你的提交简短描述...",
|
||||
generatedSelectByAI: "选择一个 AI 生成的简短描述:",
|
||||
confirmCommit: "是否提交或修改commit ?",
|
||||
},
|
||||
// prettier-ignore
|
||||
types: [
|
||||
{ value: "feat", name: "特性: ✨ 新增功能", emoji: ":sparkles:" },
|
||||
{ value: "fix", name: "修复: 🐛 修复缺陷", emoji: ":bug:" },
|
||||
{ value: "docs", name: "文档: 📝 文档变更(更新README文件,或者注释)", emoji: ":memo:" },
|
||||
{ value: "style", name: "格式: 🌈 代码格式(空格、格式化、缺失的分号等)", emoji: ":lipstick:" },
|
||||
{ value: "refactor", name: "重构: 🔄 代码重构(不修复错误也不添加特性的代码更改)", emoji: ":recycle:" },
|
||||
{ value: "perf", name: "性能: 🚀 性能优化", emoji: ":zap:" },
|
||||
{ value: "test", name: "测试: 🧪 添加疏漏测试或已有测试改动", emoji: ":white_check_mark:"},
|
||||
{ value: "build", name: "构建: 📦️ 构建流程、外部依赖变更(如升级 npm 包、修改 vite 配置等)", emoji: ":package:"},
|
||||
{ value: "ci", name: "集成: ⚙️ 修改 CI 配置、脚本", emoji: ":ferris_wheel:"},
|
||||
{ value: "revert", name: "回退: ↩️ 回滚 commit",emoji: ":rewind:"},
|
||||
{ value: "chore", name: "其他: 🛠️ 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)", emoji: ":hammer:"},
|
||||
{ value: "wip", name: "开发中: 🚧 开发阶段临时提交", emoji: ":construction:"},
|
||||
],
|
||||
useEmoji: true,
|
||||
emojiAlign: "center",
|
||||
useAI: false,
|
||||
aiNumber: 1,
|
||||
themeColorCode: "",
|
||||
scopes: [],
|
||||
allowCustomScopes: true,
|
||||
allowEmptyScopes: true,
|
||||
customScopesAlign: "bottom",
|
||||
customScopesAlias: "custom",
|
||||
emptyScopesAlias: "empty",
|
||||
upperCaseSubject: false,
|
||||
markBreakingChangeMode: false,
|
||||
allowBreakingChanges: ["feat", "fix"],
|
||||
breaklineNumber: 100,
|
||||
breaklineChar: "|",
|
||||
skipQuestions: [],
|
||||
issuePrefixes: [{ value: "closed", name: "closed: ISSUES has been processed" }],
|
||||
customIssuePrefixAlign: "top",
|
||||
emptyIssuePrefixAlias: "skip",
|
||||
customIssuePrefixAlias: "custom",
|
||||
allowCustomIssuePrefix: true,
|
||||
allowEmptyIssuePrefix: true,
|
||||
confirmColorize: true,
|
||||
maxHeaderLength: Infinity,
|
||||
maxSubjectLength: Infinity,
|
||||
minSubjectLength: 0,
|
||||
scopeOverrides: undefined,
|
||||
defaultBody: "",
|
||||
defaultIssues: "",
|
||||
defaultScope: "",
|
||||
defaultSubject: "",
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,242 @@
|
||||
// https://eslint.org/docs/latest/use/configure/configuration-files-new
|
||||
|
||||
// 基础ESLint配置
|
||||
import eslint from "@eslint/js";
|
||||
import globals from "globals";
|
||||
// TypeScript支持
|
||||
import * as typescriptEslint from "typescript-eslint";
|
||||
// Vue支持
|
||||
import pluginVue from "eslint-plugin-vue";
|
||||
import vueParser from "vue-eslint-parser";
|
||||
// 代码风格与格式化
|
||||
import configPrettier from "eslint-config-prettier";
|
||||
import prettierPlugin from "eslint-plugin-prettier";
|
||||
|
||||
// 解析自动导入配置
|
||||
import fs from "node:fs";
|
||||
let autoImportGlobals = {};
|
||||
try {
|
||||
autoImportGlobals =
|
||||
JSON.parse(fs.readFileSync("./.eslintrc-auto-import.json", "utf-8")).globals || {};
|
||||
} catch (error) {
|
||||
// 文件不存在或解析错误时使用空对象
|
||||
console.warn("Could not load auto-import globals", error);
|
||||
}
|
||||
|
||||
// Element Plus组件
|
||||
const elementPlusComponents = {
|
||||
// Element Plus 组件添加为全局变量,避免 no-undef 报错
|
||||
ElInput: "readonly",
|
||||
ElSelect: "readonly",
|
||||
ElSwitch: "readonly",
|
||||
ElCascader: "readonly",
|
||||
ElInputNumber: "readonly",
|
||||
ElTimePicker: "readonly",
|
||||
ElTimeSelect: "readonly",
|
||||
ElDatePicker: "readonly",
|
||||
ElTreeSelect: "readonly",
|
||||
ElText: "readonly",
|
||||
ElRadioGroup: "readonly",
|
||||
ElCheckboxGroup: "readonly",
|
||||
ElOption: "readonly",
|
||||
ElRadio: "readonly",
|
||||
ElCheckbox: "readonly",
|
||||
ElInputTag: "readonly",
|
||||
ElForm: "readonly",
|
||||
ElFormItem: "readonly",
|
||||
ElTable: "readonly",
|
||||
ElTableColumn: "readonly",
|
||||
ElButton: "readonly",
|
||||
ElDialog: "readonly",
|
||||
ElPagination: "readonly",
|
||||
ElMessage: "readonly",
|
||||
ElMessageBox: "readonly",
|
||||
ElNotification: "readonly",
|
||||
ElTree: "readonly",
|
||||
};
|
||||
|
||||
export default [
|
||||
// 忽略文件配置
|
||||
{
|
||||
ignores: [
|
||||
"**/node_modules/**",
|
||||
"**/dist/**",
|
||||
"**/*.min.*",
|
||||
"**/auto-imports.d.ts",
|
||||
"**/components.d.ts",
|
||||
"types/**/*.d.ts",
|
||||
],
|
||||
},
|
||||
|
||||
// 基础 JavaScript 配置
|
||||
eslint.configs.recommended,
|
||||
|
||||
// Vue 推荐配置
|
||||
...pluginVue.configs["flat/recommended"],
|
||||
|
||||
// TypeScript 推荐配置
|
||||
...typescriptEslint.configs.recommended,
|
||||
|
||||
// 全局配置
|
||||
{
|
||||
// 指定要检查的文件
|
||||
files: ["**/*.{js,mjs,cjs,ts,mts,cts,vue}"],
|
||||
languageOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
globals: {
|
||||
...globals.browser, // 浏览器环境全局变量
|
||||
...globals.node, // Node.js 环境全局变量
|
||||
...globals.es2022, // ES2022 全局对象
|
||||
...autoImportGlobals, // 自动导入的 API 函数
|
||||
...elementPlusComponents, // Element Plus 组件
|
||||
// 全局类型定义,解决 TypeScript 中定义但 ESLint 不识别的问题
|
||||
PageQuery: "readonly",
|
||||
PageResult: "readonly",
|
||||
OptionType: "readonly",
|
||||
ApiResponse: "readonly",
|
||||
ExcelResult: "readonly",
|
||||
TagView: "readonly",
|
||||
AppSettings: "readonly",
|
||||
__APP_INFO__: "readonly",
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
vue: pluginVue,
|
||||
"@typescript-eslint": typescriptEslint.plugin,
|
||||
},
|
||||
rules: {
|
||||
// 基础规则
|
||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||
|
||||
// ES6+ 规则
|
||||
"prefer-const": "error",
|
||||
"no-var": "error",
|
||||
"object-shorthand": "error",
|
||||
|
||||
// 最佳实践
|
||||
eqeqeq: "off",
|
||||
"no-multi-spaces": "error",
|
||||
"no-multiple-empty-lines": ["error", { max: 1, maxBOF: 0, maxEOF: 0 }],
|
||||
|
||||
// 禁用与 TypeScript 冲突的规则
|
||||
"no-unused-vars": "off",
|
||||
"no-undef": "off",
|
||||
"no-redeclare": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
},
|
||||
},
|
||||
|
||||
// Vue 文件特定配置
|
||||
{
|
||||
files: ["**/*.vue"],
|
||||
languageOptions: {
|
||||
parser: vueParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
parser: typescriptEslint.parser,
|
||||
extraFileExtensions: [".vue"],
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
// Vue 规则
|
||||
"vue/multi-word-component-names": "off",
|
||||
"vue/no-v-html": "off",
|
||||
"vue/require-default-prop": "off",
|
||||
"vue/require-explicit-emits": "error",
|
||||
"vue/no-unused-vars": "error",
|
||||
"vue/no-mutating-props": "off",
|
||||
"vue/valid-v-for": "warn",
|
||||
"vue/no-template-shadow": "warn",
|
||||
"vue/return-in-computed-property": "warn",
|
||||
"vue/block-order": [
|
||||
"error",
|
||||
{
|
||||
order: ["template", "script", "style"],
|
||||
},
|
||||
],
|
||||
"vue/html-self-closing": [
|
||||
"error",
|
||||
{
|
||||
html: {
|
||||
void: "always",
|
||||
normal: "never",
|
||||
component: "always",
|
||||
},
|
||||
svg: "always",
|
||||
math: "always",
|
||||
},
|
||||
],
|
||||
"vue/component-name-in-template-casing": ["error", "PascalCase"],
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
},
|
||||
},
|
||||
|
||||
// TypeScript 文件特定配置
|
||||
{
|
||||
files: ["**/*.{ts,tsx,mts,cts}"],
|
||||
languageOptions: {
|
||||
parser: typescriptEslint.parser,
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
project: "./tsconfig.eslint.json",
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
// TypeScript 规则
|
||||
"@typescript-eslint/no-explicit-any": "off", // 允许使用any类型,方便开发
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
"@typescript-eslint/no-empty-object-type": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"warn",
|
||||
{
|
||||
argsIgnorePattern: "^_",
|
||||
varsIgnorePattern: "^_",
|
||||
caughtErrorsIgnorePattern: "^_",
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-unused-expressions": "warn", // 降级为警告
|
||||
"@typescript-eslint/consistent-type-imports": "off", // 关闭强制使用type import
|
||||
"@typescript-eslint/no-import-type-side-effects": "error",
|
||||
},
|
||||
},
|
||||
|
||||
// .d.ts 文件配置
|
||||
{
|
||||
files: ["**/*.d.ts"],
|
||||
rules: {
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
},
|
||||
},
|
||||
|
||||
// CURD 组件配置
|
||||
{
|
||||
files: ["**/components/CURD/**/*.{ts,vue}"],
|
||||
rules: {
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
},
|
||||
},
|
||||
|
||||
// Prettier 集成(必须放在最后)
|
||||
{
|
||||
plugins: {
|
||||
prettier: prettierPlugin, // 将 Prettier 的输出作为 ESLint 的问题来报告
|
||||
},
|
||||
rules: {
|
||||
...configPrettier.rules,
|
||||
"prettier/prettier": ["error", {}, { usePrettierrc: true }],
|
||||
"arrow-body-style": "off",
|
||||
"prefer-arrow-callback": "off",
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,93 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="Vue3 + Vite + TypeScript + Element-Plus 的后台管理模板 " />
|
||||
<meta
|
||||
name="keywords"
|
||||
content="vue,element-plus,typescript,vue-element-admin,vue3-element-admin"
|
||||
/>
|
||||
<title>%VITE_APP_TITLE%</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<div class="loading-container">
|
||||
<div class="loading-spinner">
|
||||
<div class="loading-bar"></div>
|
||||
<div class="loading-bar"></div>
|
||||
<div class="loading-bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
|
||||
<style>
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.loading-bar {
|
||||
width: 4px;
|
||||
height: 24px;
|
||||
background-color: #498cff;
|
||||
border-radius: 2px;
|
||||
animation: loading-animation 1.2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.loading-bar:nth-child(1) {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.loading-bar:nth-child(2) {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.loading-bar:nth-child(3) {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
@keyframes loading-animation {
|
||||
0% {
|
||||
opacity: 0.3;
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: scaleY(1.2);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0.3;
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</html>
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017-present PanJiaChen
|
||||
|
||||
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 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,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021-present 有来开源组织
|
||||
|
||||
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 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,61 @@
|
||||
import { defineMock } from "./base";
|
||||
|
||||
export default defineMock([
|
||||
{
|
||||
url: "auth/captcha",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
captchaId: "534b8ef2b0a24121bec76391ddd159f9",
|
||||
captchaBase64:
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAAkCAIAAADNSmkJAAAFKUlEQVR4Xu2ZXUwcVRiGV70wMWo08V5NvPXCrDbFaGpMaZW2hqQxaoiJTRsaMBCNSYtpa2JTKiFSelFa+Q/QZcMWqEhBlh+htbEpZhMrBQrlJ0hBywLLyrJ0WZbje3bqOvPNLHPWrDvdOE9ONmfe78zkzMs335wzWJhJQrBQweS/wTQ6QWgYHdoIOcecOe05O+t2WkutO+p2ZF3Ksg/YV9ZW6FATYajR3nveg60H9327r3O8c35lHgp+r05dPdJzBL73TPSQ8SaCKIxGLsPlop+K0JHrEkPuoT31e5qGmmjARACF0agYyGVNlyVm/pzZXrN9fHGcBkz0UBid+31u93i3XFFT80vN8cvHqWqih8Lo1NpUqS5vwh3vnd223VQ10UNh9NbyrcFQUK6oCawHUipSqGqiB83oBf+CXFGDMp1mS6OqiR4Ko7FexkpOrqhpHGw82nOUqiZ6KIzGrkRuorW0dJMmOy+hOCfYGzb2RBFv6HRO0gEJw/U7y+pgL1bwmTxexN6sZ31TdEwEhdG+gA+7EqyXpUO1uZH20cWL8hMTRt1N9tBXzCJrOIRoCPJpSO2RAp4HmtCdIfZ+2JWgEBN9LbR28seTGU0Zue1tMLp+YIAMSADzfvbkKX4/eb28j4YODiGin3heqmIlLja5hAUCu+nmGY3JWKvpMAlqNGgebsauBOvlqSX+JEx7p7EbTLen53XlzfmWUioqXikrc68Y8N2juJ/fyVsNChGHEE//rBANYWaZz+TRQqpLaBgNsPfDrgSpbS21YtV87IdjrlkX9JZbt5DOma2t9ITo5F+5glN22WwL/n+yDv00mw06orKxOqQ5+J04hhViwzAXETIcJDVm8uxZqktoGx2Nj9t43Wgaul/ERQiGQvtbWnDWgZYW9CXlQFjZ/7ciyHNn+Z2MexTimIeLz59TiIln0M1e+IbPpOAaDUnEYPTi6iqKxpbycs/qKo1tCslfKcffPn9enuMiPPY1vxO/ckeFQ4h46cdGqUWoidE/y54q5tPY5WDrGzQqIXot4BgchEE57e00IMCw2/1qZSVO/7SjA78o9INzcxsbrL+fnTnDDh9mmZn8F30oG1Hm+nABv5mQMopDS/h1HxtqTzWbABMe9sxpPoe9zezeOo1GELqWhPS8t46M0IAYHbdvR1aHbaOjbjfLz2eFhez6dba4yAfgF30o0BFVE8+Mjh/wFxPI+I5mAEHU6Ls+38vhTFwOBGhMDF8gkFpbC5ffsdv/uBs6dIj19dExEtARVXv9YNbop8NFY3aZ6gRRo+tu3IBHnzmdNCBMXldXJKPfL74WzWUJRE+coDUknqsOdZXQbAJYwluVTbOZI3Qt8GFzMwxyjo3RgBiN4fr+elXVpZGRLWXl6PdOTtJBSlBDUK/lnIrjOlrtqWYTQDJaF6FrTXu9sOa1ysrVoM5HVE1GFxZQcyJ/p+xzv6K/rbr6N6+XDpUBl0tKFIrbz78qWB6YnWFMCBld4XLBms+7df75ook/GNzb0GCV7U1Qfz9p64TyQWNjYD3qe9rj4SMJtQP3MyjSDPzWIRHPjH7X4YAvfXoPuyZf9Pbi3PcuXIh4mp3NllYC6XY79C+jl2o8PBipxjnBttn4MgMNnWgfcRJGPI2OL8hTj3LloIlmRicvBhiNykvecpqoa3RSY4DRcLAwyicuOepVR1JjgNFYHWONHL04czTX0UmNAUYD7Pr+xc4wqTHGaBb2OtZvHUmNYUazcA2J6etdUmOk0f8rTKMTxF91RG0D1SwYGwAAAABJRU5ErkJggg==",
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
url: "auth/login",
|
||||
method: ["POST"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
accessToken:
|
||||
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImRlcHRJZCI6MSwiZGF0YVNjb3BlIjoxLCJ1c2VySWQiOjIsImlhdCI6MTcyODE5MzA1MiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9BRE1JTiJdLCJqdGkiOiJhZDg3NzlhZDZlYWY0OWY3OTE4M2ZmYmI5OWM4MjExMSJ9.58YHwL3sNNC22jyAmOZeSm-7MITzfHb_epBIz7LvWeA",
|
||||
tokenType: "Bearer",
|
||||
refreshToken:
|
||||
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImRlcHRJZCI6MSwiZGF0YVNjb3BlIjoxLCJ1c2VySWQiOjIsImlhdCI6MTcyODE5MzA1MiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9BRE1JTiJdLCJqdGkiOiJhZDg3NzlhZDZlYWY0OWY3OTE4M2ZmYmI5OWM4MjExMSJ9.58YHwL3sNNC22jyAmOZeSm-7MITzfHb_epBIz7LvWeA",
|
||||
expiresIn: 7200,
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
url: "auth/refresh-token",
|
||||
method: ["POST"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
accessToken:
|
||||
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImRlcHRJZCI6MSwiZGF0YVNjb3BlIjoxLCJ1c2VySWQiOjIsImlhdCI6MTcyODE5MzA1MiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9BRE1JTiJdLCJqdGkiOiJhZDg3NzlhZDZlYWY0OWY3OTE4M2ZmYmI5OWM4MjExMSJ9.58YHwL3sNNC22jyAmOZeSm-7MITzfHb_epBIz7LvWeA",
|
||||
tokenType: "Bearer",
|
||||
refreshToken:
|
||||
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImRlcHRJZCI6MSwiZGF0YVNjb3BlIjoxLCJ1c2VySWQiOjIsImlhdCI6MTcyODE5MzA1MiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9BRE1JTiJdLCJqdGkiOiJhZDg3NzlhZDZlYWY0OWY3OTE4M2ZmYmI5OWM4MjExMSJ9.58YHwL3sNNC22jyAmOZeSm-7MITzfHb_epBIz7LvWeA",
|
||||
expiresIn: 7200,
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
url: "auth/logout",
|
||||
method: ["DELETE"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {},
|
||||
msg: "string",
|
||||
},
|
||||
},
|
||||
]);
|
||||
@@ -0,0 +1,7 @@
|
||||
import path from "path";
|
||||
import { createDefineMock } from "vite-plugin-mock-dev-server";
|
||||
|
||||
export const defineMock = createDefineMock((mock) => {
|
||||
// 拼接url
|
||||
mock.url = path.join(import.meta.env.VITE_APP_BASE_API + "/api/v1/", mock.url);
|
||||
});
|
||||
@@ -0,0 +1,153 @@
|
||||
import { defineMock } from "./base";
|
||||
|
||||
export default defineMock([
|
||||
{
|
||||
url: "depts/options",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: [
|
||||
{
|
||||
value: "1",
|
||||
label: "有来技术",
|
||||
children: [
|
||||
{
|
||||
value: "2",
|
||||
label: "研发部门",
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "测试部门",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
url: "depts",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: [
|
||||
{
|
||||
id: "1",
|
||||
parentId: "0",
|
||||
name: "有来技术",
|
||||
code: "YOULAI",
|
||||
sort: 1,
|
||||
status: 1,
|
||||
children: [
|
||||
{
|
||||
id: "2",
|
||||
parentId: "1",
|
||||
name: "研发部门",
|
||||
code: "RD001",
|
||||
sort: 1,
|
||||
status: 1,
|
||||
children: [],
|
||||
createTime: null,
|
||||
updateTime: "2022-04-19 12:46",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
parentId: "1",
|
||||
name: "测试部门",
|
||||
code: "QA001",
|
||||
sort: 1,
|
||||
status: 1,
|
||||
children: [],
|
||||
createTime: null,
|
||||
updateTime: "2022-04-19 12:46",
|
||||
},
|
||||
],
|
||||
createTime: null,
|
||||
updateTime: null,
|
||||
},
|
||||
],
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
|
||||
// 新增部门
|
||||
{
|
||||
url: "depts",
|
||||
method: ["POST"],
|
||||
body({ body }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "新增部门" + body.name + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 获取部门表单数据
|
||||
{
|
||||
url: "depts/:id/form",
|
||||
method: ["GET"],
|
||||
body: ({ params }) => {
|
||||
return {
|
||||
code: "00000",
|
||||
data: deptMap[params.id],
|
||||
msg: "一切ok",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 修改部门
|
||||
{
|
||||
url: "depts/:id",
|
||||
method: ["PUT"],
|
||||
body({ body }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "修改部门" + body.name + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 删除部门
|
||||
{
|
||||
url: "depts/:id",
|
||||
method: ["DELETE"],
|
||||
body({ params }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "删除部门" + params.id + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
// 部门映射表数据
|
||||
const deptMap: Record<string, any> = {
|
||||
1: {
|
||||
id: "1",
|
||||
name: "有来技术",
|
||||
code: "YOULAI",
|
||||
parentId: "0",
|
||||
status: 1,
|
||||
sort: 1,
|
||||
},
|
||||
2: {
|
||||
id: "2",
|
||||
name: "研发部门",
|
||||
code: "RD001",
|
||||
parentId: "1",
|
||||
status: 1,
|
||||
sort: 1,
|
||||
},
|
||||
3: {
|
||||
id: "3",
|
||||
name: "测试部门",
|
||||
code: "QA001",
|
||||
parentId: "1",
|
||||
status: 1,
|
||||
sort: 1,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,312 @@
|
||||
import { defineMock } from "./base";
|
||||
|
||||
export default defineMock([
|
||||
{
|
||||
url: "dicts",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
list: [
|
||||
{
|
||||
id: "1",
|
||||
name: "性别",
|
||||
dictCode: "gender",
|
||||
status: 1,
|
||||
},
|
||||
],
|
||||
total: 1,
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 字典列表
|
||||
*/
|
||||
{
|
||||
url: "dicts/options",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: [
|
||||
{
|
||||
value: "gender",
|
||||
label: "性别",
|
||||
},
|
||||
],
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
|
||||
// 新增字典
|
||||
{
|
||||
url: "dicts",
|
||||
method: ["POST"],
|
||||
body({ body }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "新增字典" + body.name + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 获取字典表单数据
|
||||
{
|
||||
url: "dicts/:id/form",
|
||||
method: ["GET"],
|
||||
body: ({ params }) => {
|
||||
return {
|
||||
code: "00000",
|
||||
data: dictMap[params.id],
|
||||
msg: "一切ok",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 修改字典
|
||||
{
|
||||
url: "dicts/:id",
|
||||
method: ["PUT"],
|
||||
body({ body }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "修改字典" + body.name + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 删除字典
|
||||
{
|
||||
url: "dicts/:ids",
|
||||
method: ["DELETE"],
|
||||
body({ params }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "删除字典" + params.ids + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
//---------------------------------------------------
|
||||
// 字典项相关接口
|
||||
//---------------------------------------------------
|
||||
|
||||
// 字典项分页列表
|
||||
{
|
||||
url: "dicts/:dictCode/items",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
list: [
|
||||
{
|
||||
id: "1",
|
||||
dictCode: "gender",
|
||||
label: "男",
|
||||
value: "1",
|
||||
sort: 1,
|
||||
status: 1,
|
||||
tagType: "P",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
dictCode: "gender",
|
||||
label: "女",
|
||||
value: "2",
|
||||
sort: 2,
|
||||
status: 1,
|
||||
tagType: "D",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
dictCode: "gender",
|
||||
label: "保密",
|
||||
value: "0",
|
||||
sort: 3,
|
||||
status: 1,
|
||||
tagType: "I",
|
||||
},
|
||||
],
|
||||
total: 3,
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
// 字典项列表
|
||||
{
|
||||
url: "dicts/:dictCode/items/options",
|
||||
method: ["GET"],
|
||||
body: ({ params }) => {
|
||||
const dictCode = params.dictCode;
|
||||
|
||||
let list = null;
|
||||
|
||||
if (dictCode == "gender") {
|
||||
list = [
|
||||
{
|
||||
value: "1",
|
||||
label: "男",
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "女",
|
||||
},
|
||||
{
|
||||
value: "0",
|
||||
label: "保密",
|
||||
},
|
||||
];
|
||||
} else if (dictCode == "notice_level") {
|
||||
list = [
|
||||
{
|
||||
value: "L",
|
||||
label: "低",
|
||||
tagType: "I",
|
||||
},
|
||||
{
|
||||
value: "M",
|
||||
label: "中",
|
||||
tagType: "W",
|
||||
},
|
||||
{
|
||||
value: "H",
|
||||
label: "高",
|
||||
tagType: "D",
|
||||
},
|
||||
];
|
||||
} else if (dictCode == "notice_type") {
|
||||
list = [
|
||||
{
|
||||
value: "1",
|
||||
label: "系统升级",
|
||||
tagType: "S",
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "系统维护",
|
||||
tagType: "P",
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "安全警告",
|
||||
tagType: "D",
|
||||
},
|
||||
{
|
||||
value: "4",
|
||||
label: "假期通知",
|
||||
tagType: "S",
|
||||
},
|
||||
{
|
||||
value: "5",
|
||||
label: "公司新闻",
|
||||
tagType: "P",
|
||||
},
|
||||
{
|
||||
value: "99",
|
||||
label: "其他",
|
||||
tagType: "I",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return {
|
||||
code: "00000",
|
||||
data: list,
|
||||
msg: "一切ok",
|
||||
};
|
||||
},
|
||||
},
|
||||
// 新增字典项
|
||||
{
|
||||
url: "dicts/:dictCode/items",
|
||||
method: ["POST"],
|
||||
body({ body }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "新增字典项" + body.label + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 字典项表单数据
|
||||
{
|
||||
url: "dicts/:dictCode/items/:itemId/form",
|
||||
method: ["GET"],
|
||||
body: ({ params }) => {
|
||||
return {
|
||||
code: "00000",
|
||||
data: dictItemMap[params.itemId],
|
||||
msg: "一切ok",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 修改字典项
|
||||
{
|
||||
url: "dicts/:dictCode/items/:itemId",
|
||||
method: ["PUT"],
|
||||
body({ body }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "修改字典项" + body.label + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 删除字典
|
||||
{
|
||||
url: "dicts/:dictCode/items/:itemId",
|
||||
method: ["DELETE"],
|
||||
body({ params }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "删除字典" + params.itemId + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
// 字典映射表数据
|
||||
const dictMap: Record<string, any> = {
|
||||
1: {
|
||||
id: "1",
|
||||
name: "性别",
|
||||
dictCode: "gender",
|
||||
status: 1,
|
||||
},
|
||||
};
|
||||
|
||||
// 字典项映射表数据
|
||||
const dictItemMap: Record<string, any> = {
|
||||
1: {
|
||||
id: "1",
|
||||
value: "1",
|
||||
label: "男",
|
||||
sort: 1,
|
||||
status: 1,
|
||||
tagType: "P",
|
||||
},
|
||||
2: {
|
||||
id: "2",
|
||||
value: "2",
|
||||
label: "女",
|
||||
sort: 2,
|
||||
status: 1,
|
||||
tagType: "D",
|
||||
},
|
||||
3: {
|
||||
id: "3",
|
||||
value: "0",
|
||||
label: "保密",
|
||||
sort: 3,
|
||||
status: 1,
|
||||
tagType: "I",
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,205 @@
|
||||
import { defineMock } from "./base";
|
||||
|
||||
export default defineMock([
|
||||
{
|
||||
url: "logs",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
list: [
|
||||
{
|
||||
id: "36192",
|
||||
module: "菜单",
|
||||
content: "菜单列表",
|
||||
requestUri: "/api/v1/menus",
|
||||
method: null,
|
||||
ip: "183.156.148.241",
|
||||
region: "浙江省 杭州市",
|
||||
browser: "Chrome 109.0.0.0",
|
||||
os: "OSX",
|
||||
executionTime: 5,
|
||||
createBy: null,
|
||||
createTime: "2024-07-07 20:38:47",
|
||||
operator: "系统管理员",
|
||||
},
|
||||
{
|
||||
id: "36190",
|
||||
module: "字典",
|
||||
content: "字典分页列表",
|
||||
requestUri: "/api/v1/dicts",
|
||||
method: null,
|
||||
ip: "183.156.148.241",
|
||||
region: "浙江省 杭州市",
|
||||
browser: "Chrome 109.0.0.0",
|
||||
os: "OSX",
|
||||
executionTime: 9,
|
||||
createBy: null,
|
||||
createTime: "2024-07-07 20:38:45",
|
||||
operator: "系统管理员",
|
||||
},
|
||||
{
|
||||
id: "36193",
|
||||
module: "部门",
|
||||
content: "部门列表",
|
||||
requestUri: "/api/v1/depts",
|
||||
method: null,
|
||||
ip: "192.168.31.134",
|
||||
region: "0 内网IP",
|
||||
browser: "Chrome 125.0.0.0",
|
||||
os: "Windows 10 or Windows Server 2016",
|
||||
executionTime: 27,
|
||||
createBy: null,
|
||||
createTime: "2024-07-07 20:38:45",
|
||||
operator: "系统管理员",
|
||||
},
|
||||
{
|
||||
id: "36191",
|
||||
module: "菜单",
|
||||
content: "菜单列表",
|
||||
requestUri: "/api/v1/menus",
|
||||
method: null,
|
||||
ip: "192.168.31.134",
|
||||
region: "0 内网IP",
|
||||
browser: "Chrome 125.0.0.0",
|
||||
os: "Windows 10 or Windows Server 2016",
|
||||
executionTime: 39,
|
||||
createBy: null,
|
||||
createTime: "2024-07-07 20:38:44",
|
||||
operator: "系统管理员",
|
||||
},
|
||||
{
|
||||
id: "36189",
|
||||
module: "角色",
|
||||
content: "角色分页列表",
|
||||
requestUri: "/api/v1/roles",
|
||||
method: null,
|
||||
ip: "192.168.31.134",
|
||||
region: "0 内网IP",
|
||||
browser: "Chrome 125.0.0.0",
|
||||
os: "Windows 10 or Windows Server 2016",
|
||||
executionTime: 55,
|
||||
createBy: null,
|
||||
createTime: "2024-07-07 20:38:43",
|
||||
operator: "系统管理员",
|
||||
},
|
||||
{
|
||||
id: "36188",
|
||||
module: "用户",
|
||||
content: "用户分页列表",
|
||||
requestUri: "/api/v1/users",
|
||||
method: null,
|
||||
ip: "192.168.31.134",
|
||||
region: "0 内网IP",
|
||||
browser: "Chrome 125.0.0.0",
|
||||
os: "Windows 10 or Windows Server 2016",
|
||||
executionTime: 92,
|
||||
createBy: null,
|
||||
createTime: "2024-07-07 20:38:42",
|
||||
operator: "系统管理员",
|
||||
},
|
||||
{
|
||||
id: "36187",
|
||||
module: "登录",
|
||||
content: "登录",
|
||||
requestUri: "/api/v1/auth/login",
|
||||
method: null,
|
||||
ip: "192.168.31.134",
|
||||
region: "0 内网IP",
|
||||
browser: "Chrome 125.0.0.0",
|
||||
os: "Windows 10 or Windows Server 2016",
|
||||
executionTime: 19340,
|
||||
createBy: null,
|
||||
createTime: "2024-07-07 20:38:09",
|
||||
operator: "系统管理员",
|
||||
},
|
||||
{
|
||||
id: "36186",
|
||||
module: "登录",
|
||||
content: "登录",
|
||||
requestUri: "/api/v1/auth/login",
|
||||
method: null,
|
||||
ip: "192.168.31.134",
|
||||
region: "0 内网IP",
|
||||
browser: "Chrome 125.0.0.0",
|
||||
os: "Windows 10 or Windows Server 2016",
|
||||
executionTime: 19869,
|
||||
createBy: null,
|
||||
createTime: "2024-07-07 20:37:59",
|
||||
operator: "系统管理员",
|
||||
},
|
||||
{
|
||||
id: "36185",
|
||||
module: "登录",
|
||||
content: "登录",
|
||||
requestUri: "/api/v1/auth/login",
|
||||
method: null,
|
||||
ip: "112.103.111.59",
|
||||
region: "黑龙江省 哈尔滨市",
|
||||
browser: "Chrome 97.0.4692.98",
|
||||
os: "Android",
|
||||
executionTime: 96,
|
||||
createBy: null,
|
||||
createTime: "2024-07-07 20:37:21",
|
||||
operator: "系统管理员",
|
||||
},
|
||||
{
|
||||
id: "36184",
|
||||
module: "登录",
|
||||
content: "登录",
|
||||
requestUri: "/api/v1/auth/login",
|
||||
method: null,
|
||||
ip: "114.86.204.190",
|
||||
region: "上海 上海市",
|
||||
browser: "Chrome 125.0.0.0",
|
||||
os: "Windows 10 or Windows Server 2016",
|
||||
executionTime: 89,
|
||||
createBy: null,
|
||||
createTime: "2024-07-07 20:29:37",
|
||||
operator: "系统管理员",
|
||||
},
|
||||
],
|
||||
total: 36188,
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "logs/analytics/trend",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
dates: [
|
||||
"2024-06-30",
|
||||
"2024-07-01",
|
||||
"2024-07-02",
|
||||
"2024-07-03",
|
||||
"2024-07-04",
|
||||
"2024-07-05",
|
||||
"2024-07-06",
|
||||
"2024-07-07",
|
||||
],
|
||||
pvList: [1751, 5168, 4882, 5301, 4721, 4885, 1901, 1003],
|
||||
uvList: [207, 566, 565, 631, 579, 496, 222, 152],
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "logs/analytics/overview",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
todayUvCount: 169,
|
||||
totalUvCount: 19985,
|
||||
uvGrowthRate: -0.57,
|
||||
todayPvCount: 1629,
|
||||
totalPvCount: 286086,
|
||||
pvGrowthRate: -0.65,
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
]);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,416 @@
|
||||
import { defineMock } from "./base";
|
||||
|
||||
export default defineMock([
|
||||
{
|
||||
url: "notices",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
list: [
|
||||
{
|
||||
id: "1",
|
||||
title: "v2.12.0 新增系统日志,访问趋势统计功能。",
|
||||
publishStatus: 1,
|
||||
type: 1,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
publishTime: "2024-09-30 17:21",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "v2.13.0 新增菜单搜索。",
|
||||
publishStatus: 1,
|
||||
type: 1,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
publishTime: "2024-09-30 17:22",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "\r\nv2.14.0 新增个人中心。",
|
||||
publishStatus: 1,
|
||||
type: 1,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
publishTime: "2024-09-30 17:23",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title: "v2.15.0 登录页面改造。",
|
||||
publishStatus: 1,
|
||||
type: 1,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
publishTime: "2024-09-30 17:24",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
title: "v2.16.0 通知公告、字典翻译组件。",
|
||||
publishStatus: 1,
|
||||
type: 1,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
publishTime: "2024-09-30 17:25",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
title: "系统将于本周六凌晨 2 点进行维护,预计维护时间为 2 小时。",
|
||||
publishStatus: 1,
|
||||
type: 2,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
publishTime: "2024-09-30 17:26",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
title: "最近发现一些钓鱼邮件,请大家提高警惕,不要点击陌生链接。",
|
||||
publishStatus: 1,
|
||||
type: 3,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
publishTime: "2024-09-30 17:27",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
title: "国庆假期从 10 月 1 日至 10 月 7 日放假,共 7 天。",
|
||||
publishStatus: 1,
|
||||
type: 4,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
publishTime: "2024-09-30 17:28",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
{
|
||||
id: "9",
|
||||
title: "公司将在 10 月 15 日举办新产品发布会,敬请期待。",
|
||||
publishStatus: 1,
|
||||
type: 5,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
publishTime: "2024-09-30 17:29",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
{
|
||||
id: "10",
|
||||
title: "v2.16.1 版本修复了 WebSocket 重复连接导致的后台线程阻塞问题,优化了通知公告。",
|
||||
publishStatus: 1,
|
||||
type: 1,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
publishTime: "2024-09-30 17:30",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
],
|
||||
total: 10,
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
|
||||
// 新增通知
|
||||
{
|
||||
url: "notices",
|
||||
method: ["POST"],
|
||||
body() {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "新增成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 获取通知表单数据
|
||||
{
|
||||
url: "notices/:id/form",
|
||||
method: ["GET"],
|
||||
body: ({ params }) => {
|
||||
return {
|
||||
code: "00000",
|
||||
data: noticeMap[params.id],
|
||||
msg: "一切ok",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 获取通知详情
|
||||
{
|
||||
url: "notices/:id/detail",
|
||||
method: ["GET"],
|
||||
body: ({ params }) => {
|
||||
return {
|
||||
code: "00000",
|
||||
data: noticeMap[params.id],
|
||||
msg: "一切ok",
|
||||
};
|
||||
},
|
||||
},
|
||||
// 修改通知
|
||||
{
|
||||
url: "notices/:id",
|
||||
method: ["PUT"],
|
||||
body({ body }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "修改通知" + body.title + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 删除通知
|
||||
{
|
||||
url: "notices/:id",
|
||||
method: ["DELETE"],
|
||||
body({ params }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "删除通知" + params.id + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 我的通知分页列表
|
||||
{
|
||||
url: "notices/my",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
list: [
|
||||
{
|
||||
id: "10",
|
||||
title: "v2.16.1 版本修复了 WebSocket 重复连接导致的后台线程阻塞问题,优化了通知公告。",
|
||||
type: 1,
|
||||
level: "L",
|
||||
publisherName: "系统管理员",
|
||||
publishTime: "2024-09-30 17:30",
|
||||
isRead: 0,
|
||||
},
|
||||
{
|
||||
id: "9",
|
||||
title: "公司将在 10 月 15 日举办新产品发布会,敬请期待。",
|
||||
type: 5,
|
||||
level: "L",
|
||||
publisherName: "系统管理员",
|
||||
publishTime: "2024-09-30 17:29",
|
||||
isRead: 0,
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
title: "国庆假期从 10 月 1 日至 10 月 7 日放假,共 7 天。",
|
||||
type: 4,
|
||||
level: "L",
|
||||
publisherName: "系统管理员",
|
||||
publishTime: "2024-09-30 17:28",
|
||||
isRead: 0,
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
title: "最近发现一些钓鱼邮件,请大家提高警惕,不要点击陌生链接。",
|
||||
type: 3,
|
||||
level: "L",
|
||||
publisherName: "系统管理员",
|
||||
publishTime: "2024-09-30 17:27",
|
||||
isRead: 0,
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
title: "系统将于本周六凌晨 2 点进行维护,预计维护时间为 2 小时。",
|
||||
type: 2,
|
||||
level: "L",
|
||||
publisherName: "系统管理员",
|
||||
publishTime: "2024-09-30 17:26",
|
||||
isRead: 0,
|
||||
},
|
||||
],
|
||||
total: 10,
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
// 通知映射表数据
|
||||
const noticeMap: Record<string, any> = {
|
||||
1: {
|
||||
id: "1",
|
||||
title: "v2.12.0 新增系统日志,访问趋势统计功能。",
|
||||
publishStatus: 1,
|
||||
type: 1,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
levelLabel: null,
|
||||
publishTime: "2024-09-30 17:21",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
2: {
|
||||
id: "2",
|
||||
title: "v2.13.0 新增菜单搜索。",
|
||||
publishStatus: 1,
|
||||
type: 1,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
levelLabel: null,
|
||||
publishTime: "2024-09-30 17:22",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
3: {
|
||||
id: "3",
|
||||
title: "\r\nv2.14.0 新增个人中心。",
|
||||
publishStatus: 1,
|
||||
type: 1,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
levelLabel: null,
|
||||
publishTime: "2024-09-30 17:23",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
4: {
|
||||
id: "4",
|
||||
title: "v2.15.0 登录页面改造。",
|
||||
publishStatus: 1,
|
||||
type: 1,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
levelLabel: null,
|
||||
publishTime: "2024-09-30 17:24",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
|
||||
5: {
|
||||
id: "5",
|
||||
title: "v2.16.0 通知公告、字典翻译组件。",
|
||||
publishStatus: 1,
|
||||
type: 1,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
levelLabel: null,
|
||||
publishTime: "2024-09-30 17:25",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
6: {
|
||||
id: "6",
|
||||
title: "系统将于本周六凌晨 2 点进行维护,预计维护时间为 2 小时。",
|
||||
publishStatus: 1,
|
||||
type: 2,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
levelLabel: null,
|
||||
publishTime: "2024-09-30 17:26",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
7: {
|
||||
id: "7",
|
||||
title: "最近发现一些钓鱼邮件,请大家提高警惕,不要点击陌生链接。",
|
||||
publishStatus: 1,
|
||||
type: 3,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
levelLabel: null,
|
||||
publishTime: "2024-09-30 17:27",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
8: {
|
||||
id: "8",
|
||||
title: "国庆假期从 10 月 1 日至 10 月 7 日放假,共 7 天。",
|
||||
publishStatus: 1,
|
||||
type: 4,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
levelLabel: null,
|
||||
publishTime: "2024-09-30 17:28",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
9: {
|
||||
id: "9",
|
||||
title: "公司将在 10 月 15 日举办新产品发布会,敬请期待。",
|
||||
publishStatus: 1,
|
||||
type: 5,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
levelLabel: null,
|
||||
publishTime: "2024-09-30 17:29",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
10: {
|
||||
id: "10",
|
||||
title: "v2.16.1 版本修复了 WebSocket 重复连接导致的后台线程阻塞问题,优化了通知公告。",
|
||||
publishStatus: 1,
|
||||
type: 1,
|
||||
publisherName: "系统管理员",
|
||||
level: "L",
|
||||
levelLabel: null,
|
||||
publishTime: "2024-09-30 17:30",
|
||||
isRead: null,
|
||||
targetType: 1,
|
||||
createTime: "2024-09-28 11:21",
|
||||
revokeTime: "2024-09-30 17:21",
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,250 @@
|
||||
import { defineMock } from "./base";
|
||||
|
||||
export default defineMock([
|
||||
{
|
||||
url: "roles/options",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: [
|
||||
{ value: "2", label: "系统管理员" },
|
||||
{ value: "4", label: "部门主管" },
|
||||
{ value: "5", label: "部门成员" },
|
||||
{ value: "6", label: "普通员工" },
|
||||
{ value: "7", label: "自定义权限用户" },
|
||||
{ value: "3", label: "访问游客" },
|
||||
],
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
url: "roles",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
list: [
|
||||
{
|
||||
id: "2",
|
||||
name: "系统管理员",
|
||||
code: "ADMIN",
|
||||
status: 1,
|
||||
sort: 2,
|
||||
dataScope: 1,
|
||||
createTime: "2021-03-25 12:39:54",
|
||||
updateTime: null,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
name: "访问游客",
|
||||
code: "GUEST",
|
||||
status: 1,
|
||||
sort: 3,
|
||||
dataScope: 3,
|
||||
createTime: "2021-05-26 15:49:05",
|
||||
updateTime: "2019-05-05 16:00:00",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
name: "部门主管",
|
||||
code: "DEPT_MANAGER",
|
||||
status: 1,
|
||||
sort: 4,
|
||||
dataScope: 2,
|
||||
createTime: "2021-03-25 12:39:54",
|
||||
updateTime: null,
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
name: "部门成员",
|
||||
code: "DEPT_MEMBER",
|
||||
status: 1,
|
||||
sort: 5,
|
||||
dataScope: 3,
|
||||
createTime: "2021-03-25 12:39:54",
|
||||
updateTime: null,
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
name: "普通员工",
|
||||
code: "EMPLOYEE",
|
||||
status: 1,
|
||||
sort: 6,
|
||||
dataScope: 4,
|
||||
createTime: "2021-03-25 12:39:54",
|
||||
updateTime: null,
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
name: "自定义权限用户",
|
||||
code: "CUSTOM_USER",
|
||||
status: 1,
|
||||
sort: 7,
|
||||
dataScope: 5,
|
||||
createTime: "2021-03-25 12:39:54",
|
||||
updateTime: null,
|
||||
},
|
||||
],
|
||||
total: 6,
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
|
||||
// 新增角色
|
||||
{
|
||||
url: "roles",
|
||||
method: ["POST"],
|
||||
body({ body }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "新增角色" + body.name + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 获取角色表单数据
|
||||
{
|
||||
url: "roles/:id/form",
|
||||
method: ["GET"],
|
||||
body: ({ params }) => {
|
||||
return {
|
||||
code: "00000",
|
||||
data: roleMap[params.id],
|
||||
msg: "一切ok",
|
||||
};
|
||||
},
|
||||
},
|
||||
// 修改角色
|
||||
{
|
||||
url: "roles/:id",
|
||||
method: ["PUT"],
|
||||
body({ body }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "修改角色" + body.name + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 删除角色
|
||||
{
|
||||
url: "roles/:id",
|
||||
method: ["DELETE"],
|
||||
body({ params }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "删除角色" + params.id + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
// 获取角色拥有的菜单ID
|
||||
{
|
||||
url: "roles/:id/menu-ids",
|
||||
method: ["GET"],
|
||||
body: () => {
|
||||
return {
|
||||
code: "00000",
|
||||
data: [
|
||||
1, 2, 31, 32, 33, 88, 3, 70, 71, 72, 4, 73, 75, 74, 5, 76, 77, 78, 6, 79, 81, 84, 85, 86,
|
||||
87, 40, 41, 26, 30, 20, 21, 22, 23, 24, 89, 90, 91, 36, 37, 38, 39, 93, 94, 95, 97, 102,
|
||||
89, 90, 91, 93, 94, 95, 97, 102, 103, 104,
|
||||
],
|
||||
msg: "一切ok",
|
||||
};
|
||||
},
|
||||
},
|
||||
// 保存角色菜单
|
||||
{
|
||||
url: "roles/:id/menus",
|
||||
method: ["PUT"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
|
||||
// 获取角色部门ID列表(自定义数据权限)
|
||||
{
|
||||
url: "roles/:id/dept-ids",
|
||||
method: ["GET"],
|
||||
body: ({ params }) => {
|
||||
const role = roleMap[params.id];
|
||||
return {
|
||||
code: "00000",
|
||||
data: role?.dataScope === 5 ? role.deptIds || [1, 2] : [],
|
||||
msg: "一切ok",
|
||||
};
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
// 角色映射表数据
|
||||
const roleMap: Record<string, any> = {
|
||||
2: {
|
||||
id: "2",
|
||||
name: "系统管理员",
|
||||
code: "ADMIN",
|
||||
status: 1,
|
||||
sort: 2,
|
||||
dataScope: 1,
|
||||
createTime: "2021-03-25 12:39:54",
|
||||
updateTime: null,
|
||||
},
|
||||
3: {
|
||||
id: "3",
|
||||
name: "访问游客",
|
||||
code: "GUEST",
|
||||
status: 1,
|
||||
sort: 3,
|
||||
dataScope: 3,
|
||||
createTime: "2021-05-26 15:49:05",
|
||||
updateTime: "2019-05-05 16:00:00",
|
||||
},
|
||||
4: {
|
||||
id: "4",
|
||||
name: "部门主管",
|
||||
code: "DEPT_MANAGER",
|
||||
status: 1,
|
||||
sort: 4,
|
||||
dataScope: 2,
|
||||
createTime: "2021-03-25 12:39:54",
|
||||
updateTime: null,
|
||||
},
|
||||
5: {
|
||||
id: "5",
|
||||
name: "部门成员",
|
||||
code: "DEPT_MEMBER",
|
||||
status: 1,
|
||||
sort: 5,
|
||||
dataScope: 3,
|
||||
createTime: "2021-03-25 12:39:54",
|
||||
updateTime: null,
|
||||
},
|
||||
6: {
|
||||
id: "6",
|
||||
name: "普通员工",
|
||||
code: "EMPLOYEE",
|
||||
status: 1,
|
||||
sort: 6,
|
||||
dataScope: 4,
|
||||
createTime: "2021-03-25 12:39:54",
|
||||
updateTime: null,
|
||||
},
|
||||
7: {
|
||||
id: "7",
|
||||
name: "自定义权限用户",
|
||||
code: "CUSTOM_USER",
|
||||
status: 1,
|
||||
sort: 7,
|
||||
dataScope: 5,
|
||||
deptIds: [1, 2],
|
||||
createTime: "2021-03-25 12:39:54",
|
||||
updateTime: null,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,125 @@
|
||||
import { defineMock } from "./base";
|
||||
|
||||
export default defineMock([
|
||||
{
|
||||
url: "tenant-plans",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
list: [
|
||||
{
|
||||
id: "1",
|
||||
name: "基础版",
|
||||
code: "BASIC",
|
||||
status: 1,
|
||||
sort: 1,
|
||||
remark: "",
|
||||
createTime: "2026-03-01 10:00:00",
|
||||
updateTime: "2026-03-01 10:00:00",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "专业版",
|
||||
code: "PRO",
|
||||
status: 1,
|
||||
sort: 2,
|
||||
remark: "",
|
||||
createTime: "2026-03-02 10:00:00",
|
||||
updateTime: "2026-03-02 10:00:00",
|
||||
},
|
||||
],
|
||||
total: 2,
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenant-plans/options",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: [
|
||||
{ value: "1", label: "基础版" },
|
||||
{ value: "2", label: "专业版" },
|
||||
],
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenant-plans/:planId/form",
|
||||
method: ["GET"],
|
||||
body: ({ params }) => {
|
||||
const planId = Number(params.planId);
|
||||
const form =
|
||||
planId === 2
|
||||
? {
|
||||
id: "2",
|
||||
name: "专业版",
|
||||
code: "PRO",
|
||||
status: 1,
|
||||
sort: 2,
|
||||
remark: "",
|
||||
}
|
||||
: {
|
||||
id: "1",
|
||||
name: "基础版",
|
||||
code: "BASIC",
|
||||
status: 1,
|
||||
sort: 1,
|
||||
remark: "",
|
||||
};
|
||||
|
||||
return {
|
||||
code: "00000",
|
||||
data: form,
|
||||
msg: "一切ok",
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenant-plans",
|
||||
method: ["POST"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenant-plans/:planId",
|
||||
method: ["PUT"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenant-plans/:ids",
|
||||
method: ["DELETE"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenant-plans/:planId/menuIds",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: [1, 2, 3, 4, 5, 6],
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenant-plans/:planId/menus",
|
||||
method: ["PUT"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
]);
|
||||
@@ -0,0 +1,264 @@
|
||||
import { defineMock } from "./base";
|
||||
|
||||
export default defineMock([
|
||||
{
|
||||
url: "tenants/options",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: [
|
||||
{
|
||||
id: "1",
|
||||
name: "默认租户",
|
||||
code: "default",
|
||||
contactName: "管理员",
|
||||
contactPhone: "17621210366",
|
||||
contactEmail: "",
|
||||
domain: "default",
|
||||
logo: "",
|
||||
planId: "1",
|
||||
status: 1,
|
||||
remark: "",
|
||||
expireTime: null,
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "演示租户",
|
||||
code: "demo",
|
||||
contactName: "演示用户",
|
||||
contactPhone: "17621210366",
|
||||
contactEmail: "",
|
||||
domain: "demo",
|
||||
logo: "",
|
||||
planId: "2",
|
||||
status: 1,
|
||||
remark: "",
|
||||
expireTime: null,
|
||||
isDefault: false,
|
||||
},
|
||||
],
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenants/current",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
id: "1",
|
||||
name: "默认租户",
|
||||
code: "default",
|
||||
contactName: "管理员",
|
||||
contactPhone: "17621210366",
|
||||
contactEmail: "",
|
||||
domain: "default",
|
||||
logo: "",
|
||||
planId: "1",
|
||||
status: 1,
|
||||
remark: "",
|
||||
expireTime: null,
|
||||
isDefault: true,
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenants",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
list: [
|
||||
{
|
||||
id: "1",
|
||||
name: "默认租户",
|
||||
code: "default",
|
||||
contactName: "管理员",
|
||||
contactPhone: "17621210366",
|
||||
contactEmail: "",
|
||||
domain: "default",
|
||||
logo: "",
|
||||
planId: "1",
|
||||
status: 1,
|
||||
remark: "",
|
||||
expireTime: null,
|
||||
createTime: "2026-03-01 10:00:00",
|
||||
updateTime: "2026-03-01 10:00:00",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "演示租户",
|
||||
code: "demo",
|
||||
contactName: "演示用户",
|
||||
contactPhone: "17621210366",
|
||||
contactEmail: "",
|
||||
domain: "demo",
|
||||
logo: "",
|
||||
planId: "2",
|
||||
status: 1,
|
||||
remark: "",
|
||||
expireTime: null,
|
||||
createTime: "2026-03-02 10:00:00",
|
||||
updateTime: "2026-03-02 10:00:00",
|
||||
},
|
||||
],
|
||||
total: 2,
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenants/:tenantId/form",
|
||||
method: ["GET"],
|
||||
body: ({ params }) => {
|
||||
const tenantId = Number(params.tenantId);
|
||||
const form =
|
||||
tenantId === 2
|
||||
? {
|
||||
id: "2",
|
||||
name: "演示租户",
|
||||
code: "demo",
|
||||
domain: "demo",
|
||||
contactName: "演示用户",
|
||||
contactPhone: "17621210366",
|
||||
contactEmail: "",
|
||||
logo: "",
|
||||
planId: "2",
|
||||
status: 1,
|
||||
remark: "",
|
||||
expireTime: null,
|
||||
}
|
||||
: {
|
||||
id: "1",
|
||||
name: "默认租户",
|
||||
code: "default",
|
||||
domain: "default",
|
||||
contactName: "管理员",
|
||||
contactPhone: "17621210366",
|
||||
contactEmail: "",
|
||||
logo: "",
|
||||
planId: "1",
|
||||
status: 1,
|
||||
remark: "",
|
||||
expireTime: null,
|
||||
};
|
||||
|
||||
return {
|
||||
code: "00000",
|
||||
data: form,
|
||||
msg: "一切ok",
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenants",
|
||||
method: ["POST"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
tenantId: "3",
|
||||
tenantCode: "test",
|
||||
tenantName: "测试租户",
|
||||
adminUsername: "admin",
|
||||
adminInitialPassword: "123456",
|
||||
adminRoleCode: "TENANT_ADMIN",
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenants/:tenantId",
|
||||
method: ["PUT"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenants/:ids",
|
||||
method: ["DELETE"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenants/:tenantId/status",
|
||||
method: ["PUT"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenants/:tenantId/menuIds",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: [1, 2, 3, 4, 5, 6],
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenants/:tenantId/menus",
|
||||
method: ["PUT"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "tenants/:tenantId/switch",
|
||||
method: ["POST"],
|
||||
body({ params }) {
|
||||
const tenantId = Number(params.tenantId);
|
||||
|
||||
const allTenants = [
|
||||
{
|
||||
id: "1",
|
||||
name: "默认租户",
|
||||
code: "default",
|
||||
contactName: "管理员",
|
||||
contactPhone: "17621210366",
|
||||
contactEmail: "",
|
||||
domain: "default",
|
||||
logo: "",
|
||||
planId: "1",
|
||||
status: 1,
|
||||
remark: "",
|
||||
expireTime: null,
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "演示租户",
|
||||
code: "demo",
|
||||
contactName: "演示用户",
|
||||
contactPhone: "17621210366",
|
||||
contactEmail: "",
|
||||
domain: "demo",
|
||||
logo: "",
|
||||
planId: "2",
|
||||
status: 1,
|
||||
remark: "",
|
||||
expireTime: null,
|
||||
isDefault: false,
|
||||
},
|
||||
];
|
||||
|
||||
const tenant = allTenants.find((t) => t.id === String(tenantId)) || null;
|
||||
|
||||
return {
|
||||
code: tenant ? "00000" : "A0400",
|
||||
data: tenant,
|
||||
msg: tenant ? "切换租户成功" : "租户不存在",
|
||||
};
|
||||
},
|
||||
},
|
||||
]);
|
||||
@@ -0,0 +1,250 @@
|
||||
import { defineMock } from "./base";
|
||||
|
||||
export default defineMock([
|
||||
{
|
||||
url: "users/me",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
userId: "2",
|
||||
username: "admin",
|
||||
nickname: "系统管理员",
|
||||
avatar: "https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif",
|
||||
roles: ["ADMIN"],
|
||||
perms: [
|
||||
"sys:user:list",
|
||||
"sys:user:create",
|
||||
"sys:user:update",
|
||||
"sys:user:delete",
|
||||
"sys:user:import",
|
||||
"sys:user:export",
|
||||
"sys:user:reset-password",
|
||||
|
||||
"sys:role:list",
|
||||
"sys:role:create",
|
||||
"sys:role:update",
|
||||
"sys:role:delete",
|
||||
|
||||
"sys:dept:list",
|
||||
"sys:dept:create",
|
||||
"sys:dept:update",
|
||||
"sys:dept:delete",
|
||||
|
||||
"sys:menu:list",
|
||||
"sys:menu:create",
|
||||
"sys:menu:update",
|
||||
"sys:menu:delete",
|
||||
|
||||
"sys:dict:list",
|
||||
"sys:dict:create",
|
||||
"sys:dict:update",
|
||||
"sys:dict:delete",
|
||||
|
||||
"sys:dict-item:list",
|
||||
"sys:dict-item:create",
|
||||
"sys:dict-item:update",
|
||||
"sys:dict-item:delete",
|
||||
|
||||
"sys:notice:list",
|
||||
"sys:notice:create",
|
||||
"sys:notice:update",
|
||||
"sys:notice:delete",
|
||||
"sys:notice:revoke",
|
||||
"sys:notice:publish",
|
||||
|
||||
"sys:config:list",
|
||||
"sys:config:create",
|
||||
"sys:config:update",
|
||||
"sys:config:delete",
|
||||
"sys:config:refresh",
|
||||
],
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
url: "users",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
list: [
|
||||
{
|
||||
id: "2",
|
||||
username: "admin",
|
||||
nickname: "系统管理员",
|
||||
mobile: "17621210366",
|
||||
gender: 1,
|
||||
avatar: "https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif",
|
||||
email: "",
|
||||
status: 1,
|
||||
deptId: "1",
|
||||
roleIds: [2],
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
username: "test",
|
||||
nickname: "测试小用户",
|
||||
mobile: "17621210366",
|
||||
gender: 1,
|
||||
avatar: "https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif",
|
||||
email: "youlaitech@163.com",
|
||||
status: 1,
|
||||
deptId: "3",
|
||||
roleIds: [3],
|
||||
},
|
||||
],
|
||||
total: 2,
|
||||
},
|
||||
msg: "一切ok",
|
||||
},
|
||||
},
|
||||
|
||||
// 新增用户
|
||||
{
|
||||
url: "users",
|
||||
method: ["POST"],
|
||||
body({ body }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "新增用户" + body.nickname + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 获取用户表单数据
|
||||
{
|
||||
url: "users/:userId/form",
|
||||
method: ["GET"],
|
||||
body: ({ params }) => {
|
||||
return {
|
||||
code: "00000",
|
||||
data: userMap[params.userId],
|
||||
msg: "一切ok",
|
||||
};
|
||||
},
|
||||
},
|
||||
// 修改用户
|
||||
{
|
||||
url: "users/:userId",
|
||||
method: ["PUT"],
|
||||
body({ body }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "修改用户" + body.nickname + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 删除用户
|
||||
{
|
||||
url: "users/:userId",
|
||||
method: ["DELETE"],
|
||||
body({ params }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "删除用户" + params.userId + "成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 重置密码
|
||||
{
|
||||
url: "users/:userId/password/reset",
|
||||
method: ["PUT"],
|
||||
body({ query }) {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "重置密码成功,新密码为:" + query.password,
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// 导出Excel
|
||||
{
|
||||
url: "users/export",
|
||||
method: ["GET"],
|
||||
headers: {
|
||||
"Content-Disposition": "attachment; filename=%E7%94%A8%E6%88%B7%E5%88%97%E8%A1%A8.xlsx",
|
||||
"Content-Type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
url: "users/profile",
|
||||
method: ["GET"],
|
||||
body: {
|
||||
code: "00000",
|
||||
data: {
|
||||
id: "2",
|
||||
username: "admin",
|
||||
nickname: "系统管理员",
|
||||
avatar: "https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif",
|
||||
gender: 1,
|
||||
mobile: "17621210366",
|
||||
email: null,
|
||||
deptName: "有来技术",
|
||||
roleNames: "系统管理员",
|
||||
createTime: "2019-10-10",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
url: "users/profile",
|
||||
method: ["PUT"],
|
||||
body() {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "修改个人信息成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
url: "users/password",
|
||||
method: ["PUT"],
|
||||
body() {
|
||||
return {
|
||||
code: "00000",
|
||||
data: null,
|
||||
msg: "修改密码成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
// 用户映射表数据
|
||||
const userMap: Record<string, any> = {
|
||||
2: {
|
||||
id: "2",
|
||||
username: "admin",
|
||||
nickname: "系统管理员",
|
||||
mobile: "17621210366",
|
||||
gender: 1,
|
||||
avatar: "https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif",
|
||||
email: "",
|
||||
status: 1,
|
||||
deptId: "1",
|
||||
roleIds: [2],
|
||||
},
|
||||
3: {
|
||||
id: "3",
|
||||
username: "test",
|
||||
nickname: "测试小用户",
|
||||
mobile: "17621210366",
|
||||
gender: 1,
|
||||
avatar: "https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif",
|
||||
email: "youlaitech@163.com",
|
||||
status: 1,
|
||||
deptId: "3",
|
||||
roleIds: [3],
|
||||
},
|
||||
};
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
{
|
||||
"name": "vue3-element-admin",
|
||||
"description": "Vue3 + Vite + TypeScript + Element-Plus 的后台管理模板,vue-element-admin 的 Vue3 版本",
|
||||
"version": "4.4.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
"preview": "vite preview",
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --noEmit",
|
||||
"lint:eslint": "eslint --cache \"src/**/*.{vue,ts,js}\" --fix",
|
||||
"lint:prettier": "prettier --write \"**/*.{js,cjs,ts,json,css,scss,vue,html,md}\"",
|
||||
"lint:stylelint": "stylelint --cache \"**/*.{css,scss,vue}\" --fix",
|
||||
"lint:lint-staged": "lint-staged",
|
||||
"lint": "npm run lint:eslint && npm run lint:prettier && npm run lint:stylelint",
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"prepare": "husky",
|
||||
"commit": "git-cz"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "node_modules/cz-git"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,ts}": [
|
||||
"eslint --fix",
|
||||
"prettier --write"
|
||||
],
|
||||
"*.{cjs,json}": [
|
||||
"prettier --write"
|
||||
],
|
||||
"*.{vue,html}": [
|
||||
"eslint --fix",
|
||||
"prettier --write",
|
||||
"stylelint --fix"
|
||||
],
|
||||
"*.{scss,css}": [
|
||||
"stylelint --fix",
|
||||
"prettier --write"
|
||||
],
|
||||
"*.md": [
|
||||
"prettier --write"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.2",
|
||||
"@vueuse/core": "^14.2.1",
|
||||
"@wangeditor-next/editor": "^5.6.49",
|
||||
"@wangeditor-next/editor-for-vue": "^5.1.14",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^1.13.6",
|
||||
"codemirror": "^5.65.16",
|
||||
"codemirror-editor-vue3": "^2.8.0",
|
||||
"echarts": "^6.0.0",
|
||||
"element-plus": "^2.13.6",
|
||||
"exceljs": "^4.4.0",
|
||||
"lodash-es": "^4.17.23",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"path-to-regexp": "^8.3.0",
|
||||
"pinia": "^3.0.4",
|
||||
"qs": "^6.15.0",
|
||||
"sortablejs": "^1.15.7",
|
||||
"vue": "^3.5.30",
|
||||
"vue-draggable-plus": "^0.6.1",
|
||||
"vue-i18n": "^11.3.0",
|
||||
"vue-router": "^5.0.3",
|
||||
"vxe-table": "~4.6.25"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^20.5.0",
|
||||
"@commitlint/config-conventional": "^20.5.0",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@iconify/utils": "^3.1.0",
|
||||
"@types/codemirror": "^5.60.17",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^25.5.0",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/path-browserify": "^1.0.3",
|
||||
"@types/qs": "^6.15.0",
|
||||
"@types/sortablejs": "^1.15.9",
|
||||
"@vitejs/plugin-vue": "^6.0.5",
|
||||
"autoprefixer": "^10.4.27",
|
||||
"commitizen": "^4.3.1",
|
||||
"cz-git": "^1.12.0",
|
||||
"eslint": "^10.0.3",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.5",
|
||||
"eslint-plugin-vue": "^10.8.0",
|
||||
"globals": "^17.4.0",
|
||||
"husky": "^9.1.7",
|
||||
"jiti": "^2.6.1",
|
||||
"lint-staged": "^16.4.0",
|
||||
"postcss": "^8.5.8",
|
||||
"postcss-html": "^1.8.1",
|
||||
"postcss-scss": "^4.0.9",
|
||||
"prettier": "^3.8.1",
|
||||
"sass": "^1.98.0",
|
||||
"stylelint": "^17.4.0",
|
||||
"stylelint-config-html": "^1.1.0",
|
||||
"stylelint-config-recess-order": "^7.6.1",
|
||||
"stylelint-config-recommended": "^18.0.0",
|
||||
"stylelint-config-recommended-scss": "^17.0.0",
|
||||
"stylelint-config-recommended-vue": "^1.6.1",
|
||||
"stylelint-prettier": "^5.0.3",
|
||||
"terser": "^5.46.0",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.57.2",
|
||||
"unocss": "^66.6.6",
|
||||
"unplugin-auto-import": "^21.0.0",
|
||||
"unplugin-vue-components": "^32.0.0",
|
||||
"vite": "^8.0.0",
|
||||
"vite-plugin-mock-dev-server": "^2.1.1",
|
||||
"vue-eslint-parser": "^10.4.0",
|
||||
"vue-tsc": "^3.2.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"repository": "https://gitee.com/youlaiorg/vue3-element-admin.git",
|
||||
"author": "有来开源组织",
|
||||
"license": "MIT"
|
||||
}
|
||||
Generated
+7348
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<el-config-provider :locale="locale" :size="size">
|
||||
<!-- 开启水印-->
|
||||
<el-watermark
|
||||
:font="{ color: fontColor }"
|
||||
:content="showWatermark ? watermarkContent : ''"
|
||||
:z-index="9999"
|
||||
class="wh-full"
|
||||
>
|
||||
<router-view />
|
||||
</el-watermark>
|
||||
</el-config-provider>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useAppStore, useSettingsStore } from "@/store";
|
||||
import { appConfig } from "@/settings";
|
||||
import { ThemeMode, ComponentSize } from "@/enums";
|
||||
|
||||
const appStore = useAppStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
|
||||
const locale = computed(() => appStore.locale);
|
||||
const size = computed(() => appStore.size as ComponentSize);
|
||||
const showWatermark = computed(() => settingsStore.showWatermark);
|
||||
const watermarkContent = appConfig.name;
|
||||
|
||||
// 明亮/暗黑主题水印字体颜色适配
|
||||
const fontColor = computed(() => {
|
||||
return settingsStore.theme === ThemeMode.DARK ? "rgba(255, 255, 255, .15)" : "rgba(0, 0, 0, .15)";
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,69 @@
|
||||
import request from "@/utils/request";
|
||||
import type { LoginRequest, LoginResponse, CaptchaInfo } from "./types";
|
||||
|
||||
const AUTH_BASE_URL = "/api/v1/auth";
|
||||
|
||||
const AuthAPI = {
|
||||
/** 登录接口*/
|
||||
login(data: LoginRequest) {
|
||||
const payload: Record<string, any> = {
|
||||
username: data.username,
|
||||
password: data.password,
|
||||
captchaId: data.captchaId,
|
||||
captchaCode: data.captchaCode,
|
||||
};
|
||||
|
||||
// tenantId 可选,仅在提供时包含(多租户功能)
|
||||
if (typeof data.tenantId !== "undefined") {
|
||||
payload.tenantId = data.tenantId;
|
||||
}
|
||||
|
||||
return request<any, LoginResponse>({
|
||||
url: `${AUTH_BASE_URL}/login`,
|
||||
method: "post",
|
||||
data: payload,
|
||||
});
|
||||
},
|
||||
|
||||
/** 切换租户(平台用户) - 返回新的 token */
|
||||
switchTenant(tenantId: number) {
|
||||
return request<any, LoginResponse>({
|
||||
url: `${AUTH_BASE_URL}/switch-tenant`,
|
||||
method: "post",
|
||||
params: { tenantId },
|
||||
});
|
||||
},
|
||||
|
||||
/** 刷新 token 接口*/
|
||||
refreshToken(refreshToken: string) {
|
||||
return request<any, LoginResponse>({
|
||||
url: `${AUTH_BASE_URL}/refresh-token`,
|
||||
method: "post",
|
||||
params: { refreshToken },
|
||||
headers: {
|
||||
Authorization: "no-auth",
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
/** 退出登录接口 */
|
||||
logout() {
|
||||
return request({
|
||||
url: `${AUTH_BASE_URL}/logout`,
|
||||
method: "delete",
|
||||
});
|
||||
},
|
||||
|
||||
/** 获取验证码接口*/
|
||||
getCaptcha() {
|
||||
return request<any, CaptchaInfo>({
|
||||
url: `${AUTH_BASE_URL}/captcha`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default AuthAPI;
|
||||
|
||||
// 重导出类型
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 认证相关类型定义
|
||||
*/
|
||||
|
||||
/**
|
||||
* 登录请求参数
|
||||
*/
|
||||
export interface LoginRequest {
|
||||
/** 用户名 */
|
||||
username: string;
|
||||
/** 密码 */
|
||||
password: string;
|
||||
/** 验证码缓存key */
|
||||
captchaId?: string;
|
||||
/** 验证码 */
|
||||
captchaCode?: string;
|
||||
/** 记住我 */
|
||||
rememberMe?: boolean;
|
||||
/** 租户ID */
|
||||
tenantId?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录响应
|
||||
*/
|
||||
export interface LoginResponse {
|
||||
/** 访问令牌 */
|
||||
accessToken: string;
|
||||
/** 刷新令牌 */
|
||||
refreshToken: string;
|
||||
/** 令牌类型 */
|
||||
tokenType: string;
|
||||
/** 过期时间(单位:秒) */
|
||||
expiresIn: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证码响应
|
||||
*/
|
||||
export interface CaptchaInfo {
|
||||
/** 验证码缓存key */
|
||||
captchaId: string;
|
||||
/** 验证码图片Base64 */
|
||||
captchaBase64: string;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 通用 API 类型定义
|
||||
*/
|
||||
|
||||
/** API 响应结构 */
|
||||
export interface ApiResponse<T = any> {
|
||||
/** 响应码 */
|
||||
code: string;
|
||||
/** 响应数据 */
|
||||
data: T;
|
||||
/** 响应消息 */
|
||||
msg: string;
|
||||
}
|
||||
|
||||
/** 基础查询参数 */
|
||||
export interface BaseQueryParams {
|
||||
/** 页码 */
|
||||
pageNum: number;
|
||||
/** 每页记录数 */
|
||||
pageSize: number;
|
||||
|
||||
/** 排序字段 */
|
||||
sortBy?: string;
|
||||
|
||||
/** 排序方式(正序:ASC;反序:DESC) */
|
||||
order?: string;
|
||||
}
|
||||
|
||||
/** 分页数据结构(仅分页接口) */
|
||||
export interface PageResult<T> {
|
||||
/** 数据列表 */
|
||||
list: T[];
|
||||
/** 总记录数 */
|
||||
total: number;
|
||||
}
|
||||
|
||||
/** 下拉选项 */
|
||||
export interface OptionItem {
|
||||
/** 选项值 */
|
||||
value: string | number;
|
||||
/** 选项标签 */
|
||||
label: string;
|
||||
/** 子选项 */
|
||||
children?: OptionItem[];
|
||||
}
|
||||
|
||||
/** Excel 导入结果 */
|
||||
export interface ExcelResult {
|
||||
/** 响应码 */
|
||||
code: string;
|
||||
/** 无效数据数量 */
|
||||
invalidCount: number;
|
||||
/** 有效数据数量 */
|
||||
validCount: number;
|
||||
/** 错误信息列表 */
|
||||
messageList: string[];
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import request from "@/utils/request";
|
||||
import type { FileInfo } from "./types";
|
||||
|
||||
const FileAPI = {
|
||||
/** 上传文件 (传入 FormData,上传进度回调) */
|
||||
upload(formData: FormData, onProgress?: (percent: number) => void) {
|
||||
return request<any, FileInfo>({
|
||||
url: "/api/v1/files",
|
||||
method: "post",
|
||||
data: formData,
|
||||
headers: { "Content-Type": "multipart/form-data" },
|
||||
onUploadProgress: (progressEvent) => {
|
||||
if (progressEvent.total) {
|
||||
const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total);
|
||||
onProgress?.(percent);
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
/** 上传文件(传入 File) */
|
||||
uploadFile(file: File) {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
return request<any, FileInfo>({
|
||||
url: "/api/v1/files",
|
||||
method: "post",
|
||||
data: formData,
|
||||
headers: { "Content-Type": "multipart/form-data" },
|
||||
});
|
||||
},
|
||||
|
||||
/** 删除文件 */
|
||||
delete(filePath?: string) {
|
||||
return request({
|
||||
url: "/api/v1/files",
|
||||
method: "delete",
|
||||
params: { filePath },
|
||||
});
|
||||
},
|
||||
|
||||
/** 下载文件 */
|
||||
download(url: string, fileName?: string) {
|
||||
return request({
|
||||
url,
|
||||
method: "get",
|
||||
responseType: "blob",
|
||||
}).then((res) => {
|
||||
const blob = new Blob([res.data]);
|
||||
const a = document.createElement("a");
|
||||
const urlObject = window.URL.createObjectURL(blob);
|
||||
a.href = urlObject;
|
||||
a.download = fileName || "下载文件";
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(urlObject);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default FileAPI;
|
||||
|
||||
// 重导出类型
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* File 文件上传类型定义
|
||||
*/
|
||||
|
||||
/** 文件信息 */
|
||||
export interface FileInfo {
|
||||
/** 文件名称 */
|
||||
name: string;
|
||||
/** 文件URL */
|
||||
url: string;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import request from "@/utils/request";
|
||||
import type { MemberAuthConfig, MemberAuthTestEmailRequest } from "./types";
|
||||
|
||||
const MEMBER_AUTH_CONFIG_BASE_URL = "/api/v1/admin/member/auth-config";
|
||||
|
||||
const MemberAuthConfigAPI = {
|
||||
getConfig() {
|
||||
return request<any, MemberAuthConfig>({
|
||||
url: MEMBER_AUTH_CONFIG_BASE_URL,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
updateConfig(data: MemberAuthConfig) {
|
||||
return request<any, MemberAuthConfig>({
|
||||
url: MEMBER_AUTH_CONFIG_BASE_URL,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
sendTestEmail(data: MemberAuthTestEmailRequest) {
|
||||
return request<any, void>({
|
||||
url: `${MEMBER_AUTH_CONFIG_BASE_URL}/test-email`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default MemberAuthConfigAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,28 @@
|
||||
export interface VerificationChannelConfig {
|
||||
enabled?: boolean;
|
||||
providerType?: string;
|
||||
expireSeconds?: number;
|
||||
senderName?: string;
|
||||
senderNickname?: string;
|
||||
emailTitle?: string;
|
||||
brandName?: string;
|
||||
footerText?: string;
|
||||
host?: string;
|
||||
port?: number;
|
||||
username?: string;
|
||||
password?: string;
|
||||
endpoint?: string;
|
||||
sslEnabled?: boolean;
|
||||
}
|
||||
|
||||
export interface MemberAuthConfig {
|
||||
registerMethods?: string[];
|
||||
loginMethods?: string[];
|
||||
mobileVerification?: VerificationChannelConfig;
|
||||
emailVerification?: VerificationChannelConfig;
|
||||
}
|
||||
|
||||
export interface MemberAuthTestEmailRequest {
|
||||
testEmail: string;
|
||||
emailVerification: VerificationChannelConfig;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import request from "@/utils/request";
|
||||
import type { MemberPurposeTagConfig } from "./types";
|
||||
|
||||
const MEMBER_PURPOSE_TAG_CONFIG_BASE_URL = "/api/v1/admin/member/purpose-tag-config";
|
||||
|
||||
const MemberPurposeTagConfigAPI = {
|
||||
getConfig() {
|
||||
return request<any, MemberPurposeTagConfig>({
|
||||
url: MEMBER_PURPOSE_TAG_CONFIG_BASE_URL,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
updateConfig(data: MemberPurposeTagConfig) {
|
||||
return request<any, MemberPurposeTagConfig>({
|
||||
url: MEMBER_PURPOSE_TAG_CONFIG_BASE_URL,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default MemberPurposeTagConfigAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,10 @@
|
||||
export interface MemberPurposeTagItem {
|
||||
id?: string;
|
||||
targetName?: string;
|
||||
targetType?: string;
|
||||
hotType?: boolean;
|
||||
}
|
||||
|
||||
export interface MemberPurposeTagConfig {
|
||||
items?: MemberPurposeTagItem[];
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import request from "@/utils/request";
|
||||
import type { MemberSiteConfig } from "./types";
|
||||
|
||||
const MEMBER_SITE_CONFIG_BASE_URL = "/api/v1/admin/member/site-config";
|
||||
|
||||
const MemberSiteConfigAPI = {
|
||||
getConfig() {
|
||||
return request<any, MemberSiteConfig>({
|
||||
url: MEMBER_SITE_CONFIG_BASE_URL,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
updateConfig(data: MemberSiteConfig) {
|
||||
return request<any, MemberSiteConfig>({
|
||||
url: MEMBER_SITE_CONFIG_BASE_URL,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default MemberSiteConfigAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,9 @@
|
||||
export interface MemberSiteConfig {
|
||||
siteName?: string;
|
||||
siteFaviconUrl?: string;
|
||||
siteLogoUrl?: string;
|
||||
customerServiceType?: "QR_CODE" | "URL";
|
||||
customerServiceQrUrl?: string;
|
||||
customerServiceUrl?: string;
|
||||
homeFooterContent?: string;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import request from "@/utils/request";
|
||||
import type {
|
||||
MemberDistributionDetailItem,
|
||||
MemberUserAgentLevelForm,
|
||||
MemberUserForm,
|
||||
MemberUserItem,
|
||||
MemberUserQueryParams,
|
||||
MemberUserStatusForm,
|
||||
MemberWalletItem,
|
||||
} from "./types";
|
||||
|
||||
const MEMBER_USER_BASE_URL = "/api/v1/admin/member/users";
|
||||
|
||||
const MemberUserAPI = {
|
||||
getPage(queryParams?: MemberUserQueryParams) {
|
||||
return request<any, PageResult<MemberUserItem>>({
|
||||
url: MEMBER_USER_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
create(data: MemberUserForm) {
|
||||
return request({
|
||||
url: MEMBER_USER_BASE_URL,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
getDetail(id: number) {
|
||||
return request<any, MemberUserItem>({
|
||||
url: `${MEMBER_USER_BASE_URL}/${id}`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
update(id: number, data: MemberUserForm) {
|
||||
return request({
|
||||
url: `${MEMBER_USER_BASE_URL}/${id}`,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
updateStatus(id: number, data: MemberUserStatusForm) {
|
||||
return request({
|
||||
url: `${MEMBER_USER_BASE_URL}/${id}/status`,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
updateAgentLevel(id: number, data: MemberUserAgentLevelForm) {
|
||||
return request({
|
||||
url: `${MEMBER_USER_BASE_URL}/${id}/agent-level`,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
getWallet(id: number) {
|
||||
return request<any, MemberWalletItem>({
|
||||
url: `${MEMBER_USER_BASE_URL}/${id}/wallet`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
getDistributionDetail(id: number) {
|
||||
return request<any, MemberDistributionDetailItem>({
|
||||
url: `${MEMBER_USER_BASE_URL}/${id}/distribution`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default MemberUserAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,107 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface MemberUserQueryParams extends BaseQueryParams {
|
||||
keywords?: string;
|
||||
status?: number;
|
||||
source?: string;
|
||||
verifyStatus?: number;
|
||||
agentLevel?: number;
|
||||
inviteCode?: string;
|
||||
parentInviteCode?: string;
|
||||
}
|
||||
|
||||
export interface MemberUserItem {
|
||||
id?: number;
|
||||
username?: string;
|
||||
nickname?: string;
|
||||
avatar?: string;
|
||||
mobile?: string;
|
||||
email?: string;
|
||||
status?: number;
|
||||
source?: string;
|
||||
wxOpenid?: string;
|
||||
wxUnionid?: string;
|
||||
lastLoginTime?: string;
|
||||
lastLoginIp?: string;
|
||||
remark?: string;
|
||||
verifyStatus?: number;
|
||||
realName?: string;
|
||||
lastVerifyRecordId?: number;
|
||||
lastSubmitTime?: string;
|
||||
verifiedTime?: string;
|
||||
auditTime?: string;
|
||||
auditRemark?: string;
|
||||
inviteCode?: string;
|
||||
agentLevel?: number;
|
||||
parentMemberUserId?: number;
|
||||
parentUsername?: string;
|
||||
parentMobile?: string;
|
||||
parentInviteCode?: string;
|
||||
grandParentMemberUserId?: number;
|
||||
grandParentUsername?: string;
|
||||
grandParentMobile?: string;
|
||||
grandParentInviteCode?: string;
|
||||
bindSource?: string;
|
||||
bindTime?: string;
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
export interface MemberDistributionDetailItem {
|
||||
memberUserId?: number;
|
||||
username?: string;
|
||||
nickname?: string;
|
||||
mobile?: string;
|
||||
inviteCode?: string;
|
||||
agentLevel?: number;
|
||||
parentMemberUserId?: number;
|
||||
parentUsername?: string;
|
||||
parentMobile?: string;
|
||||
parentInviteCode?: string;
|
||||
grandParentMemberUserId?: number;
|
||||
grandParentUsername?: string;
|
||||
grandParentMobile?: string;
|
||||
grandParentInviteCode?: string;
|
||||
bindSource?: string;
|
||||
bindTime?: string;
|
||||
hasOpenSuccessOrder?: boolean;
|
||||
hasCommissionRecord?: boolean;
|
||||
openSuccessOrderCount?: number;
|
||||
commissionRecordCount?: number;
|
||||
}
|
||||
|
||||
export interface MemberUserForm {
|
||||
id?: number;
|
||||
mobile?: string;
|
||||
username?: string;
|
||||
nickname?: string;
|
||||
password?: string;
|
||||
avatar?: string;
|
||||
email?: string;
|
||||
source?: string;
|
||||
status?: number;
|
||||
agentLevel?: number;
|
||||
remark?: string;
|
||||
initialBalance?: number;
|
||||
}
|
||||
|
||||
export interface MemberUserStatusForm {
|
||||
status?: number;
|
||||
}
|
||||
|
||||
export interface MemberUserAgentLevelForm {
|
||||
agentLevel?: number;
|
||||
}
|
||||
|
||||
export interface MemberWalletItem {
|
||||
id?: number;
|
||||
memberUserId?: number;
|
||||
balance?: number;
|
||||
frozenBalance?: number;
|
||||
totalRechargeAmount?: number;
|
||||
totalConsumeAmount?: number;
|
||||
totalRefundAmount?: number;
|
||||
status?: number;
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import request from "@/utils/request";
|
||||
import type {
|
||||
MemberVerifyAuditForm,
|
||||
MemberVerifyPolicy,
|
||||
MemberVerifyRecordDetail,
|
||||
MemberVerifyRecordItem,
|
||||
MemberVerifyRecordQueryParams,
|
||||
} from "./types";
|
||||
|
||||
const MEMBER_VERIFY_POLICY_BASE_URL = "/api/v1/admin/member/verify-policy";
|
||||
const MEMBER_VERIFY_RECORD_BASE_URL = "/api/v1/admin/member/verify-records";
|
||||
|
||||
const MemberVerifyAPI = {
|
||||
getPolicy() {
|
||||
return request<any, MemberVerifyPolicy>({
|
||||
url: MEMBER_VERIFY_POLICY_BASE_URL,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
updatePolicy(data: MemberVerifyPolicy) {
|
||||
return request<any, MemberVerifyPolicy>({
|
||||
url: MEMBER_VERIFY_POLICY_BASE_URL,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
getPage(queryParams?: MemberVerifyRecordQueryParams) {
|
||||
return request<any, PageResult<MemberVerifyRecordItem>>({
|
||||
url: MEMBER_VERIFY_RECORD_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getDetail(id: number) {
|
||||
return request<any, MemberVerifyRecordDetail>({
|
||||
url: `${MEMBER_VERIFY_RECORD_BASE_URL}/${id}`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
audit(id: number, data: MemberVerifyAuditForm) {
|
||||
return request({
|
||||
url: `${MEMBER_VERIFY_RECORD_BASE_URL}/${id}/audit`,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default MemberVerifyAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,73 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface MemberVerifyFieldPolicy {
|
||||
code?: string;
|
||||
label?: string;
|
||||
type?: string;
|
||||
enabled?: boolean;
|
||||
required?: boolean;
|
||||
readonly?: boolean;
|
||||
source?: string;
|
||||
maxCount?: number;
|
||||
sort?: number;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
export interface MemberVerifyPolicy {
|
||||
enabled?: boolean;
|
||||
forceRequired?: boolean;
|
||||
forceScenes?: string[];
|
||||
fields?: MemberVerifyFieldPolicy[];
|
||||
}
|
||||
|
||||
export interface MemberVerifyRecordQueryParams extends BaseQueryParams {
|
||||
keywords?: string;
|
||||
status?: number;
|
||||
memberUserId?: number;
|
||||
}
|
||||
|
||||
export interface MemberVerifyRecordItem {
|
||||
id?: number;
|
||||
verifyNo?: string;
|
||||
memberUserId?: number;
|
||||
usernameSnapshot?: string;
|
||||
nicknameSnapshot?: string;
|
||||
mobileSnapshot?: string;
|
||||
realName?: string;
|
||||
status?: number;
|
||||
submitRemark?: string;
|
||||
submitTime?: string;
|
||||
auditTime?: string;
|
||||
auditBy?: number;
|
||||
auditRemark?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
export interface MemberVerifyRecordDetail {
|
||||
id?: number;
|
||||
verifyNo?: string;
|
||||
memberUserId?: number;
|
||||
usernameSnapshot?: string;
|
||||
nicknameSnapshot?: string;
|
||||
mobileSnapshot?: string;
|
||||
realName?: string;
|
||||
idCardNo?: string;
|
||||
idCardFrontUrl?: string;
|
||||
idCardBackUrl?: string;
|
||||
supportDocs?: string[];
|
||||
status?: number;
|
||||
submitRemark?: string;
|
||||
submitTime?: string;
|
||||
auditTime?: string;
|
||||
auditBy?: number;
|
||||
auditRemark?: string;
|
||||
policySnapshot?: MemberVerifyPolicy;
|
||||
formData?: Record<string, any>;
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
export interface MemberVerifyAuditForm {
|
||||
status?: number;
|
||||
auditRemark?: string;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export { default } from "@/api/proxy/region";
|
||||
export type { RegionForm as CityLibraryForm, RegionItem as CityLibraryItem, RegionQueryParams as CityLibraryQueryParams } from "@/api/proxy/region";
|
||||
@@ -0,0 +1 @@
|
||||
export type { RegionForm as CityLibraryForm, RegionItem as CityLibraryItem, RegionQueryParams as CityLibraryQueryParams } from "@/api/proxy/region/types";
|
||||
@@ -0,0 +1,48 @@
|
||||
import request from "@/utils/request";
|
||||
import type { CityForm, CityItem, CityQueryParams } from "./types";
|
||||
|
||||
const CITY_BASE_URL = "/api/v1/proxy/cities";
|
||||
|
||||
const CityAPI = {
|
||||
getPage(queryParams?: CityQueryParams) {
|
||||
return request<any, PageResult<CityItem>>({
|
||||
url: CITY_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getFormData(id: string) {
|
||||
return request<any, CityForm>({
|
||||
url: `${CITY_BASE_URL}/${id}/form`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
create(data: CityForm) {
|
||||
return request({
|
||||
url: CITY_BASE_URL,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
update(id: string, data: CityForm) {
|
||||
return request({
|
||||
url: `${CITY_BASE_URL}/${id}`,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
deleteById(id: string) {
|
||||
return request({
|
||||
url: `${CITY_BASE_URL}/${id}`,
|
||||
method: "delete",
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default CityAPI;
|
||||
|
||||
export type { CityForm, CityItem, CityQueryParams };
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface CityQueryParams extends BaseQueryParams {
|
||||
keywords?: string;
|
||||
regionCode?: string;
|
||||
}
|
||||
|
||||
export interface CityItem {
|
||||
id?: string;
|
||||
city?: string;
|
||||
cityCn?: string;
|
||||
regionCode?: string;
|
||||
state?: string;
|
||||
countryName?: string;
|
||||
}
|
||||
|
||||
export interface CityForm {
|
||||
id?: string;
|
||||
city?: string;
|
||||
cityCn?: string;
|
||||
regionCode?: string;
|
||||
state?: string;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
import request from "@/utils/request";
|
||||
import type {
|
||||
DistributionCommissionItem,
|
||||
DistributionCommissionQueryParams,
|
||||
DistributionConfigModel,
|
||||
DistributionWithdrawApproveForm,
|
||||
DistributionWithdrawItem,
|
||||
DistributionWithdrawPayForm,
|
||||
DistributionWithdrawQueryParams,
|
||||
DistributionWithdrawRejectForm,
|
||||
} from "./types";
|
||||
|
||||
const DISTRIBUTION_CONFIG_BASE_URL = "/api/v1/proxy/distribution-config";
|
||||
const DISTRIBUTION_COMMISSION_BASE_URL = "/api/v1/proxy/distribution-commissions";
|
||||
const DISTRIBUTION_WITHDRAW_BASE_URL = "/api/v1/proxy/distribution-withdraws";
|
||||
|
||||
const DistributionAPI = {
|
||||
/**
|
||||
* 获取当前分销配置
|
||||
*/
|
||||
getCurrentConfig() {
|
||||
return request<any, DistributionConfigModel>({
|
||||
url: DISTRIBUTION_CONFIG_BASE_URL,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 保存当前分销配置
|
||||
*/
|
||||
updateCurrentConfig(data: DistributionConfigModel) {
|
||||
return request({
|
||||
url: DISTRIBUTION_CONFIG_BASE_URL,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取佣金流水分页数据
|
||||
*/
|
||||
getCommissionPage(queryParams?: DistributionCommissionQueryParams) {
|
||||
return request<any, PageResult<DistributionCommissionItem>>({
|
||||
url: DISTRIBUTION_COMMISSION_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getWithdrawPage(queryParams?: DistributionWithdrawQueryParams) {
|
||||
return request<any, PageResult<DistributionWithdrawItem>>({
|
||||
url: DISTRIBUTION_WITHDRAW_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getWithdrawDetail(id: string | number) {
|
||||
return request<any, DistributionWithdrawItem>({
|
||||
url: `${DISTRIBUTION_WITHDRAW_BASE_URL}/${id}`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
approveWithdraw(id: string | number, data?: DistributionWithdrawApproveForm) {
|
||||
return request({
|
||||
url: `${DISTRIBUTION_WITHDRAW_BASE_URL}/${id}/approve`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
rejectWithdraw(id: string | number, data: DistributionWithdrawRejectForm) {
|
||||
return request({
|
||||
url: `${DISTRIBUTION_WITHDRAW_BASE_URL}/${id}/reject`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
payWithdraw(id: string | number, data: DistributionWithdrawPayForm) {
|
||||
return request({
|
||||
url: `${DISTRIBUTION_WITHDRAW_BASE_URL}/${id}/pay`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default DistributionAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,106 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
/**
|
||||
* 分销配置表单/视图对象
|
||||
*/
|
||||
export interface DistributionConfigModel {
|
||||
id?: string;
|
||||
distributionEnabled?: number;
|
||||
firstLevelRate?: number;
|
||||
secondLevelRate?: number;
|
||||
withdrawThreshold?: number;
|
||||
withdrawFeeRate?: number;
|
||||
settleRule?: string;
|
||||
status?: number;
|
||||
remark?: string;
|
||||
createBy?: number;
|
||||
updateBy?: number;
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分销佣金查询参数
|
||||
*/
|
||||
export interface DistributionCommissionQueryParams extends BaseQueryParams {
|
||||
userId?: number;
|
||||
fromUserId?: number;
|
||||
orderNo?: string;
|
||||
commissionStatus?: string;
|
||||
levelNo?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分销佣金分页对象
|
||||
*/
|
||||
export interface DistributionCommissionItem {
|
||||
id?: string;
|
||||
userId?: number;
|
||||
fromUserId?: number;
|
||||
orderId?: number;
|
||||
orderNo?: string;
|
||||
levelNo?: number;
|
||||
rate?: number;
|
||||
baseAmount?: number;
|
||||
commissionAmount?: number;
|
||||
commissionStatus?: string;
|
||||
confirmTime?: string;
|
||||
settleTime?: string;
|
||||
invalidTime?: string;
|
||||
remark?: string;
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
export interface DistributionWithdrawQueryParams extends BaseQueryParams {
|
||||
keywords?: string;
|
||||
memberUserId?: number;
|
||||
status?: string;
|
||||
methodType?: string;
|
||||
submitStartDate?: string;
|
||||
submitEndDate?: string;
|
||||
payStartDate?: string;
|
||||
payEndDate?: string;
|
||||
}
|
||||
|
||||
export interface DistributionWithdrawItem {
|
||||
id?: string;
|
||||
withdrawNo?: string;
|
||||
memberUserId?: number;
|
||||
usernameSnapshot?: string;
|
||||
nicknameSnapshot?: string;
|
||||
mobileSnapshot?: string;
|
||||
withdrawMethodId?: number;
|
||||
methodType?: string;
|
||||
accountNameSnapshot?: string;
|
||||
accountNoSnapshot?: string;
|
||||
qrCodeUrlSnapshot?: string;
|
||||
amount?: number;
|
||||
paidAmount?: number;
|
||||
status?: string;
|
||||
submitRemark?: string;
|
||||
submitTime?: string;
|
||||
auditRemark?: string;
|
||||
auditBy?: number;
|
||||
auditTime?: string;
|
||||
payRemark?: string;
|
||||
payProofUrls?: string[];
|
||||
payBy?: number;
|
||||
payTime?: string;
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
export interface DistributionWithdrawApproveForm {
|
||||
auditRemark?: string;
|
||||
}
|
||||
|
||||
export interface DistributionWithdrawRejectForm {
|
||||
auditRemark: string;
|
||||
}
|
||||
|
||||
export interface DistributionWithdrawPayForm {
|
||||
paidAmount?: number;
|
||||
payRemark?: string;
|
||||
payProofUrls?: string[];
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import request from "@/utils/request";
|
||||
import type {
|
||||
DurationMultiplierForm,
|
||||
DurationMultiplierItem,
|
||||
DurationMultiplierQueryParams,
|
||||
} from "./types";
|
||||
|
||||
const DURATION_MULTIPLIER_BASE_URL = "/api/v1/proxy/duration-multipliers";
|
||||
|
||||
const DurationMultiplierAPI = {
|
||||
getPage(queryParams?: DurationMultiplierQueryParams) {
|
||||
return request<any, PageResult<DurationMultiplierItem>>({
|
||||
url: DURATION_MULTIPLIER_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getFormData(id: string) {
|
||||
return request<any, DurationMultiplierForm>({
|
||||
url: `${DURATION_MULTIPLIER_BASE_URL}/${id}/form`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
create(data: DurationMultiplierForm) {
|
||||
return request({
|
||||
url: DURATION_MULTIPLIER_BASE_URL,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
update(id: string, data: DurationMultiplierForm) {
|
||||
return request({
|
||||
url: `${DURATION_MULTIPLIER_BASE_URL}/${id}`,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
deleteById(id: string) {
|
||||
return request({
|
||||
url: `${DURATION_MULTIPLIER_BASE_URL}/${id}`,
|
||||
method: "delete",
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default DurationMultiplierAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface DurationMultiplierQueryParams extends BaseQueryParams {
|
||||
productId?: number;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
export interface DurationMultiplierForm {
|
||||
id?: string;
|
||||
productId?: number;
|
||||
durationDays?: number;
|
||||
durationUnit?: string;
|
||||
durationValue?: number;
|
||||
multiplier?: number;
|
||||
status?: number;
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
export interface DurationMultiplierItem {
|
||||
id?: string;
|
||||
productId?: number;
|
||||
durationDays?: number;
|
||||
durationUnit?: string;
|
||||
durationValue?: number;
|
||||
displayName?: string;
|
||||
multiplier?: number;
|
||||
status?: number;
|
||||
remark?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import request from "@/utils/request";
|
||||
import type {
|
||||
DynamicChannelItem,
|
||||
DynamicChannelQueryParams,
|
||||
DynamicChannelUpdateForm,
|
||||
DynamicEndpointGenerateForm,
|
||||
DynamicTrafficForm,
|
||||
DynamicTrafficResult,
|
||||
} from "./types";
|
||||
|
||||
const DYNAMIC_CHANNEL_BASE_URL = "/api/v1/proxy/dynamic-channels";
|
||||
|
||||
const DynamicChannelAPI = {
|
||||
getPage(queryParams?: DynamicChannelQueryParams) {
|
||||
return request<any, PageResult<DynamicChannelItem>>({
|
||||
url: DYNAMIC_CHANNEL_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
sync(providerId: number) {
|
||||
return request({
|
||||
url: `${DYNAMIC_CHANNEL_BASE_URL}/sync/${providerId}`,
|
||||
method: "post",
|
||||
});
|
||||
},
|
||||
|
||||
update(data: DynamicChannelUpdateForm) {
|
||||
return request({
|
||||
url: `${DYNAMIC_CHANNEL_BASE_URL}/update`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
getTraffic(data: DynamicTrafficForm) {
|
||||
return request<any, DynamicTrafficResult>({
|
||||
url: `${DYNAMIC_CHANNEL_BASE_URL}/traffic`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
generateEndpoints(data: DynamicEndpointGenerateForm) {
|
||||
return request<any, string[]>({
|
||||
url: `${DYNAMIC_CHANNEL_BASE_URL}/generate-endpoints`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default DynamicChannelAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,59 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface DynamicChannelQueryParams extends BaseQueryParams {
|
||||
userId?: number;
|
||||
channelName?: string;
|
||||
channelStatus?: string;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
export interface DynamicChannelItem {
|
||||
id?: string;
|
||||
userId?: number;
|
||||
orderId?: number;
|
||||
productId?: number;
|
||||
upstreamChannelId?: string;
|
||||
channelName?: string;
|
||||
channelPassword?: string;
|
||||
channelStatus?: string;
|
||||
flowPackageGb?: number;
|
||||
trafficLimitGb?: number;
|
||||
usedTrafficGb?: number;
|
||||
remainingTrafficGb?: number;
|
||||
expiredAt?: string;
|
||||
allowGenerateProxy?: number;
|
||||
status?: number;
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
export interface DynamicChannelUpdateForm {
|
||||
channelId?: number;
|
||||
channelName?: string;
|
||||
trafficLimitGb?: number;
|
||||
enable?: boolean;
|
||||
channelPassword?: string;
|
||||
}
|
||||
|
||||
export interface DynamicTrafficForm {
|
||||
channelId?: number;
|
||||
dateType?: number;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
}
|
||||
|
||||
export interface DynamicTrafficResult {
|
||||
channelId?: number;
|
||||
usedTrafficGb?: number;
|
||||
totalTrafficGb?: number;
|
||||
rawData?: string;
|
||||
}
|
||||
|
||||
export interface DynamicEndpointGenerateForm {
|
||||
channelId?: number;
|
||||
location?: string;
|
||||
stickySessionTime?: number;
|
||||
count?: number;
|
||||
domain?: string;
|
||||
state?: string;
|
||||
city?: string;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import request from "@/utils/request";
|
||||
import type { DynamicPlanForm, DynamicPlanItem, DynamicPlanQueryParams } from "./types";
|
||||
|
||||
const DYNAMIC_PLAN_BASE_URL = "/api/v1/proxy/dynamic-plans";
|
||||
|
||||
const DynamicPlanAPI = {
|
||||
getPage(queryParams?: DynamicPlanQueryParams) {
|
||||
return request<any, PageResult<DynamicPlanItem>>({
|
||||
url: DYNAMIC_PLAN_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getFormData(id: string) {
|
||||
return request<any, DynamicPlanForm>({
|
||||
url: `${DYNAMIC_PLAN_BASE_URL}/${id}/form`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
create(data: DynamicPlanForm) {
|
||||
return request({
|
||||
url: DYNAMIC_PLAN_BASE_URL,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
update(id: string, data: DynamicPlanForm) {
|
||||
return request({
|
||||
url: `${DYNAMIC_PLAN_BASE_URL}/${id}`,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
deleteById(id: string) {
|
||||
return request({
|
||||
url: `${DYNAMIC_PLAN_BASE_URL}/${id}`,
|
||||
method: "delete",
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default DynamicPlanAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface DynamicPlanQueryParams extends BaseQueryParams {
|
||||
productId?: number;
|
||||
planCode?: string;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
export interface DynamicPlanForm {
|
||||
id?: string;
|
||||
productId?: number;
|
||||
planCode?: string;
|
||||
flowGb?: number;
|
||||
basePrice?: number;
|
||||
allowStickySession?: number;
|
||||
allowLocationSelect?: number;
|
||||
allowCustomLimit?: number;
|
||||
status?: number;
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
export interface DynamicPlanItem {
|
||||
id?: string;
|
||||
productId?: number;
|
||||
planCode?: string;
|
||||
flowGb?: number;
|
||||
basePrice?: number;
|
||||
allowStickySession?: number;
|
||||
allowLocationSelect?: number;
|
||||
allowCustomLimit?: number;
|
||||
status?: number;
|
||||
remark?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
import request from "@/utils/request";
|
||||
import type {
|
||||
OpenApiAccountFlowItem,
|
||||
OpenApiAccountFlowQueryParams,
|
||||
OpenApiAdminAccount,
|
||||
OpenApiAdminRechargeForm,
|
||||
OpenApiApplyAuditForm,
|
||||
OpenApiApplyDetail,
|
||||
OpenApiApplyItem,
|
||||
OpenApiApplyQueryParams,
|
||||
OpenApiCallbackLogDetail,
|
||||
OpenApiCallbackLogItem,
|
||||
OpenApiCallbackLogQueryParams,
|
||||
OpenApiRechargeOrderItem,
|
||||
OpenApiRechargeOrderQueryParams,
|
||||
} from "./types";
|
||||
|
||||
const OPEN_API_APPLY_BASE_URL = "/api/v1/admin/open-api/applies";
|
||||
const OPEN_API_CALLBACK_LOG_BASE_URL = "/api/v1/admin/open-api/callback-logs";
|
||||
const OPEN_API_ACCOUNT_BASE_URL = "/api/v1/admin/open-api/accounts";
|
||||
|
||||
const OpenApiApplyAPI = {
|
||||
getPage(queryParams?: OpenApiApplyQueryParams) {
|
||||
return request<any, PageResult<OpenApiApplyItem>>({
|
||||
url: OPEN_API_APPLY_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getDetail(id: number) {
|
||||
return request<any, OpenApiApplyDetail>({
|
||||
url: `${OPEN_API_APPLY_BASE_URL}/${id}`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
audit(id: number, data: OpenApiApplyAuditForm) {
|
||||
return request({
|
||||
url: `${OPEN_API_APPLY_BASE_URL}/${id}/audit`,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
getCallbackLogPage(queryParams?: OpenApiCallbackLogQueryParams) {
|
||||
return request<any, PageResult<OpenApiCallbackLogItem>>({
|
||||
url: OPEN_API_CALLBACK_LOG_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getCallbackLogDetail(id: number) {
|
||||
return request<any, OpenApiCallbackLogDetail>({
|
||||
url: `${OPEN_API_CALLBACK_LOG_BASE_URL}/${id}`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
retryCallbackLog(id: number) {
|
||||
return request({
|
||||
url: `${OPEN_API_CALLBACK_LOG_BASE_URL}/${id}/retry`,
|
||||
method: "post",
|
||||
});
|
||||
},
|
||||
|
||||
getAccount(memberUserId: number) {
|
||||
return request<any, OpenApiAdminAccount>({
|
||||
url: `${OPEN_API_ACCOUNT_BASE_URL}/${memberUserId}`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
getFlowPage(memberUserId: number, queryParams?: OpenApiAccountFlowQueryParams) {
|
||||
return request<any, PageResult<OpenApiAccountFlowItem>>({
|
||||
url: `${OPEN_API_ACCOUNT_BASE_URL}/${memberUserId}/flows`,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getRechargePage(memberUserId: number, queryParams?: OpenApiRechargeOrderQueryParams) {
|
||||
return request<any, PageResult<OpenApiRechargeOrderItem>>({
|
||||
url: `${OPEN_API_ACCOUNT_BASE_URL}/${memberUserId}/recharges`,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
recharge(data: OpenApiAdminRechargeForm) {
|
||||
return request({
|
||||
url: `${OPEN_API_ACCOUNT_BASE_URL}/recharge`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default OpenApiApplyAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,161 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface OpenApiApplyQueryParams extends BaseQueryParams {
|
||||
keywords?: string;
|
||||
status?: number;
|
||||
memberUserId?: number;
|
||||
}
|
||||
|
||||
export interface OpenApiApplyItem {
|
||||
id?: number;
|
||||
applyNo?: string;
|
||||
memberUserId?: number;
|
||||
usernameSnapshot?: string;
|
||||
mobileSnapshot?: string;
|
||||
contactName?: string;
|
||||
contactMobile?: string;
|
||||
contactEmail?: string;
|
||||
companyName?: string;
|
||||
purpose?: string;
|
||||
status?: number;
|
||||
submitTime?: string;
|
||||
auditTime?: string;
|
||||
auditRemark?: string;
|
||||
openApiAppId?: number;
|
||||
}
|
||||
|
||||
export interface OpenApiApplyDetail {
|
||||
id?: number;
|
||||
applyNo?: string;
|
||||
memberUserId?: number;
|
||||
usernameSnapshot?: string;
|
||||
mobileSnapshot?: string;
|
||||
contactName?: string;
|
||||
contactMobile?: string;
|
||||
contactEmail?: string;
|
||||
companyName?: string;
|
||||
purpose?: string;
|
||||
scenarioDescription?: string;
|
||||
allowIpList?: string;
|
||||
status?: number;
|
||||
submitRemark?: string;
|
||||
submitTime?: string;
|
||||
auditTime?: string;
|
||||
auditBy?: number;
|
||||
auditRemark?: string;
|
||||
openApiAppId?: number;
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
export interface OpenApiApplyAuditForm {
|
||||
status?: number;
|
||||
auditRemark?: string;
|
||||
}
|
||||
|
||||
export interface OpenApiCallbackLogQueryParams extends BaseQueryParams {
|
||||
keywords?: string;
|
||||
deliveryStatus?: string;
|
||||
}
|
||||
|
||||
export interface OpenApiCallbackLogItem {
|
||||
id?: number;
|
||||
openApiAppId?: number;
|
||||
appId?: string;
|
||||
memberUserId?: number;
|
||||
orderId?: number;
|
||||
orderNo?: string;
|
||||
callbackUrl?: string;
|
||||
eventType?: string;
|
||||
responseStatus?: number;
|
||||
deliveryStatus?: string;
|
||||
errorMessage?: string;
|
||||
attemptNo?: number;
|
||||
triggerTime?: string;
|
||||
finishTime?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
export interface OpenApiCallbackLogDetail extends OpenApiCallbackLogItem {
|
||||
requestBody?: string;
|
||||
responseBody?: string;
|
||||
}
|
||||
|
||||
export interface OpenApiAdminAccount {
|
||||
memberUserId?: number;
|
||||
openApiAppId?: number;
|
||||
appId?: string;
|
||||
appName?: string;
|
||||
appStatus?: number;
|
||||
allowIpList?: string;
|
||||
callbackUrl?: string;
|
||||
lastAuthTime?: string;
|
||||
lastAuthIp?: string;
|
||||
accountId?: number;
|
||||
balance?: number;
|
||||
frozenBalance?: number;
|
||||
totalRechargeAmount?: number;
|
||||
totalConsumeAmount?: number;
|
||||
totalRefundAmount?: number;
|
||||
accountStatus?: number;
|
||||
accountCreateTime?: string;
|
||||
accountUpdateTime?: string;
|
||||
}
|
||||
|
||||
export interface OpenApiAccountFlowQueryParams extends BaseQueryParams {
|
||||
keywords?: string;
|
||||
bizType?: string;
|
||||
changeType?: string;
|
||||
}
|
||||
|
||||
export interface OpenApiAccountFlowItem {
|
||||
id?: number;
|
||||
flowNo?: string;
|
||||
openApiAppId?: number;
|
||||
memberUserId?: number;
|
||||
bizType?: string;
|
||||
changeType?: string;
|
||||
changeAmount?: number;
|
||||
beforeBalance?: number;
|
||||
afterBalance?: number;
|
||||
relatedOrderNo?: string;
|
||||
remark?: string;
|
||||
operateBy?: number;
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
export interface OpenApiRechargeOrderQueryParams extends BaseQueryParams {
|
||||
keywords?: string;
|
||||
payStatus?: string;
|
||||
paymentType?: string;
|
||||
createStartDate?: string;
|
||||
createEndDate?: string;
|
||||
}
|
||||
|
||||
export interface OpenApiRechargeOrderItem {
|
||||
id?: number;
|
||||
rechargeNo?: string;
|
||||
payOrderNo?: string;
|
||||
openApiAppId?: number;
|
||||
memberUserId?: number;
|
||||
paymentType?: string;
|
||||
payStatus?: string;
|
||||
channelOrderNo?: string;
|
||||
clientType?: string;
|
||||
returnUrl?: string;
|
||||
amount?: number;
|
||||
giftAmount?: number;
|
||||
creditedAmount?: number;
|
||||
promotionRuleSnapshot?: string;
|
||||
currency?: string;
|
||||
paidTime?: string;
|
||||
remark?: string;
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
export interface OpenApiAdminRechargeForm {
|
||||
memberUserId?: number;
|
||||
amount?: number;
|
||||
remark?: string;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import request from "@/utils/request";
|
||||
import type {
|
||||
OrderCompensationRecordItem,
|
||||
OrderCompensationRecordQueryParams,
|
||||
OrderOperateLogItem,
|
||||
WalletFlowItem,
|
||||
} from "./types";
|
||||
|
||||
const ORDER_COMPENSATION_RECORD_BASE_URL = "/api/v1/proxy/order-compensation-records";
|
||||
|
||||
const OrderCompensationRecordAPI = {
|
||||
getPage(queryParams?: OrderCompensationRecordQueryParams) {
|
||||
return request<any, PageResult<OrderCompensationRecordItem>>({
|
||||
url: ORDER_COMPENSATION_RECORD_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getOrderOperateLogs(orderNo: string) {
|
||||
return request<any, OrderOperateLogItem[]>({
|
||||
url: `${ORDER_COMPENSATION_RECORD_BASE_URL}/order-operate-logs`,
|
||||
method: "get",
|
||||
params: { orderNo },
|
||||
});
|
||||
},
|
||||
|
||||
getWalletFlows(orderNo: string) {
|
||||
return request<any, WalletFlowItem[]>({
|
||||
url: `${ORDER_COMPENSATION_RECORD_BASE_URL}/wallet-flows`,
|
||||
method: "get",
|
||||
params: { orderNo },
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default OrderCompensationRecordAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,54 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface OrderCompensationRecordQueryParams extends BaseQueryParams {
|
||||
keywords?: string;
|
||||
orderNo?: string;
|
||||
compensationType?: string;
|
||||
compensationStatus?: string;
|
||||
operatorName?: string;
|
||||
}
|
||||
|
||||
export interface OrderCompensationRecordItem {
|
||||
id?: number;
|
||||
orderId?: number;
|
||||
orderNo?: string;
|
||||
compensationType?: string;
|
||||
attemptNo?: number;
|
||||
compensationStatus?: string;
|
||||
reason?: string;
|
||||
errorMessage?: string;
|
||||
relatedFlowNo?: string;
|
||||
operatorId?: number;
|
||||
operatorName?: string;
|
||||
executeTime?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
export interface OrderOperateLogItem {
|
||||
id?: number;
|
||||
orderId?: number;
|
||||
orderNo?: string;
|
||||
operateType?: string;
|
||||
beforeStatus?: string;
|
||||
afterStatus?: string;
|
||||
content?: string;
|
||||
operatorId?: number;
|
||||
operatorName?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
export interface WalletFlowItem {
|
||||
id?: number;
|
||||
flowNo?: string;
|
||||
userId?: number;
|
||||
memberUserId?: number;
|
||||
bizType?: string;
|
||||
changeType?: string;
|
||||
changeAmount?: number;
|
||||
beforeBalance?: number;
|
||||
afterBalance?: number;
|
||||
relatedOrderNo?: string;
|
||||
remark?: string;
|
||||
operateBy?: number;
|
||||
createTime?: string;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import request from "@/utils/request";
|
||||
import type { OrderCreateForm, OrderItem, OrderPayForm, OrderQueryParams, OrderSubmitResult } from "./types";
|
||||
|
||||
const ORDER_BASE_URL = "/api/v1/proxy/orders";
|
||||
|
||||
const OrderAPI = {
|
||||
getPage(queryParams?: OrderQueryParams) {
|
||||
return request<any, PageResult<OrderItem>>({
|
||||
url: ORDER_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
create(data: OrderCreateForm) {
|
||||
return request<any, OrderSubmitResult>({
|
||||
url: ORDER_BASE_URL,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
pay(orderNo: string, data?: OrderPayForm) {
|
||||
return request<any, OrderSubmitResult>({
|
||||
url: `${ORDER_BASE_URL}/${orderNo}/pay`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
cancel(orderNo: string) {
|
||||
return request<any, OrderSubmitResult>({
|
||||
url: `${ORDER_BASE_URL}/${orderNo}/cancel`,
|
||||
method: "post",
|
||||
});
|
||||
},
|
||||
|
||||
retryCompensation(orderNo: string) {
|
||||
return request<any, OrderSubmitResult>({
|
||||
url: `${ORDER_BASE_URL}/${orderNo}/retry-compensation`,
|
||||
method: "post",
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default OrderAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,101 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface OrderQueryParams extends BaseQueryParams {
|
||||
orderNo?: string;
|
||||
userId?: number;
|
||||
memberUserId?: number;
|
||||
productType?: string;
|
||||
orderStatus?: string;
|
||||
compensationStatus?: string;
|
||||
}
|
||||
|
||||
export interface OrderItem {
|
||||
id?: number;
|
||||
orderNo?: string;
|
||||
userId?: number;
|
||||
memberUserId?: number;
|
||||
productId?: number;
|
||||
productCode?: string;
|
||||
productName?: string;
|
||||
productType?: string;
|
||||
regionId?: number;
|
||||
regionCode?: string;
|
||||
regionName?: string;
|
||||
regionNameZh?: string;
|
||||
countryCode?: string;
|
||||
countryName?: string;
|
||||
flowGb?: number;
|
||||
orderType?: string;
|
||||
orderStatus?: string;
|
||||
payStatus?: string;
|
||||
openStatus?: string;
|
||||
compensationStatus?: string;
|
||||
paymentType?: string;
|
||||
buyQuantity?: number;
|
||||
durationDays?: number;
|
||||
durationUnit?: string;
|
||||
durationValue?: number;
|
||||
durationDisplayName?: string;
|
||||
saleAmount?: number;
|
||||
paidAmount?: number;
|
||||
openSuccessAmount?: number;
|
||||
staticQuantityDiscountRate?: number;
|
||||
staticQuantityDiscountRuleDescription?: string;
|
||||
remark?: string;
|
||||
compensationReason?: string;
|
||||
compensationRetryCount?: number;
|
||||
lastCompensationTime?: string;
|
||||
payTime?: string;
|
||||
openTime?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
export interface OrderCreateForm {
|
||||
productId?: number;
|
||||
userId?: number;
|
||||
memberUserId?: number;
|
||||
quantity?: number;
|
||||
durationDays?: number;
|
||||
durationUnit?: string;
|
||||
durationValue?: number;
|
||||
regionId?: number;
|
||||
regionCode?: string;
|
||||
regionNameZh?: string;
|
||||
countryCode?: string;
|
||||
countryName?: string;
|
||||
qiyunPid?: string;
|
||||
qiyunProjectName?: string;
|
||||
qiyunAreaId?: string;
|
||||
qiyunAreaName?: string;
|
||||
qiyunNodeId?: string;
|
||||
qiyunNodeName?: string;
|
||||
dynamicPlanId?: number;
|
||||
}
|
||||
|
||||
export interface OrderSubmitResult {
|
||||
orderId?: number;
|
||||
orderNo?: string;
|
||||
payOrderNo?: string;
|
||||
orderStatus?: string;
|
||||
payStatus?: string;
|
||||
openStatus?: string;
|
||||
compensationStatus?: string;
|
||||
compensationReason?: string;
|
||||
paymentType?: string;
|
||||
paymentCompleted?: boolean;
|
||||
payAction?: string;
|
||||
payData?: string;
|
||||
payMessage?: string;
|
||||
gatewayOrderNo?: string;
|
||||
saleAmount?: number;
|
||||
durationDays?: number;
|
||||
durationUnit?: string;
|
||||
durationValue?: number;
|
||||
durationDisplayName?: string;
|
||||
}
|
||||
|
||||
export interface OrderPayForm {
|
||||
paymentType?: string;
|
||||
clientType?: string;
|
||||
returnUrl?: string;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import request from "@/utils/request";
|
||||
import type { ProxyPaymentExchangeConfig } from "./types";
|
||||
|
||||
const PROXY_PAYMENT_EXCHANGE_CONFIG_BASE_URL = "/api/v1/admin/proxy/payment-exchange-config";
|
||||
|
||||
const ProxyPaymentExchangeConfigAPI = {
|
||||
getConfig() {
|
||||
return request<any, ProxyPaymentExchangeConfig>({
|
||||
url: PROXY_PAYMENT_EXCHANGE_CONFIG_BASE_URL,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
updateConfig(data: ProxyPaymentExchangeConfig) {
|
||||
return request<any, ProxyPaymentExchangeConfig>({
|
||||
url: PROXY_PAYMENT_EXCHANGE_CONFIG_BASE_URL,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default ProxyPaymentExchangeConfigAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,16 @@
|
||||
export interface ProxyPaymentExchangeConfig {
|
||||
enabled?: boolean;
|
||||
sourceCurrency?: string;
|
||||
targetCurrency?: string;
|
||||
apiUrl?: string;
|
||||
requestMethod?: string;
|
||||
requestHeaders?: Record<string, string>;
|
||||
requestBody?: string;
|
||||
ratePath?: string;
|
||||
successPath?: string;
|
||||
successValue?: string;
|
||||
messagePath?: string;
|
||||
rateAdjustRatio?: number;
|
||||
fallbackRate?: number;
|
||||
timeoutMs?: number;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import request from "@/utils/request";
|
||||
import type { ProductForm, ProductItem, ProductQueryParams } from "./types";
|
||||
|
||||
const PRODUCT_BASE_URL = "/api/v1/proxy/products";
|
||||
|
||||
const ProductAPI = {
|
||||
getPage(queryParams?: ProductQueryParams) {
|
||||
return request<any, PageResult<ProductItem>>({
|
||||
url: PRODUCT_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getFormData(id: string) {
|
||||
return request<any, ProductForm>({
|
||||
url: `${PRODUCT_BASE_URL}/${id}/form`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
create(data: ProductForm) {
|
||||
return request({
|
||||
url: PRODUCT_BASE_URL,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
update(id: string, data: ProductForm) {
|
||||
return request({
|
||||
url: `${PRODUCT_BASE_URL}/${id}`,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
deleteById(id: string) {
|
||||
return request({
|
||||
url: `${PRODUCT_BASE_URL}/${id}`,
|
||||
method: "delete",
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default ProductAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,50 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface ProductQueryParams extends BaseQueryParams {
|
||||
keywords?: string;
|
||||
productType?: string;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
export interface ProductForm {
|
||||
id?: string;
|
||||
productCode?: string;
|
||||
productName?: string;
|
||||
productType?: string;
|
||||
upstreamProviderId?: number;
|
||||
upstreamProductCode?: string;
|
||||
proxiesType?: string;
|
||||
proxiesFormat?: string;
|
||||
purposeWeb?: string;
|
||||
upstreamParams?: string;
|
||||
upstreamCapabilities?: string;
|
||||
protocolsType?: number;
|
||||
udpStatus?: number;
|
||||
currency?: string;
|
||||
enableDistribution?: number;
|
||||
status?: number;
|
||||
sort?: number;
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
export interface ProductItem {
|
||||
id?: string;
|
||||
productCode?: string;
|
||||
productName?: string;
|
||||
productType?: string;
|
||||
upstreamProviderId?: number;
|
||||
upstreamProductCode?: string;
|
||||
proxiesType?: string;
|
||||
proxiesFormat?: string;
|
||||
purposeWeb?: string;
|
||||
upstreamParams?: string;
|
||||
upstreamCapabilities?: string;
|
||||
protocolsType?: number;
|
||||
udpStatus?: number;
|
||||
currency?: string;
|
||||
enableDistribution?: number;
|
||||
status?: number;
|
||||
sort?: number;
|
||||
remark?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import request from "@/utils/request";
|
||||
import type { ProxyWalletRechargePromotionConfig } from "./types";
|
||||
|
||||
const PROXY_WALLET_RECHARGE_PROMOTION_CONFIG_BASE_URL = "/api/v1/admin/proxy/wallet-recharge-promotion-config";
|
||||
|
||||
const ProxyWalletRechargePromotionConfigAPI = {
|
||||
getConfig() {
|
||||
return request<any, ProxyWalletRechargePromotionConfig>({
|
||||
url: PROXY_WALLET_RECHARGE_PROMOTION_CONFIG_BASE_URL,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
updateConfig(data: ProxyWalletRechargePromotionConfig) {
|
||||
return request<any, ProxyWalletRechargePromotionConfig>({
|
||||
url: PROXY_WALLET_RECHARGE_PROMOTION_CONFIG_BASE_URL,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default ProxyWalletRechargePromotionConfigAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,12 @@
|
||||
export interface ProxyWalletRechargePromotionRule {
|
||||
rechargeAmount?: number;
|
||||
giftAmount?: number;
|
||||
}
|
||||
|
||||
export interface ProxyWalletRechargePromotionConfig {
|
||||
enabled?: boolean;
|
||||
title?: string;
|
||||
minRechargeAmount?: number;
|
||||
quickAmounts?: number[];
|
||||
rules?: ProxyWalletRechargePromotionRule[];
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import request from "@/utils/request";
|
||||
import type { RegionForm, RegionItem, RegionQueryParams } from "./types";
|
||||
|
||||
const REGION_BASE_URL = "/api/v1/proxy/regions";
|
||||
|
||||
const RegionAPI = {
|
||||
getPage(queryParams?: RegionQueryParams) {
|
||||
return request<any, PageResult<RegionItem>>({
|
||||
url: REGION_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getFormData(id: string) {
|
||||
return request<any, RegionForm>({
|
||||
url: `${REGION_BASE_URL}/${id}/form`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
create(data: RegionForm) {
|
||||
return request({
|
||||
url: REGION_BASE_URL,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
update(id: string, data: RegionForm) {
|
||||
return request({
|
||||
url: `${REGION_BASE_URL}/${id}`,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
deleteById(id: string) {
|
||||
return request({
|
||||
url: `${REGION_BASE_URL}/${id}`,
|
||||
method: "delete",
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default RegionAPI;
|
||||
|
||||
export type { RegionForm, RegionItem, RegionQueryParams };
|
||||
@@ -0,0 +1,29 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface RegionQueryParams extends BaseQueryParams {
|
||||
keywords?: string;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
export interface RegionForm {
|
||||
id?: string;
|
||||
regionCode?: string;
|
||||
regionNameZh?: string;
|
||||
regionName?: string;
|
||||
iconUrl?: string;
|
||||
status?: number;
|
||||
sort?: number;
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
export interface RegionItem {
|
||||
id?: string;
|
||||
regionCode?: string;
|
||||
regionNameZh?: string;
|
||||
regionName?: string;
|
||||
iconUrl?: string;
|
||||
status?: number;
|
||||
sort?: number;
|
||||
remark?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import request from "@/utils/request";
|
||||
import type {
|
||||
StaticAssetAutoRenewForm,
|
||||
StaticAssetBatchSyncForm,
|
||||
StaticAssetChangeNodeForm,
|
||||
StaticAssetCredentialForm,
|
||||
StaticAssetItem,
|
||||
StaticAssetQueryParams,
|
||||
StaticAssetRenewForm,
|
||||
StaticAssetRenewResult,
|
||||
StaticAssetSyncForm,
|
||||
StaticAssetWhitelistItem,
|
||||
StaticAssetWhitelistForm,
|
||||
} from "./types";
|
||||
|
||||
const STATIC_ASSET_BASE_URL = "/api/v1/proxy/static-assets";
|
||||
|
||||
const StaticAssetAPI = {
|
||||
getPage(queryParams?: StaticAssetQueryParams) {
|
||||
return request<any, PageResult<StaticAssetItem>>({
|
||||
url: STATIC_ASSET_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
renew(data: StaticAssetRenewForm) {
|
||||
return request<any, StaticAssetRenewResult>({
|
||||
url: `${STATIC_ASSET_BASE_URL}/renew`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
updateCredentials(data: StaticAssetCredentialForm) {
|
||||
return request({
|
||||
url: `${STATIC_ASSET_BASE_URL}/credentials`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
changeNode(data: StaticAssetChangeNodeForm) {
|
||||
return request({
|
||||
url: `${STATIC_ASSET_BASE_URL}/change-node`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
syncFromUpstream(data: StaticAssetSyncForm) {
|
||||
return request({
|
||||
url: `${STATIC_ASSET_BASE_URL}/sync`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
batchSyncFromUpstream(data: StaticAssetBatchSyncForm) {
|
||||
return request<any, number>({
|
||||
url: `${STATIC_ASSET_BASE_URL}/batch-sync`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
updateAutoRenew(data: StaticAssetAutoRenewForm) {
|
||||
return request({
|
||||
url: `${STATIC_ASSET_BASE_URL}/auto-renew`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
addWhitelist(data: StaticAssetWhitelistForm) {
|
||||
return request({
|
||||
url: `${STATIC_ASSET_BASE_URL}/whitelists`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
getWhitelistList(assetId: number) {
|
||||
return request<any, StaticAssetWhitelistItem[]>({
|
||||
url: `${STATIC_ASSET_BASE_URL}/${assetId}/whitelists`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
deleteWhitelist(id: number) {
|
||||
return request({
|
||||
url: `${STATIC_ASSET_BASE_URL}/whitelists/${id}`,
|
||||
method: "delete",
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default StaticAssetAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,95 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface StaticAssetQueryParams extends BaseQueryParams {
|
||||
userId?: number;
|
||||
memberUserId?: number;
|
||||
orderId?: number;
|
||||
proxyAddress?: string;
|
||||
countryCode?: string;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
export interface StaticAssetItem {
|
||||
id?: string;
|
||||
userId?: number;
|
||||
userUsername?: string;
|
||||
memberUserId?: number;
|
||||
memberUsername?: string;
|
||||
orderId?: number;
|
||||
productId?: number;
|
||||
productName?: string;
|
||||
providerType?: string;
|
||||
upstreamProviderId?: number;
|
||||
upstreamProductCode?: string;
|
||||
upstreamParams?: string;
|
||||
upstreamProxyId?: string;
|
||||
proxyAddress?: string;
|
||||
port?: number;
|
||||
username?: string;
|
||||
password?: string;
|
||||
protocols?: string;
|
||||
countryCode?: string;
|
||||
countryName?: string;
|
||||
cityName?: string;
|
||||
proxyStatus?: number;
|
||||
isAutoRenew?: number;
|
||||
expiredAt?: string;
|
||||
status?: number;
|
||||
updateTime?: string;
|
||||
latestSyncFailLogId?: number;
|
||||
latestSyncFailMessage?: string;
|
||||
latestSyncFailTime?: string;
|
||||
}
|
||||
|
||||
export interface StaticAssetRenewForm {
|
||||
assetId?: number;
|
||||
durationDays?: number;
|
||||
}
|
||||
|
||||
export interface StaticAssetRenewResult {
|
||||
orderNo?: string;
|
||||
}
|
||||
|
||||
export interface StaticAssetCredentialForm {
|
||||
assetId?: number;
|
||||
username?: string;
|
||||
password?: string;
|
||||
}
|
||||
|
||||
export interface StaticAssetChangeNodeForm {
|
||||
assetId?: number;
|
||||
nodeId?: string;
|
||||
nodeValue?: string;
|
||||
}
|
||||
|
||||
export interface StaticAssetSyncForm {
|
||||
assetId?: number;
|
||||
}
|
||||
|
||||
export interface StaticAssetBatchSyncForm {
|
||||
assetIds?: number[];
|
||||
orderId?: number;
|
||||
}
|
||||
|
||||
export interface StaticAssetAutoRenewForm {
|
||||
assetId?: number;
|
||||
isAutoRenew?: number;
|
||||
}
|
||||
|
||||
export interface StaticAssetWhitelistForm {
|
||||
assetId?: number;
|
||||
address?: string;
|
||||
}
|
||||
|
||||
export interface StaticAssetWhitelistItem {
|
||||
id?: number;
|
||||
userId?: number;
|
||||
productId?: number;
|
||||
proxyType?: string;
|
||||
whitelistIp?: string;
|
||||
upstreamAddressId?: string;
|
||||
status?: number;
|
||||
remark?: string;
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import request from "@/utils/request";
|
||||
import type {
|
||||
StaticConfirmedProfitItem,
|
||||
StaticConfirmedProfitQueryParams,
|
||||
StaticConfirmedProfitReport,
|
||||
StaticConfirmedProfitSummary,
|
||||
} from "./types";
|
||||
|
||||
const STATIC_CONFIRMED_PROFIT_BASE_URL = "/api/v1/proxy/static-order-confirmed-profit";
|
||||
|
||||
const StaticConfirmedProfitAPI = {
|
||||
getPage(queryParams?: StaticConfirmedProfitQueryParams) {
|
||||
return request<any, PageResult<StaticConfirmedProfitItem>>({
|
||||
url: STATIC_CONFIRMED_PROFIT_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getSummary(queryParams?: StaticConfirmedProfitQueryParams) {
|
||||
return request<any, StaticConfirmedProfitSummary>({
|
||||
url: `${STATIC_CONFIRMED_PROFIT_BASE_URL}/summary`,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getReport(queryParams?: StaticConfirmedProfitQueryParams) {
|
||||
return request<any, StaticConfirmedProfitReport>({
|
||||
url: `${STATIC_CONFIRMED_PROFIT_BASE_URL}/report`,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default StaticConfirmedProfitAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,80 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface StaticConfirmedProfitQueryParams extends BaseQueryParams {
|
||||
dateType?: string;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
orderNo?: string;
|
||||
memberUserId?: number;
|
||||
paymentType?: string;
|
||||
orderType?: string;
|
||||
reportRangeType?: string;
|
||||
}
|
||||
|
||||
export interface StaticConfirmedProfitItem {
|
||||
orderId?: number;
|
||||
orderNo?: string;
|
||||
payOrderNo?: string;
|
||||
gatewayOrderNo?: string;
|
||||
userId?: number;
|
||||
memberUserId?: number;
|
||||
productId?: number;
|
||||
productCode?: string;
|
||||
productName?: string;
|
||||
paymentType?: string;
|
||||
orderType?: string;
|
||||
orderStatus?: string;
|
||||
openStatus?: string;
|
||||
compensationStatus?: string;
|
||||
buyQuantity?: number;
|
||||
durationDays?: number;
|
||||
durationUnit?: string;
|
||||
durationValue?: number;
|
||||
durationDisplayName?: string;
|
||||
countryCode?: string;
|
||||
countryName?: string;
|
||||
cityName?: string;
|
||||
userPaidAmount?: number;
|
||||
upstreamCostAmount?: number;
|
||||
confirmedProfitAmount?: number;
|
||||
currency?: string;
|
||||
staticQuantityDiscountRate?: number;
|
||||
staticQuantityDiscountRuleDescription?: string;
|
||||
payTime?: string;
|
||||
openTime?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
export interface StaticConfirmedProfitSummary {
|
||||
orderCount?: number;
|
||||
totalUserPaidAmount?: number;
|
||||
totalUpstreamCostAmount?: number;
|
||||
totalConfirmedProfitAmount?: number;
|
||||
avgConfirmedProfitAmount?: number;
|
||||
currency?: string;
|
||||
}
|
||||
|
||||
export interface StaticConfirmedProfitTrendItem {
|
||||
label?: string;
|
||||
userPaidAmount?: number;
|
||||
upstreamCostAmount?: number;
|
||||
confirmedProfitAmount?: number;
|
||||
}
|
||||
|
||||
export interface StaticConfirmedProfitPaymentDistributionItem {
|
||||
paymentType?: string;
|
||||
paymentTypeLabel?: string;
|
||||
orderCount?: number;
|
||||
userPaidAmount?: number;
|
||||
}
|
||||
|
||||
export interface StaticConfirmedProfitReport {
|
||||
rangeType?: string;
|
||||
dateType?: string;
|
||||
currency?: string;
|
||||
totalUserPaidAmount?: number;
|
||||
totalUpstreamCostAmount?: number;
|
||||
totalConfirmedProfitAmount?: number;
|
||||
trend?: StaticConfirmedProfitTrendItem[];
|
||||
paymentTypeDistribution?: StaticConfirmedProfitPaymentDistributionItem[];
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import request from "@/utils/request";
|
||||
import type { StaticPriceBatchForm, StaticPriceForm, StaticPriceItem, StaticPriceQueryParams } from "./types";
|
||||
|
||||
const STATIC_PRICE_BASE_URL = "/api/v1/proxy/static-region-prices";
|
||||
|
||||
const StaticPriceAPI = {
|
||||
getPage(queryParams?: StaticPriceQueryParams) {
|
||||
return request<any, PageResult<StaticPriceItem>>({
|
||||
url: STATIC_PRICE_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getFormData(id: string) {
|
||||
return request<any, StaticPriceForm>({
|
||||
url: `${STATIC_PRICE_BASE_URL}/${id}/form`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
create(data: StaticPriceForm) {
|
||||
return request({
|
||||
url: STATIC_PRICE_BASE_URL,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
createBatch(data: StaticPriceBatchForm) {
|
||||
return request({
|
||||
url: `${STATIC_PRICE_BASE_URL}/batch`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
update(id: string, data: StaticPriceForm) {
|
||||
return request({
|
||||
url: `${STATIC_PRICE_BASE_URL}/${id}`,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
deleteById(id: string) {
|
||||
return request({
|
||||
url: `${STATIC_PRICE_BASE_URL}/${id}`,
|
||||
method: "delete",
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default StaticPriceAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,90 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface StaticPriceQueryParams extends BaseQueryParams {
|
||||
productId?: number;
|
||||
priceType?: string;
|
||||
keywords?: string;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
export interface StaticPriceForm {
|
||||
id?: string;
|
||||
productId?: number;
|
||||
priceType?: string;
|
||||
qiyunProductType?: string;
|
||||
qiyunPid?: string;
|
||||
qiyunProjectName?: string;
|
||||
qiyunAreaId?: string;
|
||||
qiyunAreaName?: string;
|
||||
qiyunNodeId?: string;
|
||||
qiyunNodeName?: string;
|
||||
regionId?: number;
|
||||
regionCode?: string;
|
||||
regionName?: string;
|
||||
regionNameZh?: string;
|
||||
countryCode?: string;
|
||||
countryName?: string;
|
||||
basePrice?: number;
|
||||
currency?: string;
|
||||
status?: number;
|
||||
sort?: number;
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
export interface StaticPriceBatchItemForm {
|
||||
productId?: number;
|
||||
priceType?: string;
|
||||
qiyunProductType?: string;
|
||||
qiyunPid?: string;
|
||||
qiyunProjectName?: string;
|
||||
qiyunAreaId?: string;
|
||||
qiyunAreaName?: string;
|
||||
qiyunNodeId?: string;
|
||||
qiyunNodeName?: string;
|
||||
basePrice?: number;
|
||||
currency?: string;
|
||||
sort?: number;
|
||||
}
|
||||
|
||||
export interface StaticPriceBatchForm {
|
||||
priceType?: string;
|
||||
qiyunProductType?: string;
|
||||
qiyunPid?: string;
|
||||
qiyunProjectName?: string;
|
||||
qiyunAreaId?: string;
|
||||
qiyunAreaName?: string;
|
||||
qiyunNodeId?: string;
|
||||
qiyunNodeName?: string;
|
||||
regionId?: number;
|
||||
regionCode?: string;
|
||||
regionName?: string;
|
||||
regionNameZh?: string;
|
||||
status?: number;
|
||||
remark?: string;
|
||||
items?: StaticPriceBatchItemForm[];
|
||||
}
|
||||
|
||||
export interface StaticPriceItem {
|
||||
id?: string;
|
||||
productId?: number;
|
||||
priceType?: string;
|
||||
qiyunProductType?: string;
|
||||
qiyunPid?: string;
|
||||
qiyunProjectName?: string;
|
||||
qiyunAreaId?: string;
|
||||
qiyunAreaName?: string;
|
||||
qiyunNodeId?: string;
|
||||
qiyunNodeName?: string;
|
||||
regionId?: number;
|
||||
regionCode?: string;
|
||||
regionName?: string;
|
||||
regionNameZh?: string;
|
||||
countryCode?: string;
|
||||
countryName?: string;
|
||||
basePrice?: number;
|
||||
currency?: string;
|
||||
status?: number;
|
||||
sort?: number;
|
||||
remark?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import request from "@/utils/request";
|
||||
import type { ProxyStaticQuantityDiscountConfig } from "./types";
|
||||
|
||||
const PROXY_STATIC_QUANTITY_DISCOUNT_CONFIG_BASE_URL = "/api/v1/admin/proxy/static-quantity-discount-config";
|
||||
|
||||
const ProxyStaticQuantityDiscountConfigAPI = {
|
||||
getConfig() {
|
||||
return request<any, ProxyStaticQuantityDiscountConfig>({
|
||||
url: PROXY_STATIC_QUANTITY_DISCOUNT_CONFIG_BASE_URL,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
updateConfig(data: ProxyStaticQuantityDiscountConfig) {
|
||||
return request<any, ProxyStaticQuantityDiscountConfig>({
|
||||
url: PROXY_STATIC_QUANTITY_DISCOUNT_CONFIG_BASE_URL,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default ProxyStaticQuantityDiscountConfigAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,10 @@
|
||||
export interface ProxyStaticQuantityDiscountRule {
|
||||
minQuantity?: number;
|
||||
discountRate?: number;
|
||||
}
|
||||
|
||||
export interface ProxyStaticQuantityDiscountConfig {
|
||||
enabled?: boolean;
|
||||
title?: string;
|
||||
rules?: ProxyStaticQuantityDiscountRule[];
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import request from "@/utils/request";
|
||||
import type {
|
||||
UpstreamProviderForm,
|
||||
UpstreamProviderItem,
|
||||
UpstreamOptionItem,
|
||||
UpstreamProviderQueryParams,
|
||||
} from "./types";
|
||||
|
||||
const UPSTREAM_PROVIDER_BASE_URL = "/api/v1/proxy/upstream-providers";
|
||||
|
||||
const UpstreamProviderAPI = {
|
||||
getPage(queryParams?: UpstreamProviderQueryParams) {
|
||||
return request<any, PageResult<UpstreamProviderItem>>({
|
||||
url: UPSTREAM_PROVIDER_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getFormData(id: string) {
|
||||
return request<any, UpstreamProviderForm>({
|
||||
url: `${UPSTREAM_PROVIDER_BASE_URL}/${id}/form`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
create(data: UpstreamProviderForm) {
|
||||
return request({
|
||||
url: UPSTREAM_PROVIDER_BASE_URL,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
update(id: string, data: UpstreamProviderForm) {
|
||||
return request({
|
||||
url: `${UPSTREAM_PROVIDER_BASE_URL}/${id}`,
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
deleteById(id: string) {
|
||||
return request({
|
||||
url: `${UPSTREAM_PROVIDER_BASE_URL}/${id}`,
|
||||
method: "delete",
|
||||
});
|
||||
},
|
||||
|
||||
testConnection(id: string) {
|
||||
return request({
|
||||
url: `${UPSTREAM_PROVIDER_BASE_URL}/${id}/test-connection`,
|
||||
method: "post",
|
||||
});
|
||||
},
|
||||
|
||||
getQiYunProjects(id: number, productType: string) {
|
||||
return request<any, UpstreamOptionItem[]>({
|
||||
url: `${UPSTREAM_PROVIDER_BASE_URL}/${id}/qiyun/projects`,
|
||||
method: "get",
|
||||
params: { productType },
|
||||
});
|
||||
},
|
||||
|
||||
getQiYunAreas(id: number, productType: string, pid?: string) {
|
||||
return request<any, UpstreamOptionItem[]>({
|
||||
url: `${UPSTREAM_PROVIDER_BASE_URL}/${id}/qiyun/areas`,
|
||||
method: "get",
|
||||
params: { productType, pid },
|
||||
});
|
||||
},
|
||||
|
||||
getQiYunNodes(id: number, productType: string, pid?: string, areaId?: string) {
|
||||
return request<any, UpstreamOptionItem[]>({
|
||||
url: `${UPSTREAM_PROVIDER_BASE_URL}/${id}/qiyun/nodes`,
|
||||
method: "get",
|
||||
params: { productType, pid, areaId },
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default UpstreamProviderAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,41 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface UpstreamProviderQueryParams extends BaseQueryParams {
|
||||
keywords?: string;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
export interface UpstreamProviderForm {
|
||||
id?: string;
|
||||
providerCode?: string;
|
||||
providerName?: string;
|
||||
providerType?: string;
|
||||
baseUrl?: string;
|
||||
authUserId?: string;
|
||||
authToken?: string;
|
||||
successCodes?: string;
|
||||
httpTimeoutMs?: number;
|
||||
status?: number;
|
||||
isDefault?: number;
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
export interface UpstreamProviderItem {
|
||||
id?: string;
|
||||
providerCode?: string;
|
||||
providerName?: string;
|
||||
providerType?: string;
|
||||
baseUrl?: string;
|
||||
successCodes?: string;
|
||||
httpTimeoutMs?: number;
|
||||
status?: number;
|
||||
isDefault?: number;
|
||||
remark?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
export interface UpstreamOptionItem {
|
||||
id?: string;
|
||||
value?: string;
|
||||
extra?: Record<string, unknown>;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import request from "@/utils/request";
|
||||
import type {
|
||||
UpstreamRequestLogDetail,
|
||||
UpstreamRequestLogItem,
|
||||
UpstreamRequestLogQueryParams,
|
||||
} from "./types";
|
||||
|
||||
const UPSTREAM_REQUEST_LOG_BASE_URL = "/api/v1/proxy/upstream-request-logs";
|
||||
|
||||
const UpstreamRequestLogAPI = {
|
||||
getPage(queryParams?: UpstreamRequestLogQueryParams) {
|
||||
return request<any, PageResult<UpstreamRequestLogItem>>({
|
||||
url: UPSTREAM_REQUEST_LOG_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
getDetail(id: number) {
|
||||
return request<any, UpstreamRequestLogDetail>({
|
||||
url: `${UPSTREAM_REQUEST_LOG_BASE_URL}/${id}`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default UpstreamRequestLogAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface UpstreamRequestLogQueryParams extends BaseQueryParams {
|
||||
keywords?: string;
|
||||
providerId?: number;
|
||||
bizType?: string;
|
||||
apiName?: string;
|
||||
successFlag?: number;
|
||||
}
|
||||
|
||||
export interface UpstreamRequestLogItem {
|
||||
id?: number;
|
||||
providerId?: number;
|
||||
providerName?: string;
|
||||
bizType?: string;
|
||||
apiName?: string;
|
||||
requestUrl?: string;
|
||||
httpStatus?: number;
|
||||
bizCode?: string;
|
||||
successFlag?: number;
|
||||
durationMs?: number;
|
||||
errorMessage?: string;
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
export interface UpstreamRequestLogDetail extends UpstreamRequestLogItem {
|
||||
requestHeaders?: string;
|
||||
requestBody?: string;
|
||||
responseBody?: string;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import request from "@/utils/request";
|
||||
import type { WalletRechargeOrderItem, WalletRechargeOrderQueryParams } from "./types";
|
||||
|
||||
const WALLET_RECHARGE_ORDER_BASE_URL = "/api/v1/proxy/wallet-recharge-orders";
|
||||
|
||||
const WalletRechargeOrderAPI = {
|
||||
getPage(queryParams?: WalletRechargeOrderQueryParams) {
|
||||
return request<any, PageResult<WalletRechargeOrderItem>>({
|
||||
url: WALLET_RECHARGE_ORDER_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default WalletRechargeOrderAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface WalletRechargeOrderQueryParams extends BaseQueryParams {
|
||||
keywords?: string;
|
||||
memberUserId?: number;
|
||||
payStatus?: string;
|
||||
paymentType?: string;
|
||||
createStartDate?: string;
|
||||
createEndDate?: string;
|
||||
}
|
||||
|
||||
export interface WalletRechargeOrderItem {
|
||||
id?: number;
|
||||
rechargeNo?: string;
|
||||
payOrderNo?: string;
|
||||
memberUserId?: number;
|
||||
paymentType?: string;
|
||||
payStatus?: string;
|
||||
channelOrderNo?: string;
|
||||
clientType?: string;
|
||||
returnUrl?: string;
|
||||
amount?: number;
|
||||
currency?: string;
|
||||
paidTime?: string;
|
||||
remark?: string;
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import request from "@/utils/request";
|
||||
import type { WalletAccountItem, WalletAccountQueryParams, WalletRechargeForm } from "./types";
|
||||
|
||||
const WALLET_ACCOUNT_BASE_URL = "/api/v1/proxy/wallet-accounts";
|
||||
|
||||
const WalletAPI = {
|
||||
getPage(queryParams?: WalletAccountQueryParams) {
|
||||
return request<any, PageResult<WalletAccountItem>>({
|
||||
url: WALLET_ACCOUNT_BASE_URL,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
recharge(data: WalletRechargeForm) {
|
||||
return request({
|
||||
url: `${WALLET_ACCOUNT_BASE_URL}/recharge`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default WalletAPI;
|
||||
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
export interface WalletAccountQueryParams extends BaseQueryParams {
|
||||
userId?: number;
|
||||
memberUserId?: number;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
export interface WalletAccountItem {
|
||||
id?: string;
|
||||
userId?: number;
|
||||
memberUserId?: number;
|
||||
balance?: number;
|
||||
frozenBalance?: number;
|
||||
totalRechargeAmount?: number;
|
||||
totalConsumeAmount?: number;
|
||||
totalRefundAmount?: number;
|
||||
status?: number;
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
export interface WalletRechargeForm {
|
||||
userId?: number;
|
||||
memberUserId?: number;
|
||||
amount?: number;
|
||||
remark?: string;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import request from "@/utils/request";
|
||||
import type { ConfigQueryParams, ConfigForm, ConfigItem } from "./types";
|
||||
|
||||
const CONFIG_BASE_URL = "/api/v1/configs";
|
||||
|
||||
const ConfigAPI = {
|
||||
/** 获取配置分页数据 */
|
||||
getPage(queryParams?: ConfigQueryParams) {
|
||||
return request<any, PageResult<ConfigItem>>({
|
||||
url: `${CONFIG_BASE_URL}`,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
/** 获取配置表单数据 */
|
||||
getFormData(id: string) {
|
||||
return request<any, ConfigForm>({
|
||||
url: `${CONFIG_BASE_URL}/${id}/form`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
/** 新增配置 */
|
||||
create(data: ConfigForm) {
|
||||
return request({ url: `${CONFIG_BASE_URL}`, method: "post", data });
|
||||
},
|
||||
/** 修改配置 */
|
||||
update(id: string, data: ConfigForm) {
|
||||
return request({ url: `${CONFIG_BASE_URL}/${id}`, method: "put", data });
|
||||
},
|
||||
/** 删除配置 */
|
||||
deleteById(id: string) {
|
||||
return request({ url: `${CONFIG_BASE_URL}/${id}`, method: "delete" });
|
||||
},
|
||||
/** 刷新配置缓存 */
|
||||
refreshCache() {
|
||||
return request({ url: `${CONFIG_BASE_URL}/refresh`, method: "PUT" });
|
||||
},
|
||||
};
|
||||
|
||||
export default ConfigAPI;
|
||||
|
||||
// 重导出类型
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Config 配置类型定义
|
||||
*/
|
||||
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
/** 配置分页查询参数 */
|
||||
export interface ConfigQueryParams extends BaseQueryParams {
|
||||
/** 搜索关键字 */
|
||||
keywords?: string;
|
||||
}
|
||||
|
||||
/** 配置表单对象 */
|
||||
export interface ConfigForm {
|
||||
/** 配置ID */
|
||||
id?: string;
|
||||
/** 配置名称 */
|
||||
configName?: string;
|
||||
/** 配置键 */
|
||||
configKey?: string;
|
||||
/** 配置值 */
|
||||
configValue?: string;
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
/** 配置分页对象 */
|
||||
export interface ConfigItem {
|
||||
/** 配置ID */
|
||||
id?: string;
|
||||
/** 配置名称 */
|
||||
configName?: string;
|
||||
/** 配置键 */
|
||||
configKey?: string;
|
||||
/** 配置值 */
|
||||
configValue?: string;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import request from "@/utils/request";
|
||||
import type { DeptQueryParams, DeptItem, DeptForm } from "./types";
|
||||
import type { OptionItem } from "@/api/common";
|
||||
|
||||
const DEPT_BASE_URL = "/api/v1/depts";
|
||||
|
||||
const DeptAPI = {
|
||||
/** 获取部门树形列表 */
|
||||
getList(queryParams?: DeptQueryParams) {
|
||||
return request<any, DeptItem[]>({
|
||||
url: `${DEPT_BASE_URL}`,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
/** 获取部门下拉数据源 */
|
||||
getOptions() {
|
||||
return request<any, OptionItem[]>({ url: `${DEPT_BASE_URL}/options`, method: "get" });
|
||||
},
|
||||
/** 获取部门表单数据 */
|
||||
getFormData(id: string) {
|
||||
return request<any, DeptForm>({ url: `${DEPT_BASE_URL}/${id}/form`, method: "get" });
|
||||
},
|
||||
/** 新增部门 */
|
||||
create(data: DeptForm) {
|
||||
return request({ url: `${DEPT_BASE_URL}`, method: "post", data });
|
||||
},
|
||||
/** 修改部门 */
|
||||
update(id: string, data: DeptForm) {
|
||||
return request({ url: `${DEPT_BASE_URL}/${id}`, method: "put", data });
|
||||
},
|
||||
/** 批量删除部门,多个以英文逗号(,)分割 */
|
||||
deleteByIds(ids: string) {
|
||||
return request({ url: `${DEPT_BASE_URL}/${ids}`, method: "delete" });
|
||||
},
|
||||
};
|
||||
|
||||
export default DeptAPI;
|
||||
|
||||
// 重导出类型
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Dept 部门类型定义
|
||||
*/
|
||||
|
||||
/** 部门查询参数 */
|
||||
export interface DeptQueryParams {
|
||||
/** 搜索关键字 */
|
||||
keywords?: string;
|
||||
/** 状态 */
|
||||
status?: number;
|
||||
}
|
||||
|
||||
/** 部门视图对象 */
|
||||
export interface DeptItem {
|
||||
/** 子部门 */
|
||||
children?: DeptItem[];
|
||||
/** 创建时间 */
|
||||
createTime?: Date;
|
||||
/** 部门ID */
|
||||
id?: string;
|
||||
/** 部门名称 */
|
||||
name?: string;
|
||||
/** 父部门ID */
|
||||
parentId?: string;
|
||||
/** 排序 */
|
||||
sort?: number;
|
||||
/** 状态(1:启用;0:禁用) */
|
||||
status?: number;
|
||||
/** 父节点ID路径 */
|
||||
treePath?: string;
|
||||
/** 修改时间 */
|
||||
updateTime?: Date;
|
||||
}
|
||||
|
||||
/** 部门表单对象 */
|
||||
export interface DeptForm {
|
||||
/** 部门ID */
|
||||
id?: string;
|
||||
/** 部门名称 */
|
||||
name?: string;
|
||||
/** 部门编号 */
|
||||
code?: string;
|
||||
/** 父部门ID */
|
||||
parentId?: string;
|
||||
/** 排序 */
|
||||
sort?: number;
|
||||
/** 状态(1:启用;0:禁用) */
|
||||
status?: number;
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
import request from "@/utils/request";
|
||||
import type {
|
||||
DictTypeQueryParams,
|
||||
DictTypeItem,
|
||||
DictTypeForm,
|
||||
DictItemQueryParams,
|
||||
DictItem,
|
||||
DictItemForm,
|
||||
DictItemOption,
|
||||
} from "./types";
|
||||
import type { OptionItem } from "@/api/common";
|
||||
|
||||
const DICT_BASE_URL = "/api/v1/dicts";
|
||||
|
||||
type DictTagTypeCode = "N" | "P" | "S" | "W" | "I" | "D";
|
||||
|
||||
const decodeDictTagType = (code?: unknown): DictItemForm["tagType"] => {
|
||||
const val = String(code ?? "")
|
||||
.trim()
|
||||
.toUpperCase();
|
||||
switch (val as DictTagTypeCode) {
|
||||
case "P":
|
||||
return "primary";
|
||||
case "S":
|
||||
return "success";
|
||||
case "W":
|
||||
return "warning";
|
||||
case "I":
|
||||
return "info";
|
||||
case "D":
|
||||
return "danger";
|
||||
case "N":
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
const encodeDictTagType = (tagType?: unknown): DictTagTypeCode => {
|
||||
const val = String(tagType ?? "")
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
switch (val) {
|
||||
case "primary":
|
||||
return "P";
|
||||
case "success":
|
||||
return "S";
|
||||
case "warning":
|
||||
return "W";
|
||||
case "info":
|
||||
return "I";
|
||||
case "danger":
|
||||
case "error":
|
||||
return "D";
|
||||
case "default":
|
||||
case "":
|
||||
default:
|
||||
return "N";
|
||||
}
|
||||
};
|
||||
|
||||
const DictAPI = {
|
||||
/** 字典分页列表 */
|
||||
getPage(queryParams: DictTypeQueryParams) {
|
||||
return request<any, PageResult<DictTypeItem>>({
|
||||
url: `${DICT_BASE_URL}`,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
});
|
||||
},
|
||||
/** 字典列表 */
|
||||
getList() {
|
||||
return request<any, OptionItem[]>({ url: `${DICT_BASE_URL}/options`, method: "get" });
|
||||
},
|
||||
/** 字典表单数据 */
|
||||
getFormData(id: string) {
|
||||
return request<any, DictTypeForm>({ url: `${DICT_BASE_URL}/${id}/form`, method: "get" });
|
||||
},
|
||||
/** 新增字典 */
|
||||
create(data: DictTypeForm) {
|
||||
return request({ url: `${DICT_BASE_URL}`, method: "post", data });
|
||||
},
|
||||
/** 修改字典 */
|
||||
update(id: string, data: DictTypeForm) {
|
||||
return request({ url: `${DICT_BASE_URL}/${id}`, method: "put", data });
|
||||
},
|
||||
/** 删除字典 */
|
||||
deleteByIds(ids: string) {
|
||||
return request({ url: `${DICT_BASE_URL}/${ids}`, method: "delete" });
|
||||
},
|
||||
|
||||
/** 获取字典项分页列表 */
|
||||
getDictItemPage(dictCode: string, queryParams: DictItemQueryParams) {
|
||||
return request<any, PageResult<DictItem>>({
|
||||
url: `${DICT_BASE_URL}/${dictCode}/items`,
|
||||
method: "get",
|
||||
params: queryParams,
|
||||
}).then((data) => ({
|
||||
...data,
|
||||
list: (data.list ?? []).map((item: DictItem & { tagType?: string }) => ({
|
||||
...item,
|
||||
tagType: decodeDictTagType(item.tagType),
|
||||
})),
|
||||
}));
|
||||
},
|
||||
/** 获取字典项列表 */
|
||||
getDictItems(dictCode: string) {
|
||||
return request<any, DictItemOption[]>({
|
||||
url: `${DICT_BASE_URL}/${dictCode}/items/options`,
|
||||
method: "get",
|
||||
}).then((items) =>
|
||||
(items ?? []).map((item) => ({
|
||||
...item,
|
||||
tagType: decodeDictTagType((item as any).tagType),
|
||||
}))
|
||||
);
|
||||
},
|
||||
/** 新增字典项 */
|
||||
createDictItem(dictCode: string, data: DictItemForm) {
|
||||
return request({
|
||||
url: `${DICT_BASE_URL}/${dictCode}/items`,
|
||||
method: "post",
|
||||
data: {
|
||||
...data,
|
||||
tagType: encodeDictTagType((data as any).tagType),
|
||||
},
|
||||
});
|
||||
},
|
||||
/** 获取字典项表单数据 */
|
||||
getDictItemFormData(dictCode: string, id: string) {
|
||||
return request<any, DictItemForm>({
|
||||
url: `${DICT_BASE_URL}/${dictCode}/items/${id}/form`,
|
||||
method: "get",
|
||||
}).then((form) => ({
|
||||
...form,
|
||||
tagType: decodeDictTagType((form as any).tagType),
|
||||
}));
|
||||
},
|
||||
/** 修改字典项 */
|
||||
updateDictItem(dictCode: string, id: string, data: DictItemForm) {
|
||||
return request({
|
||||
url: `${DICT_BASE_URL}/${dictCode}/items/${id}`,
|
||||
method: "put",
|
||||
data: {
|
||||
...data,
|
||||
tagType: encodeDictTagType((data as any).tagType),
|
||||
},
|
||||
});
|
||||
},
|
||||
/** 删除字典项 */
|
||||
deleteDictItems(dictCode: string, ids: string) {
|
||||
return request({ url: `${DICT_BASE_URL}/${dictCode}/items/${ids}`, method: "delete" });
|
||||
},
|
||||
};
|
||||
|
||||
export default DictAPI;
|
||||
|
||||
// 重导出类型
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Dict 字典类型定义
|
||||
*/
|
||||
|
||||
import type { BaseQueryParams } from "@/api/common";
|
||||
|
||||
/** 字典分页查询参数 */
|
||||
|
||||
export interface DictTypeQueryParams extends BaseQueryParams {
|
||||
/** 搜索关键字 */
|
||||
keywords?: string;
|
||||
/** 状态(1:启用;0:禁用) */
|
||||
status?: number;
|
||||
}
|
||||
|
||||
/** 字典分页对象 */
|
||||
export interface DictTypeItem {
|
||||
/** 字典ID */
|
||||
id: string;
|
||||
/** 字典名称 */
|
||||
name: string;
|
||||
/** 字典编码 */
|
||||
dictCode: string;
|
||||
/** 状态(1:启用;0:禁用) */
|
||||
status: number;
|
||||
}
|
||||
|
||||
/** 字典表单对象 */
|
||||
export interface DictTypeForm {
|
||||
/** 字典ID */
|
||||
id?: string;
|
||||
/** 字典名称 */
|
||||
name?: string;
|
||||
/** 字典编码 */
|
||||
dictCode?: string;
|
||||
/** 状态(1:启用;0:禁用) */
|
||||
status?: number;
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
/** 字典项分页查询参数 */
|
||||
export interface DictItemQueryParams extends BaseQueryParams {
|
||||
/** 搜索关键字 */
|
||||
keywords?: string;
|
||||
/** 字典编码 */
|
||||
dictCode?: string;
|
||||
}
|
||||
|
||||
/** 字典项分页对象 */
|
||||
export interface DictItem {
|
||||
/** 字典项ID */
|
||||
id: string;
|
||||
/** 字典编码 */
|
||||
dictCode: string;
|
||||
/** 字典项标签 */
|
||||
label: string;
|
||||
/** 字典项值 */
|
||||
value: string;
|
||||
/** 状态(1:启用;0:禁用) */
|
||||
status: number;
|
||||
/** 排序 */
|
||||
sort?: number;
|
||||
}
|
||||
|
||||
/** 字典项表单对象 */
|
||||
export interface DictItemForm {
|
||||
/** 字典项ID */
|
||||
id?: string;
|
||||
/** 字典编码 */
|
||||
dictCode?: string;
|
||||
/** 字典项标签 */
|
||||
label?: string;
|
||||
/** 字典项值 */
|
||||
value?: string;
|
||||
/** 状态(1:启用;0:禁用) */
|
||||
status?: number;
|
||||
/** 排序 */
|
||||
sort?: number;
|
||||
/** 标签类型 */
|
||||
tagType?: "success" | "warning" | "info" | "primary" | "danger" | "";
|
||||
}
|
||||
|
||||
/** 字典项选项 */
|
||||
export interface DictItemOption {
|
||||
/** 字典项值 */
|
||||
value: number | string;
|
||||
/** 字典项标签 */
|
||||
label: string;
|
||||
/** 标签类型 */
|
||||
tagType?: "success" | "warning" | "info" | "primary" | "danger" | "";
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user