mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-20 20:39:55 +00:00
feat: 更新前端和后端配置及依赖项
refactor: 重构代码结构和优化配置 docs: 更新文档和注释内容 build: 更新构建配置和依赖项 ci: 更新CI配置和工作流 chore: 更新杂项配置和脚本 fix: 修复已知问题和错误 style: 优化代码格式和样式 perf: 优化性能和提升执行效率 test: 更新测试用例和配置
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
extends: ['@commitlint/config-conventional'],
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
# 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 # 缩进大小
|
||||
end_of_line = lf # 控制换行类型(lf | cr | crlf)
|
||||
trim_trailing_whitespace = true # 去除行首的任意空白字符
|
||||
insert_final_newline = true # 始终在文件末尾插入一个新行
|
||||
|
||||
# 表示仅 md 文件适用以下规则
|
||||
[*.md]
|
||||
[*.md] # 表示仅 md 文件适用以下规则
|
||||
max_line_length = off # 关闭最大行长度限制
|
||||
trim_trailing_whitespace = false # 关闭末尾空格修剪
|
||||
|
||||
+8
-1
@@ -1 +1,8 @@
|
||||
shamefully-hoist=true
|
||||
# registry = https://registry.npmjs.org
|
||||
registry = https://registry.npmmirror.com
|
||||
|
||||
strict-peer-dependencies=false
|
||||
auto-install-peers=true
|
||||
shamefully-hoist=true
|
||||
ignore-workspace-root-check=true
|
||||
install-workspace-root=true
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
uni-mini-router是一个轻量级的路由管理库,专为uni-app设计,解决了uni-app原生路由系统中没有路由拦截等关键功能的问题。它提供了类似Vue Router的API体验,使得在uni-app项目中实现更加灵活和强大的路由管理成为可能。
|
||||
|
||||
### 主要特点:
|
||||
### 主要特点
|
||||
|
||||
1. **Vue Router风格API**:提供与Vue Router相似的API,降低学习成本
|
||||
2. **路由拦截功能**:支持全局导航守卫,可以在路由跳转前后执行逻辑
|
||||
@@ -38,7 +38,7 @@ function generateRoutes() {
|
||||
const newPath = `/${page.path}`
|
||||
return { ...page, path: newPath }
|
||||
})
|
||||
|
||||
|
||||
// 处理分包路由
|
||||
if (subPackages && subPackages.length > 0) {
|
||||
subPackages.forEach((subPackage) => {
|
||||
@@ -49,7 +49,7 @@ function generateRoutes() {
|
||||
routes.push(...subRoutes)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
return routes
|
||||
}
|
||||
|
||||
@@ -71,10 +71,10 @@ import router from './router'
|
||||
|
||||
export function createApp() {
|
||||
const app = createSSRApp(App)
|
||||
|
||||
|
||||
// 使用路由
|
||||
app.use(router)
|
||||
|
||||
|
||||
return {
|
||||
app
|
||||
}
|
||||
@@ -93,7 +93,7 @@ export default defineConfig({
|
||||
plugins: [
|
||||
AutoImport({
|
||||
imports: [
|
||||
'vue',
|
||||
'vue',
|
||||
{
|
||||
from: 'uni-mini-router',
|
||||
imports: ['createRouter', 'useRouter', 'useRoute']
|
||||
@@ -124,15 +124,15 @@ router.push({ path: '/pages/index/index' })
|
||||
router.push({ name: 'index' })
|
||||
|
||||
// 携带参数
|
||||
router.push({
|
||||
path: '/pages/detail/index',
|
||||
query: { id: 10 }
|
||||
router.push({
|
||||
path: '/pages/detail/index',
|
||||
query: { id: 10 }
|
||||
})
|
||||
|
||||
// 通过名称 + 参数
|
||||
router.push({
|
||||
name: 'detail',
|
||||
params: { id: 10 }
|
||||
router.push({
|
||||
name: 'detail',
|
||||
params: { id: 10 }
|
||||
})
|
||||
|
||||
// Tab页面导航
|
||||
@@ -195,12 +195,12 @@ uni-mini-router提供了全局导航守卫功能,可以在路由跳转前后
|
||||
// src/router/index.ts
|
||||
router.beforeEach((to, from, next) => {
|
||||
console.log('路由跳转:', from.path, '->', to.path)
|
||||
|
||||
|
||||
// 检查是否需要登录
|
||||
if (to.meta && to.meta.requireAuth) {
|
||||
// 检查登录状态
|
||||
const isLoggedIn = uni.getStorageSync('token')
|
||||
|
||||
|
||||
if (!isLoggedIn) {
|
||||
// 未登录,跳转到登录页
|
||||
uni.showToast({ title: '请先登录', icon: 'none' })
|
||||
@@ -208,7 +208,7 @@ router.beforeEach((to, from, next) => {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 继续导航
|
||||
next()
|
||||
})
|
||||
@@ -220,7 +220,7 @@ router.beforeEach((to, from, next) => {
|
||||
// src/router/index.ts
|
||||
router.afterEach((to, from) => {
|
||||
console.log('路由跳转完成:', to.path)
|
||||
|
||||
|
||||
// 可以在这里做一些统计或记录
|
||||
})
|
||||
```
|
||||
@@ -266,7 +266,7 @@ router.beforeEach((to, from, next) => {
|
||||
// 检查页面是否需要登录
|
||||
if (to.meta && to.meta.requireAuth) {
|
||||
const token = uni.getStorageSync('token')
|
||||
|
||||
|
||||
if (!token) {
|
||||
// 显示登录提示
|
||||
uni.showModal({
|
||||
@@ -288,7 +288,7 @@ router.beforeEach((to, from, next) => {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 继续导航
|
||||
next()
|
||||
})
|
||||
@@ -308,11 +308,11 @@ function handleLogin() {
|
||||
setTimeout(() => {
|
||||
// 登录成功,存储token
|
||||
uni.setStorageSync('token', 'user_token_example')
|
||||
|
||||
|
||||
// 获取之前要去的页面
|
||||
const redirect = uni.getStorageSync('redirect') || '/pages/index/index'
|
||||
uni.removeStorageSync('redirect')
|
||||
|
||||
|
||||
// 跳转回原来的页面
|
||||
router.replaceAll(redirect)
|
||||
}, 1000)
|
||||
@@ -421,6 +421,7 @@ uni-mini-router为uni-app提供了Vue Router风格的路由解决方案,特别
|
||||
使用uni-mini-router可以让你的uni-app项目路由管理更加规范化和工程化,提升开发效率和代码质量。
|
||||
|
||||
参考资料:
|
||||
|
||||
- [uni-mini-router GitHub仓库](https://github.com/Moonofweisheng/uni-mini-router)
|
||||
- [uni-mini-router官方文档](https://moonofweisheng.github.io/uni-mini-router/)
|
||||
- [uni-app官方路由文档](https://uniapp.dcloud.net.cn/tutorial/page.html)
|
||||
- [uni-app官方路由文档](https://uniapp.dcloud.net.cn/tutorial/page.html)
|
||||
|
||||
@@ -22,13 +22,17 @@ export default [
|
||||
ignores: [
|
||||
"node_modules/**",
|
||||
"dist/**",
|
||||
"auto-imports.d.ts",
|
||||
"unpackage/**",
|
||||
"public/**",
|
||||
"static/**",
|
||||
"**/u-charts/**",
|
||||
"**/qiun-**/**",
|
||||
"**/auto-imports.d.ts",
|
||||
// unplugin-auto-import 生成的类型文件,每次提交都改变,所以加入这里吧,与 .gitignore 配合使用
|
||||
"src/types/auto-imports.d.ts",
|
||||
// vite-plugin-uni-pages 生成的类型文件,每次切换分支都一堆不同的,所以直接 .gitignore
|
||||
"uni-pages.d.ts",
|
||||
],
|
||||
},
|
||||
// 检查文件的配置
|
||||
|
||||
+3
-2
@@ -1,7 +1,8 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<html build-time="%BUILD_TIME%">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="shortcut icon" href="/favicon.png" type="image/x-icon" />
|
||||
<script>
|
||||
var coverSupport =
|
||||
"CSS" in window &&
|
||||
@@ -13,7 +14,7 @@
|
||||
'" />'
|
||||
);
|
||||
</script>
|
||||
<title></title>
|
||||
<title>FastApp</title>
|
||||
<!--preload-links-->
|
||||
<!--app-context-->
|
||||
</head>
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
// manifest.config.ts
|
||||
import { defineManifestConfig } from '@uni-helper/vite-plugin-uni-manifest'
|
||||
import { loadEnv } from 'vite'
|
||||
|
||||
// 手动解析命令行参数获取 mode
|
||||
function getMode() {
|
||||
const args = process.argv.slice(2)
|
||||
const modeFlagIndex = args.findIndex(arg => arg === '--mode')
|
||||
return modeFlagIndex !== -1 ? args[modeFlagIndex + 1] : args[0] === 'build' ? 'production' : 'development' // 默认 development
|
||||
}
|
||||
// 获取环境变量的范例
|
||||
const env = loadEnv(getMode(), path.resolve(process.cwd(), 'env'))
|
||||
const {
|
||||
VITE_APP_TITLE,
|
||||
VITE_UNI_APPID,
|
||||
VITE_WX_APPID,
|
||||
VITE_APP_PUBLIC_BASE,
|
||||
VITE_FALLBACK_LOCALE,
|
||||
} = env
|
||||
|
||||
export default defineManifestConfig({
|
||||
'name': VITE_APP_TITLE,
|
||||
'appid': VITE_UNI_APPID,
|
||||
'description': '',
|
||||
'versionName': '1.0.0',
|
||||
'versionCode': '100',
|
||||
'transformPx': false,
|
||||
'locale': VITE_FALLBACK_LOCALE, // 'zh-Hans'
|
||||
'h5': {
|
||||
router: {
|
||||
// base: VITE_APP_PUBLIC_BASE,
|
||||
},
|
||||
},
|
||||
/* 5+App特有相关 */
|
||||
'app-plus': {
|
||||
usingComponents: true,
|
||||
nvueStyleCompiler: 'uni-app',
|
||||
compilerVersion: 3,
|
||||
compatible: {
|
||||
ignoreVersion: true,
|
||||
},
|
||||
splashscreen: {
|
||||
alwaysShowBeforeRender: true,
|
||||
waiting: true,
|
||||
autoclose: true,
|
||||
delay: 0,
|
||||
},
|
||||
/* 模块配置 */
|
||||
modules: {},
|
||||
/* 应用发布信息 */
|
||||
distribute: {
|
||||
/* android打包配置 */
|
||||
android: {
|
||||
minSdkVersion: 30,
|
||||
targetSdkVersion: 30,
|
||||
abiFilters: ['armeabi-v7a', 'arm64-v8a'],
|
||||
permissions: [
|
||||
'<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>',
|
||||
'<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>',
|
||||
'<uses-permission android:name="android.permission.VIBRATE"/>',
|
||||
'<uses-permission android:name="android.permission.READ_LOGS"/>',
|
||||
'<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>',
|
||||
'<uses-feature android:name="android.hardware.camera.autofocus"/>',
|
||||
'<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>',
|
||||
'<uses-permission android:name="android.permission.CAMERA"/>',
|
||||
'<uses-permission android:name="android.permission.GET_ACCOUNTS"/>',
|
||||
'<uses-permission android:name="android.permission.READ_PHONE_STATE"/>',
|
||||
'<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>',
|
||||
'<uses-permission android:name="android.permission.WAKE_LOCK"/>',
|
||||
'<uses-permission android:name="android.permission.FLASHLIGHT"/>',
|
||||
'<uses-feature android:name="android.hardware.camera"/>',
|
||||
'<uses-permission android:name="android.permission.WRITE_SETTINGS"/>',
|
||||
],
|
||||
},
|
||||
/* ios打包配置 */
|
||||
ios: {},
|
||||
/* SDK配置 */
|
||||
sdkConfigs: {},
|
||||
/* 图标配置 */
|
||||
icons: {
|
||||
android: {
|
||||
hdpi: 'static/app/icons/72x72.png',
|
||||
xhdpi: 'static/app/icons/96x96.png',
|
||||
xxhdpi: 'static/app/icons/144x144.png',
|
||||
xxxhdpi: 'static/app/icons/192x192.png',
|
||||
},
|
||||
ios: {
|
||||
appstore: 'static/app/icons/1024x1024.png',
|
||||
ipad: {
|
||||
'app': 'static/app/icons/76x76.png',
|
||||
'app@2x': 'static/app/icons/152x152.png',
|
||||
'notification': 'static/app/icons/20x20.png',
|
||||
'notification@2x': 'static/app/icons/40x40.png',
|
||||
'proapp@2x': 'static/app/icons/167x167.png',
|
||||
'settings': 'static/app/icons/29x29.png',
|
||||
'settings@2x': 'static/app/icons/58x58.png',
|
||||
'spotlight': 'static/app/icons/40x40.png',
|
||||
'spotlight@2x': 'static/app/icons/80x80.png',
|
||||
},
|
||||
iphone: {
|
||||
'app@2x': 'static/app/icons/120x120.png',
|
||||
'app@3x': 'static/app/icons/180x180.png',
|
||||
'notification@2x': 'static/app/icons/40x40.png',
|
||||
'notification@3x': 'static/app/icons/60x60.png',
|
||||
'settings@2x': 'static/app/icons/58x58.png',
|
||||
'settings@3x': 'static/app/icons/87x87.png',
|
||||
'spotlight@2x': 'static/app/icons/80x80.png',
|
||||
'spotlight@3x': 'static/app/icons/120x120.png',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
'quickapp': {},
|
||||
/* 小程序特有相关 */
|
||||
'mp-weixin': {
|
||||
appid: VITE_WX_APPID,
|
||||
setting: {
|
||||
urlCheck: false,
|
||||
// 是否启用 ES6 转 ES5
|
||||
es6: true,
|
||||
minified: true,
|
||||
},
|
||||
optimization: {
|
||||
subPackages: true,
|
||||
},
|
||||
// styleIsolation: 'shared',
|
||||
usingComponents: true,
|
||||
// __usePrivacyCheck__: true,
|
||||
},
|
||||
'mp-alipay': {
|
||||
usingComponents: true,
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
'mp-baidu': {
|
||||
usingComponents: true,
|
||||
},
|
||||
'mp-toutiao': {
|
||||
usingComponents: true,
|
||||
},
|
||||
'uniStatistics': {
|
||||
enable: false,
|
||||
},
|
||||
'vueVersion': '3',
|
||||
})
|
||||
+61
-22
@@ -1,14 +1,42 @@
|
||||
{
|
||||
"name": "fastapp",
|
||||
"type": "module",
|
||||
"version": "2.0.0",
|
||||
"unibest-version": "3.8.0",
|
||||
"packageManager": "pnpm@10.10.0",
|
||||
"description": "unibest - 最好的 uniapp 开发模板",
|
||||
"generate-time": "用户创建项目时生成",
|
||||
"author": {
|
||||
"name": "1014TaoTao",
|
||||
"zhName": "1014TaoTao",
|
||||
"email": "948080782@qq.com",
|
||||
"github": "https://github.com/1014TaoTao/fastapi_vue3_admin",
|
||||
"gitee": "https://gitee.com/tao__tao/fastapi_vue3_admin"
|
||||
},
|
||||
"license": "MIT",
|
||||
"homepage": "https://unibest.tech",
|
||||
"repository": "https://github.com/1014TaoTao/fastapi_vue3_admin",
|
||||
"bugs": {
|
||||
"url": "https://github.com/1014TaoTao/fastapi_vue3_admin/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18",
|
||||
"pnpm": ">=7.30"
|
||||
},
|
||||
"scripts": {
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"uvm": "npx @dcloudio/uvm@latest",
|
||||
"uvm-rm": "node ./scripts/postupgrade.js",
|
||||
"postuvm": "echo upgrade uni-app success!",
|
||||
"dev:app": "uni -p app",
|
||||
"dev:app-android": "uni -p app-android",
|
||||
"dev:app-ios": "uni -p app-ios",
|
||||
"dev:app-harmony": "uni -p app-harmony",
|
||||
"dev:custom": "uni -p",
|
||||
"dev": "uni",
|
||||
"dev:h5": "uni",
|
||||
"dev:h5:ssr": "uni --ssr",
|
||||
"dev:mp": "uni -p mp-weixin",
|
||||
"dev:mp-alipay": "uni -p mp-alipay",
|
||||
"dev:mp-baidu": "uni -p mp-baidu",
|
||||
"dev:mp-jd": "uni -p mp-jd",
|
||||
@@ -26,6 +54,7 @@
|
||||
"build:app-ios": "uni build -p app-ios",
|
||||
"build:app-harmony": "uni build -p app-harmony",
|
||||
"build:custom": "uni build -p",
|
||||
"build": "uni build",
|
||||
"build:h5": "uni build --mode production",
|
||||
"build:h5:ssr": "uni build --ssr",
|
||||
"build:mp-alipay": "uni build -p mp-alipay",
|
||||
@@ -41,11 +70,13 @@
|
||||
"build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
|
||||
"build:quickapp-webview-union": "uni build -p quickapp-webview-union",
|
||||
"type-check": "vue-tsc --noEmit",
|
||||
"lint": "eslint",
|
||||
"lint:fix": "eslint --fix",
|
||||
"lint:eslint": "eslint \"src/**/*.{vue,ts}\" --fix",
|
||||
"lint:prettier": "prettier --write \"**/*.{js,cjs,ts,json,css,scss,vue,html,md}\"",
|
||||
"lint:stylelint": "stylelint \"**/*.{css,scss,vue,html}\" --fix",
|
||||
"lint:lint-staged": "lint-staged",
|
||||
"prepare": "husky",
|
||||
"prepare": "git init && husky",
|
||||
"commit": "git-cz"
|
||||
},
|
||||
"lint-staged": {
|
||||
@@ -75,36 +106,38 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@dcloudio/uni-app": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-app-harmony": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-app-plus": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-components": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-h5": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-mp-alipay": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-mp-baidu": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-mp-jd": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-mp-kuaishou": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-mp-lark": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-mp-qq": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-mp-toutiao": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-mp-weixin": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-mp-xhs": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-quickapp-webview": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-app": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-app-harmony": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-app-plus": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-components": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-h5": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-mp-alipay": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-mp-baidu": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-mp-harmony": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-mp-jd": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-mp-kuaishou": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-mp-lark": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-mp-qq": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-mp-toutiao": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-mp-weixin": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-mp-xhs": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-quickapp-webview": "3.0.0-4070520250711001",
|
||||
"@stomp/stompjs": "^7.1.1",
|
||||
"@uni-helper/uni-use": "^0.19.14",
|
||||
"@vueuse/core": "9.13.0",
|
||||
"pinia": "^2.2.2",
|
||||
"vue": "^3.5.13",
|
||||
"vue": "^3.4.21",
|
||||
"vue-i18n": "^9.14.5",
|
||||
"wot-design-uni": "^1.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^19.5.0",
|
||||
"@commitlint/config-conventional": "^19.5.0",
|
||||
"@dcloudio/types": "^3.4.8",
|
||||
"@dcloudio/uni-automator": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-cli-shared": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-stacktracey": "3.0.0-4020420240722002",
|
||||
"@dcloudio/vite-plugin-uni": "3.0.0-4020420240722002",
|
||||
"@dcloudio/uni-automator": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-cli-shared": "3.0.0-4070520250711001",
|
||||
"@dcloudio/uni-stacktracey": "3.0.0-4070520250711001",
|
||||
"@dcloudio/vite-plugin-uni": "3.0.0-4070520250711001",
|
||||
"@eslint/js": "^9.10.0",
|
||||
"@uni-helper/uni-types": "1.0.0-alpha.6",
|
||||
"@uni-helper/vite-plugin-uni-components": "^0.2.0",
|
||||
@@ -139,8 +172,14 @@
|
||||
"unocss": "^0.62.4",
|
||||
"unocss-preset-weapp": "^0.62.2",
|
||||
"unplugin-auto-import": "^0.18.3",
|
||||
"vite": "6.3.2",
|
||||
"vite": "5.2.8",
|
||||
"vue-eslint-parser": "^9.4.3",
|
||||
"vue-tsc": "^1.0.24"
|
||||
},
|
||||
"resolutions": {
|
||||
"bin-wrapper": "npm:bin-wrapper-china"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*": "eslint --fix"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export default defineUniPages({
|
||||
// 导航栏配置
|
||||
navigationBarBackgroundColor: "@navBgColor",
|
||||
navigationBarTextStyle: "@navTxtStyle",
|
||||
navigationBarTitleText: "Wot-Demo",
|
||||
navigationBarTitleText: "FastApp",
|
||||
|
||||
// 页面背景配置
|
||||
backgroundColor: "@bgColor",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.6 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.5 MiB |
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "vue-uniapp-template",
|
||||
"appid": "",
|
||||
"description": "有来移动端跨端解决方案开发模板",
|
||||
"versionName": "1.0.0",
|
||||
"description": "FastApp",
|
||||
"versionName": "2.0.0",
|
||||
"versionCode": "100",
|
||||
"transformPx": false,
|
||||
"app-plus": {
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
{
|
||||
"easycom": {
|
||||
"autoscan": true,
|
||||
"custom": {
|
||||
"^wd-(.*)": "wot-design-uni/components/wd-$1/wd-$1.vue"
|
||||
}
|
||||
},
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
@@ -77,7 +83,7 @@
|
||||
"globalStyle": {
|
||||
"navigationBarBackgroundColor": "@navBgColor",
|
||||
"navigationBarTextStyle": "@navTxtStyle",
|
||||
"navigationBarTitleText": "Wot-Demo",
|
||||
"navigationBarTitleText": "FastApp",
|
||||
"backgroundColor": "@bgColor",
|
||||
"backgroundTextStyle": "@bgTxtStyle",
|
||||
"backgroundColorTop": "@bgColorTop",
|
||||
@@ -107,4 +113,4 @@
|
||||
},
|
||||
"__esModule": true,
|
||||
"subPackages": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,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,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 检查
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,386 @@
|
||||
|
||||
# 2.11.5 (2024/6/18)
|
||||
|
||||
## ✨ feat
|
||||
|
||||
- 支持后端文件导入([#142](https://github.com/youlaitech/vue3-element-admin/pull/142)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
|
||||
|
||||
## 🐛 fix
|
||||
- vue-dev-tools 插件导致菜单路由切换卡死,暂时关闭 ([28349e](https://github.com/youlaitech/vue3-element-admin/commit/28349efe147afab36531ba148eaac3a448fe6c71)) [@haoxianrui](https://github.com/haoxianrui)
|
||||
|
||||
|
||||
|
||||
# 2.11.4 (2024/6/16)
|
||||
|
||||
## ✨ feat
|
||||
|
||||
- 操作栏增加render配置参数([#138](https://github.com/youlaitech/vue3-element-admin/pull/140)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 左侧工具栏增加type配置参数([#141](https://github.com/youlaitech/vue3-element-admin/pull/141)) [@diamont1001](https://github.com/diamont1001)
|
||||
|
||||
## ♻️ refactor
|
||||
- 更换权限分配弹窗类型为 drawer 并添加父子联动开关([2d9193](https://github.com/youlaitech/vue3-element-admin/commit/2d9193c47fd224f01f82b9c0b2bbeb5e7cb33584)) [@haoxianrui](https://github.com/haoxianrui)
|
||||
|
||||
|
||||
|
||||
# 2.11.3 (2024/6/11)
|
||||
|
||||
## ✨ feat
|
||||
|
||||
- 支持默认工具栏的导入([#138](https://github.com/youlaitech/vue3-element-admin/pull/138)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 添加CURD导入示例([19e7bb](https://github.com/youlaitech/vue3-element-admin/commit/eab91effd6a01d5a3d9257249c8d06aa252b3bf8)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
|
||||
## ♻️ refactor
|
||||
- 修改导出全量数据选项文本([904fec](https://github.com/youlaitech/vue3-element-admin/commit/904fecad65217650482fcdbb10ffb7f3d27eb9ea)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
|
||||
## 🐛 fix
|
||||
- 菜单列表未适配el-icon导致图标不显示问题修复([e72b68](https://github.com/youlaitech/vue3-element-admin/commit/e72b68337562b5a7ea24ad55bbe00023e1266b40)) [@haoxianrui](https://github.com/haoxianrui)
|
||||
|
||||
# 2.11.2 (2024/6/8)
|
||||
|
||||
## ✨ feat
|
||||
|
||||
- 支持表格远程筛选([#131](https://github.com/youlaitech/vue3-element-admin/pull/131)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 支持标签输入框([#132](https://github.com/youlaitech/vue3-element-admin/pull/132)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 表单项支持tips配置([#133](https://github.com/youlaitech/vue3-element-admin/pull/133)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 前端导出支持全量数据([#134](https://github.com/youlaitech/vue3-element-admin/pull/134)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 支持选中数据导出([#135](https://github.com/youlaitech/vue3-element-admin/pull/135)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 表格默认工具栏的导出、搜索按钮增加权限点控制([883128](https://github.com/youlaitech/vue3-element-admin/commit/8831289b655f2cc086ecdababaa89f8d8a087c42)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 页签title支持动态设置([23876a](https://github.com/youlaitech/vue3-element-admin/commit/23876aa396143bf77cb5c86af8d6023d9ff6555a)) [@haoxianrui](https://github.com/haoxianrui)
|
||||
|
||||
## ♻️ refactor
|
||||
- 默认工具栏支持自定义([#136](https://github.com/youlaitech/vue3-element-admin/pull/136)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 未配置全量导出接口时选项隐藏([eab91ef](https://github.com/youlaitech/vue3-element-admin/commit/eab91effd6a01d5a3d9257249c8d06aa252b3bf8)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
|
||||
## 🐛 fix
|
||||
- 修复注销登出后redirect跳转路由参数丢失([5626017](https://github.com/youlaitech/vue3-element-admin/commit/562601736731afd20bb1a5140d856f6515720159)) [@haoxianrui](https://github.com/haoxianrui)
|
||||
|
||||
# 2.11.1 (2024/6/6)
|
||||
|
||||
## ✨ feat
|
||||
|
||||
- 增加pagination、request、parseData配置参数([#119](https://github.com/youlaitech/vue3-element-admin/pull/119)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 增加返回顶部功能([#120](https://github.com/youlaitech/vue3-element-admin/pull/120)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 支持前端导出([#126](https://github.com/youlaitech/vue3-element-admin/pull/126)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
|
||||
## ♻️ refactor
|
||||
- 重构布局样式(解决页面抖动问题)([#116](https://github.com/youlaitech/vue3-element-admin/pull/116)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 修改CURD示例编辑弹窗尺寸([#121](https://github.com/youlaitech/vue3-element-admin/pull/121)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 统一注册vue插件([#122](https://github.com/youlaitech/vue3-element-admin/pull/122)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 默认主题跟随系统([#128](https://github.com/youlaitech/vue3-element-admin/pull/128)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 增加"scss.lint.unknownAtRules": "ignore"代码,解决style中使用@apply提示unknow at rules@apply提示问题([Gitee#22](https://gitee.com/youlaiorg/vue3-element-admin/pulls/22)) [@zjsy521](https://gitee.com/zjsy521)
|
||||
|
||||
## 🐛 fix
|
||||
- 修复左侧布局移动端菜单弹出样式 ([#117](https://github.com/youlaitech/vue3-element-admin/pull/117)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
|
||||
- 修复编辑后未清空id再新增菜单覆盖的问题([0e78eeb](https://github.com/youlaitech/vue3-element-admin/commit/0e78eeb75008fa8e9732b1b4e7d7a1ea345c7a1b)) [@haoxianrui](https://github.com/haoxianrui)
|
||||
- 修复水印层级问题([#123](https://github.com/youlaitech/vue3-element-admin/pull/123)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 修复混合布局样式问题([#124](https://github.com/youlaitech/vue3-element-admin/pull/124)) [@cshaptx4869](https://github.com/cshaptx4869)
|
||||
- 修复关闭弹窗时没有clearValidate问题([#125](https://github.com/youlaitech/vue3-element-admin/pull/125)) [@andm31](https://github.com/andm31)
|
||||
|
||||
|
||||
|
||||
# 2.11.0 (2024/5/27)
|
||||
|
||||
## ✨ feat
|
||||
- 菜单添加路由参数设置(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- 增加列表选择组件(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 增加列表选择组件使用示例(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 增加defaultToolbar配置参数(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 表单弹窗支持drawer模式(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 表单项增加computed和watchEffect配置(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 支持switch属性修改(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 表单项增加文本类型支持(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 列表列增加show配置项(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 支持搜索表单显隐控制(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 支持input属性修改(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- search配置新增函数能力拓展(author by [xiudaozhe](https://github.com/xiudaozhe))
|
||||
- 表格新增列设置控制(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- 搜索添加展开和收缩(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- watch函数增加配置项参数返回(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
|
||||
## ♻️ refactor
|
||||
- 重构图标选择组件(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 重构列表选择组件默认样式 (author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 加强对话框表单组件和列表选择组件(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- routeMeta增加alwaysShow字段声明(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 分页组件增加溢出滚动效果(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 修正登录表单的Ref类型(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 点击表格刷新按钮不重置页码(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 筛选列超出一定高度滚动(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 优化加强initFn函数,表单项增加initFn函数(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 重构watch、computed、watchEffect调用(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 修改操作成功提示(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- PageSearch 改用card作为容器,样式改用unocss写法(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 优化首页 loading 动画效果author by [haoxianrui](https://github.com/haoxianrui))
|
||||
|
||||
|
||||
## 🐛 fix
|
||||
- 路由是否始终显示不限制只有顶级目录才有的配置,开放至菜单 (author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- sockjs-client 报错 global is not defined 导致开发环境无法打开 WebSocket 页面问题修复 (author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- 发送用户重启密码功能,最少为6位字符(小于6位登陆时不允许的问题) (author by [dreamnyj](https://gitee.com/dreamnyj))
|
||||
- 修复系统设置面板滚动条问题(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 修复表单插槽失效问题(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 修改tagsview刷新丢失query问题(author by [xiudaozhe](https://github.com/xiudaozhe))
|
||||
|
||||
## 📦️ build
|
||||
- 升级 NPM 包版本至最新 (author by [haoxianrui](https://github.com/haoxianrui))
|
||||
|
||||
## ⚙️ ci
|
||||
- 规整脚本执行命令(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
|
||||
|
||||
# 2.10.1 (2024/5/4)
|
||||
|
||||
## ♻️ refactor
|
||||
- 抽离CURD的使用部分代码为Hooks实现(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 修改CURD导入权限点标识名(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- cURD表单字段支持watch监听(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- cURD表单input支持number修饰(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- cURD表单组件支持checkbox多选框(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 优化axios响应数据TS类型提示(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 修改CURD表单组件自定义类型的attrs传值(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 同步重置密码按钮权限标识重命名(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- 重构API为静态方法实现模块化管理,并将types.ts重命名为model.ts用于存放接口模型定义(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
|
||||
|
||||
## 🐛 fix
|
||||
- sockjs-client 报错 global is not defined 导致开发环境无法打开 WebSocket 页面问题修复 (author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- 主题颜色设置覆盖暗黑模式下el-table行激活的背景色问题修复 (author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- 修复因API接口调整而影响的调用页面的问题 (author by [haoxianrui](https://github.com/haoxianrui))
|
||||
|
||||
## 📦️ build
|
||||
- 升级 NPM 包版本至最新 (author by [haoxianrui](https://github.com/haoxianrui))
|
||||
|
||||
|
||||
# 2.10.0 (2024/4/26)
|
||||
## ✨ feat
|
||||
- 封装增删改查组件(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 集成 vite-plugin-vue-devtools 插件(author by [Tricker39](https://github.com/Tricker39))
|
||||
- 增加CURD配置化实现(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
|
||||
|
||||
# 2.9.3 (2024/04/14)
|
||||
## ✨ feat
|
||||
- 增加vue文件代码片段(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 菜单 hover 背景色添加值全局SCSS变量进行控制(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
|
||||
## ♻️ refactor
|
||||
- 加强基础国际化(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 增加语言和布局大小枚举类型(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 增加侧边栏状态枚举类型(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 使用布局枚举替换字面量(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- 控制台使用静态数据循环渲染(author by [april](mailto:april@zen-game.cn))
|
||||
- 本地缓存的 token 变量重命名(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- 完善 Vite 环境变量类型声明(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
|
||||
## 🐛 fix
|
||||
- 修复构建时提示iconComponent.name可能为undefined的报错 (author by [wangji1042](https://github.com/wangji1042))
|
||||
- 修复浏览器密码自动填充时可能存在的报错 (author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 修复eslint报错(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 移动端下点击左侧菜单节点后关闭侧边栏(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- 添加 size 类型断言修复类型报错(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
|
||||
## 📦️ build
|
||||
- husky9.x版本适配 (author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 升级 npm 包版本至最新(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
|
||||
# 2.9.2 (2024/03/05)
|
||||
## ✨ feat
|
||||
- vscode开发扩展推荐(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 完善基础增删改查Mock接口(author by [haoxianrui](https://github.com/haoxianrui))
|
||||
|
||||
## ♻️ refactor
|
||||
- 修改login密码框功能实现(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 弱化页面进入动画效果(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 取消推荐TypeScript Vue Plugin (author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 网站加载动画替换 (author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- 优化主题和主题色监听,避免多个页面重复初始化 (author by [haoxianrui](https://github.com/haoxianrui))
|
||||
|
||||
## 🐛 fix
|
||||
- AppMain 高度在非固定头部不正确导致出现滚动条问题修复 (author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- 修复混合模式开启固定Head时的样式问题 (author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 设置面板统一字体大小 (author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
|
||||
## 📦️build
|
||||
- 通过env配置控制mock服务 (author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 升级依赖包至最新版本 (author by [haoxianrui](https://github.com/haoxianrui))
|
||||
- 定义vite全局常量替换项目标题和版本 (author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
|
||||
# 2.9.1 (2024/02/28)
|
||||
## ♻️ refactor
|
||||
- 项目配置按钮移入navbar(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 优化user数据定义(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 统一设置栏的 SVG 图标风格
|
||||
|
||||
## 🐛 fix
|
||||
- 规整一些开发依赖(author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
- 修复登录页主题切换问题 (author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
|
||||
## 🚀 pref
|
||||
|
||||
- 压缩图片资源 (author by [cshaptx4869](https://github.com/cshaptx4869))
|
||||
|
||||
|
||||
# 2.9.0 (2024/02/25)
|
||||
|
||||
## ✨ feat
|
||||
- 引入 animate.css 动画库
|
||||
- 新增水印和配置
|
||||
- 动态路由菜单支持 element plus 的图标
|
||||
|
||||
## ♻️ refactor
|
||||
- Layout 布局重构和相关问题修复
|
||||
- sass 使用 @use 替代 @import 引入外部文件指令
|
||||
|
||||
## 🐛 fix
|
||||
- 修复管理页面部分弹窗无法打开问题
|
||||
- 主题颜色设置按钮 hover 等未变化问题修复
|
||||
|
||||
|
||||
# 2.8.1 (2024/01/10)
|
||||
|
||||
## ✨ feat
|
||||
- 替换 Mock 解决方案 vite-plugin-mock 为 vite-plugin-mock-dev-server 适配 Vite5
|
||||
|
||||
# 2.8.0 (2023/12/27)
|
||||
|
||||
## ⬆️ chore
|
||||
- 升级 Vite4 至 Vite5
|
||||
|
||||
# 2.7.1 (2023/12/12)
|
||||
|
||||
## ♻️ refactor
|
||||
- 将打包后的文件进行分类 (author by [ityangzhiwen](https://gitee.com/ityangzhiwen))
|
||||
|
||||
# 2.7.0 (2023/11/19)
|
||||
|
||||
## ♻️ refactor
|
||||
- 代码重构优化
|
||||
- 修改自动导入组件类型声明文件路径
|
||||
- 完善 typescript 类型
|
||||
|
||||
## 🐛 fix
|
||||
- 修复管理页面部分弹窗无法打开问题
|
||||
|
||||
|
||||
# 2.7.0 (2023/11/19)
|
||||
|
||||
## ♻️ refactor
|
||||
- 代码重构
|
||||
- 修改自动导入组件类型声明文件路径
|
||||
- 完善 typescript 类型
|
||||
|
||||
## 🐛 fix
|
||||
- 修复管理页面部分弹窗无法打开问题
|
||||
|
||||
|
||||
# 2.6.3 (2023/10/22)
|
||||
|
||||
## ✨ feat
|
||||
- 菜单管理新增目录只有一级子路由是否始终显示(alwaysShow)和路由页面是否缓存(keepAlive)的配置
|
||||
- 接口文档新增 swagger、knife4j
|
||||
- 引入和支持 tsx
|
||||
|
||||
## ♻️ refactor
|
||||
- 代码瘦身,整理并删除未使用的 svg
|
||||
- 控制台样式优化
|
||||
|
||||
## 🐛 fix
|
||||
- 菜单栏折叠和展开的图标暗黑模式显示问题修复
|
||||
|
||||
|
||||
# 2.6.2 (2023/10/11)
|
||||
|
||||
## 🐛 fix
|
||||
- 主题设置未持久化问题
|
||||
- UnoCSS 插件无智能提示
|
||||
|
||||
## ♻️ refactor
|
||||
- WebSocket 演示样式和代码优化
|
||||
- 用户管理代码重构
|
||||
|
||||
# 2.6.1 (2023/9/4)
|
||||
|
||||
## 🐛 fix
|
||||
- 导航顶部模式、混合模式样式在固定 Header 出现的样式问题修复
|
||||
- 固定 Header 没有持久化问题修复
|
||||
- 字典回显兼容 String 和 Number 类型
|
||||
|
||||
# 2.6.0 (2023/8/24)💥💥💥
|
||||
|
||||
## ✨ feat
|
||||
- 导航顶部模式、混合模式支持(author by [april-tong](https://april-tong.com/))
|
||||
- 平台文档(内嵌)(author by [april-tong](https://april-tong.com/))
|
||||
|
||||
# 2.5.0 (2023/8/8)
|
||||
|
||||
## ✨ feat
|
||||
- 新增 Mock(author by [ygcaicn](https://github.com/ygcaicn))
|
||||
- 图标 DEMO(author by [ygcaicn](https://github.com/ygcaicn))
|
||||
|
||||
## 🐛 fix
|
||||
- 字典支持 Number 类型
|
||||
|
||||
# 2.4.1 (2023/7/20)
|
||||
|
||||
## ✨ feat
|
||||
- 整合 vite-plugin-compression 插件打包优化(3.66MB → 1.58MB) (author by [april-tong](https://april-tong.com/))
|
||||
- 字典组件封装(author by [haoxr](https://juejin.cn/user/4187394044331261/posts))
|
||||
|
||||
## 🐛 fix
|
||||
- 分页组件hidden无效
|
||||
- 签名无法保存至后端
|
||||
- Git 提交 stylelint 校验部分机器报错
|
||||
|
||||
# 2.4.0 (2023/6/17)
|
||||
|
||||
## ✨ feat
|
||||
- 新增组件标签输入框(author by [april-tong](https://april-tong.com/))
|
||||
- 新增组件签名(author by [april-tong](https://april-tong.com/))
|
||||
- 新增组件表格(author by [april-tong](https://april-tong.com/))
|
||||
- Echarts 图表添加下载功能 author by [april-tong](https://april-tong.com/))
|
||||
|
||||
## ♻️ refactor
|
||||
- 限制包管理器为 pnpm 和 node 版本16+
|
||||
- 自定义组件自动导入配置
|
||||
- 搜索框样式写法优化
|
||||
|
||||
## 🐛 fix
|
||||
- 用户导入的部门回显成数字问题修复
|
||||
|
||||
## ⬆️ chore
|
||||
- element-plus 版本升级 2.3.5 → 2.3.6
|
||||
|
||||
# 2.3.1 (2023/5/21)
|
||||
|
||||
## 🔄 refactor
|
||||
- 组件示例文件名称优化
|
||||
|
||||
# 2.2.2 (2023/5/11)
|
||||
|
||||
## ✨ feat
|
||||
- 组件封装示例添加源码地址
|
||||
- 角色、菜单、部门、字段按钮添加权限控制
|
||||
|
||||
|
||||
# 2.3.0 (2023/5/12)
|
||||
|
||||
## ⬆️ chore
|
||||
- vue 版本升级 3.2.45 → 3.3.1 ([CHANGELOG](https://github.com/vuejs/core/blob/main/CHANGELOG.md))
|
||||
- vite 版本升级 4.3.1 → 4.3.5
|
||||
|
||||
## ♻️ refactor
|
||||
- 使用 vue 3.3 版本新特性 `defineOptions` 在 `setup` 定义组件名称,移除重复的 `script` 标签
|
||||
|
||||
# 2.2.2 (2023/5/11)
|
||||
|
||||
## ✨ feat
|
||||
- 用户新增提交添加 `vueUse` 的 `useDebounceFn` 函数实现按钮防抖节流
|
||||
|
||||
|
||||
# 2.2.1 (2023/4/25)
|
||||
|
||||
## 🐛 fix
|
||||
- 图标选择器组件使用 `onClickOutside` 未排除下拉弹出框元素导致无法输入搜索。
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
module.exports = {
|
||||
// 继承的规则
|
||||
extends: ["@commitlint/config-conventional"],
|
||||
// 自定义规则
|
||||
rules: {
|
||||
// @see https://commitlint.js.org/#/reference-rules
|
||||
|
||||
// 提交类型枚举,git提交type必须是以下类型
|
||||
"type-enum": [
|
||||
2,
|
||||
"always",
|
||||
[
|
||||
"feat", // 新增功能
|
||||
"fix", // 修复缺陷
|
||||
"docs", // 文档变更
|
||||
"style", // 代码格式(不影响功能,例如空格、分号等格式修正)
|
||||
"refactor", // 代码重构(不包括 bug 修复、功能新增)
|
||||
"perf", // 性能优化
|
||||
"test", // 添加疏漏测试或已有测试改动
|
||||
"build", // 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)
|
||||
"ci", // 修改 CI 配置、脚本
|
||||
"revert", // 回滚 commit
|
||||
"chore", // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)
|
||||
"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,216 @@
|
||||
// https://eslint.org/docs/latest/use/configure/configuration-files-new
|
||||
|
||||
import eslint from "@eslint/js";
|
||||
import pluginVue from "eslint-plugin-vue";
|
||||
import * as typescriptEslint from "typescript-eslint";
|
||||
import vueParser from "vue-eslint-parser";
|
||||
import globals from "globals";
|
||||
import configPrettier from "eslint-config-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",
|
||||
],
|
||||
},
|
||||
|
||||
// 基础 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"],
|
||||
},
|
||||
},
|
||||
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: {
|
||||
project: true,
|
||||
tsconfigRootDir: import.meta.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", // 降级为警告
|
||||
"@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 集成(必须放在最后)
|
||||
configPrettier,
|
||||
];
|
||||
+85
-9
@@ -5,18 +5,69 @@
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"i": "pnpm install",
|
||||
"dev": "vite",
|
||||
"prod": "vite --mode prod",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"docs:dev": "vitepress dev docs",
|
||||
"docs:build": "vitepress build docs",
|
||||
"docs:preview": "vitepress preview docs"
|
||||
"docs:preview": "vitepress preview docs",
|
||||
"build:pro": "pnpm vite build --mode pro",
|
||||
"build:gitee": "pnpm vite build --mode gitee",
|
||||
"build:dev": "pnpm vite build --mode dev",
|
||||
"build:test": "pnpm vite build --mode test",
|
||||
"serve:pro": "pnpm vite preview --mode pro",
|
||||
"serve:dev": "pnpm vite preview --mode dev",
|
||||
"serve:test": "pnpm vite preview --mode test",
|
||||
"clean": "pnpx rimraf node_modules",
|
||||
"ts:check": "pnpm vue-tsc --noEmit --skipLibCheck",
|
||||
"npm:check": "pnpx npm-check-updates -u",
|
||||
"clean:cache": "pnpx rimraf node_modules/.cache",
|
||||
"prepare": "husky install",
|
||||
"p": "plop",
|
||||
"icon": "esno ./scripts/icon.ts",
|
||||
"preview": "vite preview",
|
||||
"type-check": "vue-tsc --noEmit",
|
||||
"lint:format": "prettier --write --loglevel warn \"src/**/*.{js,ts,json,tsx,css,less,vue,html,md}\"",
|
||||
"lint:style": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
|
||||
"lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.cjs",
|
||||
"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": "npm run lint:eslint && npm run lint:prettier && npm run lint:stylelint",
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"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.1",
|
||||
"@vueuse/core": "^13.5.0",
|
||||
"@wangeditor-next/editor": "^5.6.38",
|
||||
"@wangeditor-next/editor": "^5.6.42",
|
||||
"@wangeditor-next/editor-for-vue": "^5.1.14",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^1.10.0",
|
||||
@@ -39,26 +90,51 @@
|
||||
"vue3-cron-plus": "^0.1.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.32.0",
|
||||
"@iconify/utils": "^2.3.0",
|
||||
"@types/codemirror": "^5.60.16",
|
||||
"@types/node": "^22.16.5",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/path-browserify": "^1.0.3",
|
||||
"@types/qs": "^6.14.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
||||
"@typescript-eslint/parser": "^8.38.0",
|
||||
"@vitejs/plugin-vue": "^5.2.4",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"commitizen": "^4.3.1",
|
||||
"cz-git": "^1.12.0",
|
||||
"eslint": "^9.32.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.3",
|
||||
"eslint-plugin-vue": "^10.4.0",
|
||||
"fs-extra": "^11.2.0",
|
||||
"husky": "^9.1.7",
|
||||
"sass": "^1.89.2",
|
||||
"terser": "^5.43.1",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.38.0",
|
||||
"unocss": "66.2.3",
|
||||
"unplugin-auto-import": "^19.3.0",
|
||||
"unplugin-vue-components": "^28.8.0",
|
||||
"vite": "^6.3.5",
|
||||
"vitepress": "^1.6.4"
|
||||
"vitepress": "^1.6.4",
|
||||
"vue-eslint-parser": "^10.2.0",
|
||||
"vue-tsc": "^2.2.12"
|
||||
},
|
||||
"packageManager": "pnpm@9.15.3",
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"npm": ">=10.0.0"
|
||||
"npm": ">=10.0.0",
|
||||
"pnpm": ">=8.1.0"
|
||||
},
|
||||
"repository": "https://gitee.com/tao__tao/fastapi_vue3_admin.git",
|
||||
"author": "948080782@qq.com",
|
||||
"license": "MIT"
|
||||
}
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://gitee.com/tao__tao/fastapi_vue3_admin.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://gitee.com/tao__tao/fastapi_vue3_admin/issues"
|
||||
},
|
||||
"author": "fastapiadmin <502431556@qq.com>",
|
||||
"license": "MIT",
|
||||
"homepage": "https://gitee.com/tao__tao/fastapi_vue3_admin"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
const GENERATOR_BASE_URL = "/api/v1/codegen";
|
||||
|
||||
const GeneratorAPI = {
|
||||
/** 获取数据表分页列表 */
|
||||
getTablePage(params: TablePageQuery) {
|
||||
return request<any, PageResult<TablePageVO[]>>({
|
||||
url: `${GENERATOR_BASE_URL}/table/page`,
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
},
|
||||
|
||||
/** 获取代码生成配置 */
|
||||
getGenConfig(tableName: string) {
|
||||
return request<any, GenConfigForm>({
|
||||
url: `${GENERATOR_BASE_URL}/${tableName}/config`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
/** 获取代码生成配置 */
|
||||
saveGenConfig(tableName: string, data: GenConfigForm) {
|
||||
return request({
|
||||
url: `${GENERATOR_BASE_URL}/${tableName}/config`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
/** 获取代码生成预览数据 */
|
||||
getPreviewData(tableName: string) {
|
||||
return request<any, GeneratorPreviewVO[]>({
|
||||
url: `${GENERATOR_BASE_URL}/${tableName}/preview`,
|
||||
method: "get",
|
||||
});
|
||||
},
|
||||
|
||||
/** 重置代码生成配置 */
|
||||
resetGenConfig(tableName: string) {
|
||||
return request({
|
||||
url: `${GENERATOR_BASE_URL}/${tableName}/config`,
|
||||
method: "delete",
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 下载 ZIP 文件
|
||||
* @param url
|
||||
* @param fileName
|
||||
*/
|
||||
download(tableName: string) {
|
||||
return request({
|
||||
url: `${GENERATOR_BASE_URL}/${tableName}/download`,
|
||||
method: "get",
|
||||
responseType: "blob",
|
||||
}).then((response) => {
|
||||
const fileName = decodeURI(
|
||||
response.headers["content-disposition"].split(";")[1].split("=")[1]
|
||||
);
|
||||
|
||||
const blob = new Blob([response.data], { type: "application/zip" });
|
||||
const a = document.createElement("a");
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
a.href = url;
|
||||
a.download = fileName;
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default GeneratorAPI;
|
||||
|
||||
/** 代码生成预览对象 */
|
||||
export interface GeneratorPreviewVO {
|
||||
/** 文件生成路径 */
|
||||
path: string;
|
||||
/** 文件名称 */
|
||||
fileName: string;
|
||||
/** 文件内容 */
|
||||
content: string;
|
||||
}
|
||||
|
||||
/** 数据表分页查询参数 */
|
||||
export interface TablePageQuery extends PageQuery {
|
||||
/** 关键字(表名) */
|
||||
keywords?: string;
|
||||
}
|
||||
|
||||
/** 数据表分页对象 */
|
||||
export interface TablePageVO {
|
||||
/** 表名称 */
|
||||
tableName: string;
|
||||
|
||||
/** 表描述 */
|
||||
tableComment: string;
|
||||
|
||||
/** 存储引擎 */
|
||||
engine: string;
|
||||
|
||||
/** 字符集排序规则 */
|
||||
tableCollation: string;
|
||||
|
||||
/** 创建时间 */
|
||||
createTime: string;
|
||||
}
|
||||
|
||||
/** 代码生成配置表单 */
|
||||
export interface GenConfigForm {
|
||||
/** 主键 */
|
||||
id?: string;
|
||||
|
||||
/** 表名 */
|
||||
tableName?: string;
|
||||
|
||||
/** 业务名 */
|
||||
businessName?: string;
|
||||
|
||||
/** 模块名 */
|
||||
moduleName?: string;
|
||||
|
||||
/** 包名 */
|
||||
packageName?: string;
|
||||
|
||||
/** 实体名 */
|
||||
entityName?: string;
|
||||
|
||||
/** 作者 */
|
||||
author?: string;
|
||||
|
||||
/** 上级菜单 */
|
||||
parentMenuId?: string;
|
||||
|
||||
/** 后端应用名 */
|
||||
backendAppName?: string;
|
||||
/** 前端应用名 */
|
||||
frontendAppName?: string;
|
||||
|
||||
/** 字段配置列表 */
|
||||
fieldConfigs?: FieldConfig[];
|
||||
}
|
||||
|
||||
/** 字段配置 */
|
||||
export interface FieldConfig {
|
||||
/** 主键 */
|
||||
id?: string;
|
||||
|
||||
/** 列名 */
|
||||
columnName?: string;
|
||||
|
||||
/** 列类型 */
|
||||
columnType?: string;
|
||||
|
||||
/** 字段名 */
|
||||
fieldName?: string;
|
||||
|
||||
/** 字段类型 */
|
||||
fieldType?: string;
|
||||
|
||||
/** 字段描述 */
|
||||
fieldComment?: string;
|
||||
|
||||
/** 是否在列表显示 */
|
||||
isShowInList?: number;
|
||||
|
||||
/** 是否在表单显示 */
|
||||
isShowInForm?: number;
|
||||
|
||||
/** 是否在查询条件显示 */
|
||||
isShowInQuery?: number;
|
||||
|
||||
/** 是否必填 */
|
||||
isRequired?: number;
|
||||
|
||||
/** 表单类型 */
|
||||
formType?: number;
|
||||
|
||||
/** 查询类型 */
|
||||
queryType?: number;
|
||||
|
||||
/** 字段长度 */
|
||||
maxLength?: number;
|
||||
|
||||
/** 字段排序 */
|
||||
fieldSort?: number;
|
||||
|
||||
/** 字典类型 */
|
||||
dictType?: string;
|
||||
}
|
||||
@@ -0,0 +1,866 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 搜索区域 -->
|
||||
<div class="search-container">
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item prop="keywords" label="关键字">
|
||||
<el-input
|
||||
v-model="queryParams.keywords"
|
||||
placeholder="表名"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item class="search-buttons">
|
||||
<el-button type="primary" @click="handleQuery">
|
||||
<template #icon>
|
||||
<Search />
|
||||
</template>
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button @click="handleResetQuery">
|
||||
<template #icon>
|
||||
<Refresh />
|
||||
</template>
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<el-card shadow="hover" class="table-card">
|
||||
<el-table
|
||||
ref="dataTableRef"
|
||||
v-loading="loading"
|
||||
:data="pageData"
|
||||
highlight-current-row
|
||||
border
|
||||
class="data-table__content"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="表名" prop="tableName" min-width="100" />
|
||||
<el-table-column label="描述" prop="tableComment" width="150" />
|
||||
|
||||
<el-table-column label="存储引擎" align="center" prop="engine" />
|
||||
|
||||
<el-table-column label="排序规则" align="center" prop="tableCollation" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" />
|
||||
|
||||
<el-table-column fixed="right" label="操作" width="200">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
link
|
||||
@click="handleOpenDialog(scope.row.tableName)"
|
||||
>
|
||||
<template #icon>
|
||||
<MagicStick />
|
||||
</template>
|
||||
生成代码
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
v-if="scope.row.isConfigured === 1"
|
||||
type="danger"
|
||||
size="small"
|
||||
link
|
||||
@click="handleResetConfig(scope.row.tableName)"
|
||||
>
|
||||
<template #icon>
|
||||
<RefreshLeft />
|
||||
</template>
|
||||
重置配置
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-if="total > 0"
|
||||
v-model:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<el-drawer
|
||||
v-model="dialog.visible"
|
||||
:title="dialog.title"
|
||||
size="80%"
|
||||
@close="dialog.visible = false"
|
||||
>
|
||||
<el-steps :active="active" align-center finish-status="success" simple>
|
||||
<el-step title="基础配置" />
|
||||
<el-step title="字段配置" />
|
||||
<el-step title="预览生成" />
|
||||
</el-steps>
|
||||
|
||||
<div class="mt-5">
|
||||
<el-form
|
||||
v-show="active == 0"
|
||||
:model="genConfigFormData"
|
||||
:label-width="100"
|
||||
:rules="genConfigFormRules"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="表名" prop="tableName">
|
||||
<el-input v-model="genConfigFormData.tableName" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="业务名" prop="businessName">
|
||||
<el-input v-model="genConfigFormData.businessName" placeholder="用户" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="主包名" prop="packageName">
|
||||
<el-input v-model="genConfigFormData.packageName" placeholder="com.youlai.boot" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="模块名" prop="moduleName">
|
||||
<el-input v-model="genConfigFormData.moduleName" placeholder="system" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="实体名" prop="entityName">
|
||||
<el-input v-model="genConfigFormData.entityName" placeholder="User" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="作者">
|
||||
<el-input v-model="genConfigFormData.author" placeholder="youlai" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex-y-between">
|
||||
<span>上级菜单</span>
|
||||
<el-tooltip effect="dark">
|
||||
<template #content>
|
||||
选择上级菜单,生成代码后会自动创建对应菜单。
|
||||
<br />
|
||||
注意1:生成菜单后需分配权限给角色,否则菜单将无法显示。
|
||||
<br />
|
||||
注意2:演示环境默认不生成菜单,如需生成,请在本地部署数据库。
|
||||
</template>
|
||||
<el-icon class="cursor-pointer">
|
||||
<QuestionFilled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-tree-select
|
||||
v-model="genConfigFormData.parentMenuId"
|
||||
placeholder="选择上级菜单"
|
||||
:data="menuOptions"
|
||||
check-strictly
|
||||
:render-after-expand="false"
|
||||
filterable
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<div v-show="active == 1" class="elTableCustom">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
row-key="id"
|
||||
:element-loading-text="loadingText"
|
||||
highlight--currentrow
|
||||
:data="genConfigFormData.fieldConfigs"
|
||||
>
|
||||
<el-table-column width="55" align="center">
|
||||
<el-icon class="cursor-move sortable-handle">
|
||||
<Rank />
|
||||
</el-icon>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="列名" width="110">
|
||||
<template #default="scope">
|
||||
{{ scope.row.columnName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="列类型" width="80">
|
||||
<template #default="scope">
|
||||
{{ scope.row.columnType }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="字段名" width="120">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.fieldName" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="字段类型" width="80">
|
||||
<template #default="scope">
|
||||
{{ scope.row.fieldType }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="字段注释" min-width="100">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.fieldComment" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="最大长度" width="80">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.maxLength" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="70">
|
||||
<template #header>
|
||||
<div class="flex-y-center">
|
||||
<span>查询</span>
|
||||
<el-checkbox
|
||||
v-model="isCheckAllQuery"
|
||||
class="ml-1"
|
||||
@change="toggleCheckAll('isShowInQuery', isCheckAllQuery)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-checkbox v-model="scope.row.isShowInQuery" :true-value="1" :false-value="0" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="70">
|
||||
<template #header>
|
||||
<div class="flex-y-center">
|
||||
<span>列表</span>
|
||||
<el-checkbox
|
||||
v-model="isCheckAllList"
|
||||
class="ml-1"
|
||||
@change="toggleCheckAll('isShowInList', isCheckAllList)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #default="scope">
|
||||
<el-checkbox v-model="scope.row.isShowInList" :true-value="1" :false-value="0" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="70">
|
||||
<template #header>
|
||||
<div class="flex-y-center">
|
||||
<span>表单</span>
|
||||
<el-checkbox
|
||||
v-model="isCheckAllForm"
|
||||
class="ml-1"
|
||||
@change="toggleCheckAll('isShowInForm', isCheckAllForm)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #default="scope">
|
||||
<el-checkbox v-model="scope.row.isShowInForm" :true-value="1" :false-value="0" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="必填" width="70">
|
||||
<template #default="scope">
|
||||
<el-checkbox
|
||||
v-if="scope.row.isShowInForm == 1"
|
||||
v-model="scope.row.isRequired"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
/>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="查询方式" min-width="120">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-if="scope.row.isShowInQuery === 1"
|
||||
v-model="scope.row.queryType"
|
||||
placeholder="请选择"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, key) in queryTypeOptions"
|
||||
:key="key"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="表单类型" min-width="120">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-if="scope.row.isShowInQuery === 1 || scope.row.isShowInForm === 1"
|
||||
v-model="scope.row.formType"
|
||||
placeholder="请选择"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, key) in formTypeOptions"
|
||||
:key="key"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="字典类型" min-width="100">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-if="scope.row.formType === FormTypeEnum.SELECT.value"
|
||||
v-model="scope.row.dictType"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in dictOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<el-row v-show="active == 2">
|
||||
<el-col :span="6">
|
||||
<el-scrollbar max-height="72vh">
|
||||
<el-tree
|
||||
:data="treeData"
|
||||
default-expand-all
|
||||
highlight-current
|
||||
@node-click="handleFileTreeNodeClick"
|
||||
>
|
||||
<template #default="{ data }">
|
||||
<div :class="`i-svg:${getFileTreeNodeIcon(data.label)}`" />
|
||||
<span class="ml-1">{{ data.label }}</span>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-scrollbar max-height="72vh">
|
||||
<div class="absolute z-36 right-5 top-2">
|
||||
<el-link type="primary" @click="handleCopyCode">
|
||||
<el-icon>
|
||||
<CopyDocument />
|
||||
</el-icon>
|
||||
一键复制
|
||||
</el-link>
|
||||
</div>
|
||||
|
||||
<Codemirror
|
||||
ref="cmRef"
|
||||
v-model:value="code"
|
||||
:options="cmOptions"
|
||||
border
|
||||
:readonly="true"
|
||||
height="100%"
|
||||
width="100%"
|
||||
/>
|
||||
</el-scrollbar>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button v-if="active !== 0" type="success" @click="handlePrevClick">
|
||||
<el-icon>
|
||||
<Back />
|
||||
</el-icon>
|
||||
{{ prevBtnText }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="handleNextClick">
|
||||
{{ nextBtnText }}
|
||||
<el-icon v-if="active !== 2">
|
||||
<Right />
|
||||
</el-icon>
|
||||
<el-icon v-else>
|
||||
<Download />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({
|
||||
name: "Codegen",
|
||||
});
|
||||
|
||||
import Sortable from "sortablejs";
|
||||
import "codemirror/mode/javascript/javascript.js";
|
||||
import Codemirror from "codemirror-editor-vue3";
|
||||
import type { CmComponentRef } from "codemirror-editor-vue3";
|
||||
import type { EditorConfiguration } from "codemirror";
|
||||
|
||||
import { FormTypeEnum } from "@/enums/codegen/form.enum";
|
||||
import { QueryTypeEnum } from "@/enums/codegen/query.enum";
|
||||
|
||||
import GeneratorAPI, {
|
||||
TablePageVO,
|
||||
GenConfigForm,
|
||||
TablePageQuery,
|
||||
FieldConfig,
|
||||
} from "@/api/codegen.api";
|
||||
|
||||
import DictAPI from "@/api/system/dict.api";
|
||||
import MenuAPI from "@/api/system/menu.api";
|
||||
|
||||
interface TreeNode {
|
||||
label: string;
|
||||
content?: string;
|
||||
children?: TreeNode[];
|
||||
}
|
||||
const treeData = ref<TreeNode[]>([]);
|
||||
|
||||
const queryFormRef = ref();
|
||||
const queryParams = reactive<TablePageQuery>({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
const loading = ref(false);
|
||||
const loadingText = ref("loading...");
|
||||
|
||||
const pageData = ref<TablePageVO[]>([]);
|
||||
const total = ref(0);
|
||||
|
||||
const formTypeOptions: Record<string, OptionType> = FormTypeEnum;
|
||||
const queryTypeOptions: Record<string, OptionType> = QueryTypeEnum;
|
||||
const dictOptions = ref<OptionType[]>();
|
||||
const menuOptions = ref<OptionType[]>([]);
|
||||
const genConfigFormData = ref<GenConfigForm>({
|
||||
fieldConfigs: [],
|
||||
});
|
||||
|
||||
const genConfigFormRules = {
|
||||
tableName: [{ required: true, message: "请输入表名", trigger: "blur" }],
|
||||
businessName: [{ required: true, message: "请输入业务名", trigger: "blur" }],
|
||||
packageName: [{ required: true, message: "请输入主包名", trigger: "blur" }],
|
||||
moduleName: [{ required: true, message: "请输入模块名", trigger: "blur" }],
|
||||
entityName: [{ required: true, message: "请输入实体名", trigger: "blur" }],
|
||||
};
|
||||
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: "",
|
||||
});
|
||||
|
||||
const { copy, copied } = useClipboard();
|
||||
const code = ref();
|
||||
const cmRef = ref<CmComponentRef>();
|
||||
const cmOptions: EditorConfiguration = {
|
||||
mode: "text/javascript",
|
||||
};
|
||||
|
||||
const prevBtnText = ref("");
|
||||
const nextBtnText = ref("下一步,字段配置");
|
||||
const active = ref(0);
|
||||
const currentTableName = ref("");
|
||||
const sortFlag = ref<object>();
|
||||
|
||||
// 查询是否全选
|
||||
const isCheckAllQuery = ref(false);
|
||||
// 列表是否全选
|
||||
const isCheckAllList = ref(false);
|
||||
// 表单是否全选
|
||||
const isCheckAllForm = ref(false);
|
||||
|
||||
watch(active, (val) => {
|
||||
if (val === 0) {
|
||||
nextBtnText.value = "下一步,字段配置";
|
||||
} else if (val === 1) {
|
||||
prevBtnText.value = "上一步,基础配置";
|
||||
nextBtnText.value = "下一步,确认生成";
|
||||
} else if (val === 2) {
|
||||
prevBtnText.value = "上一步,字段配置";
|
||||
nextBtnText.value = "下载代码";
|
||||
}
|
||||
});
|
||||
|
||||
watch(copied, () => {
|
||||
if (copied.value) {
|
||||
ElMessage.success("复制成功");
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => genConfigFormData.value.fieldConfigs as FieldConfig[],
|
||||
(newVal: FieldConfig[]) => {
|
||||
newVal.forEach((fieldConfig) => {
|
||||
if (
|
||||
fieldConfig.fieldType &&
|
||||
fieldConfig.fieldType.includes("Date") &&
|
||||
fieldConfig.isShowInQuery === 1
|
||||
) {
|
||||
fieldConfig.queryType = QueryTypeEnum.BETWEEN.value as number;
|
||||
}
|
||||
});
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
);
|
||||
|
||||
const initSort = () => {
|
||||
if (sortFlag.value) {
|
||||
return;
|
||||
}
|
||||
const table = document.querySelector(".elTableCustom .el-table__body-wrapper tbody");
|
||||
sortFlag.value = Sortable.create(<HTMLElement>table, {
|
||||
group: "shared",
|
||||
animation: 150,
|
||||
ghostClass: "sortable-ghost", //拖拽样式
|
||||
handle: ".sortable-handle", //拖拽区域
|
||||
easing: "cubic-bezier(1, 0, 0, 1)",
|
||||
|
||||
// 结束拖动事件
|
||||
onEnd: (item: any) => {
|
||||
setNodeSort(item.oldIndex, item.newIndex);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const setNodeSort = (oldIndex: number, newIndex: number) => {
|
||||
// 使用arr复制一份表格数组数据
|
||||
const arr = Object.assign([], genConfigFormData.value.fieldConfigs);
|
||||
const currentRow = arr.splice(oldIndex, 1)[0];
|
||||
arr.splice(newIndex, 0, currentRow);
|
||||
arr.forEach((item: FieldConfig, index) => {
|
||||
item.fieldSort = index + 1;
|
||||
});
|
||||
genConfigFormData.value.fieldConfigs = [];
|
||||
nextTick(async () => {
|
||||
genConfigFormData.value.fieldConfigs = arr;
|
||||
});
|
||||
};
|
||||
|
||||
/** 上一步 */
|
||||
function handlePrevClick() {
|
||||
if (active.value === 2) {
|
||||
//这里需要重新获取一次数据,如果第一次生成代码后,再次点击上一步,数据不重新获取,再次点击下一步,会再次插入数据,导致索引重复报错
|
||||
genConfigFormData.value = {
|
||||
fieldConfigs: [],
|
||||
};
|
||||
nextTick(() => {
|
||||
loading.value = true;
|
||||
GeneratorAPI.getGenConfig(currentTableName.value)
|
||||
.then((data) => {
|
||||
genConfigFormData.value = data;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
});
|
||||
initSort();
|
||||
}
|
||||
if (active.value-- <= 0) active.value = 0;
|
||||
}
|
||||
|
||||
/** 下一步 */
|
||||
function handleNextClick() {
|
||||
if (active.value === 0) {
|
||||
//这里需要校验基础配置
|
||||
const { tableName, packageName, businessName, moduleName, entityName } =
|
||||
genConfigFormData.value;
|
||||
if (!tableName || !packageName || !businessName || !moduleName || !entityName) {
|
||||
ElMessage.error("表名、业务名、包名、模块名、实体名不能为空");
|
||||
return;
|
||||
}
|
||||
initSort();
|
||||
}
|
||||
if (active.value === 1) {
|
||||
// 保存生成配置
|
||||
const tableName = genConfigFormData.value.tableName;
|
||||
if (!tableName) {
|
||||
ElMessage.error("表名不能为空");
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
loadingText.value = "代码生成中,请稍后...";
|
||||
GeneratorAPI.saveGenConfig(tableName, genConfigFormData.value)
|
||||
.then(() => {
|
||||
handlePreview(tableName);
|
||||
})
|
||||
.then(() => {
|
||||
if (active.value++ >= 2) active.value = 2;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
loadingText.value = "loading...";
|
||||
});
|
||||
} else {
|
||||
if (active.value++ >= 2) {
|
||||
active.value = 2;
|
||||
}
|
||||
if (active.value === 2) {
|
||||
const tableName = genConfigFormData.value.tableName;
|
||||
if (!tableName) {
|
||||
ElMessage.error("表名不能为空");
|
||||
return;
|
||||
}
|
||||
GeneratorAPI.download(tableName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询 */
|
||||
function handleQuery() {
|
||||
loading.value = true;
|
||||
GeneratorAPI.getTablePage(queryParams)
|
||||
.then((data) => {
|
||||
pageData.value = data.list;
|
||||
total.value = data.total;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
/** 重置查询 */
|
||||
function handleResetQuery() {
|
||||
queryFormRef.value.resetFields();
|
||||
queryParams.pageNum = 1;
|
||||
handleQuery();
|
||||
}
|
||||
|
||||
/** 打开弹窗 */
|
||||
async function handleOpenDialog(tableName: string) {
|
||||
dialog.visible = true;
|
||||
active.value = 0;
|
||||
|
||||
menuOptions.value = await MenuAPI.getOptions(true);
|
||||
|
||||
currentTableName.value = tableName;
|
||||
// 获取字典数据
|
||||
DictAPI.getList().then((data) => {
|
||||
dictOptions.value = data;
|
||||
loading.value = true;
|
||||
GeneratorAPI.getGenConfig(tableName)
|
||||
.then((data) => {
|
||||
dialog.title = `${tableName} 代码生成`;
|
||||
genConfigFormData.value = data;
|
||||
|
||||
checkAllSelected("isShowInQuery", isCheckAllQuery);
|
||||
checkAllSelected("isShowInList", isCheckAllList);
|
||||
checkAllSelected("isShowInForm", isCheckAllForm);
|
||||
|
||||
// 如果已经配置过,直接跳转到预览页面
|
||||
if (genConfigFormData.value.id) {
|
||||
active.value = 2;
|
||||
handlePreview(tableName);
|
||||
} else {
|
||||
// 如果没有配置过,跳转到基础配置页面
|
||||
active.value = 0;
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** 重置配置 */
|
||||
function handleResetConfig(tableName: string) {
|
||||
ElMessageBox.confirm("确定要重置配置吗?", "提示", {
|
||||
type: "warning",
|
||||
}).then(() => {
|
||||
GeneratorAPI.resetGenConfig(tableName).then(() => {
|
||||
ElMessage.success("重置成功");
|
||||
handleQuery();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
type FieldConfigKey = "isShowInQuery" | "isShowInList" | "isShowInForm";
|
||||
|
||||
/** 全选 */
|
||||
const toggleCheckAll = (key: FieldConfigKey, value: boolean) => {
|
||||
const fieldConfigs = genConfigFormData.value?.fieldConfigs;
|
||||
|
||||
if (fieldConfigs) {
|
||||
fieldConfigs.forEach((row: FieldConfig) => {
|
||||
row[key] = value ? 1 : 0;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const checkAllSelected = (key: keyof FieldConfig, isCheckAllRef: any) => {
|
||||
const fieldConfigs = genConfigFormData.value?.fieldConfigs || [];
|
||||
isCheckAllRef.value = fieldConfigs.every((row: FieldConfig) => row[key] === 1);
|
||||
};
|
||||
|
||||
/** 获取生成预览 */
|
||||
function handlePreview(tableName: string) {
|
||||
treeData.value = [];
|
||||
GeneratorAPI.getPreviewData(tableName)
|
||||
.then((data) => {
|
||||
dialog.title = `代码生成 ${tableName}`;
|
||||
// 组装树形结构完善代码
|
||||
const tree = buildTree(data);
|
||||
treeData.value = [tree];
|
||||
|
||||
// 默认选中第一个叶子节点并设置 code 值
|
||||
const firstLeafNode = findFirstLeafNode(tree);
|
||||
if (firstLeafNode) {
|
||||
code.value = firstLeafNode.content || "";
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
active.value = 0;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归构建树形结构
|
||||
*
|
||||
* @param data - 数据数组
|
||||
* @returns 树形结构根节点
|
||||
*/
|
||||
function buildTree(data: { path: string; fileName: string; content: string }[]): TreeNode {
|
||||
// 动态获取根节点
|
||||
const root: TreeNode = { label: "前后端代码", children: [] };
|
||||
|
||||
data.forEach((item) => {
|
||||
// 将路径分成数组
|
||||
const separator = item.path.includes("/") ? "/" : "\\";
|
||||
const parts = item.path.split(separator);
|
||||
|
||||
// 定义特殊路径
|
||||
const specialPaths = [
|
||||
"src" + separator + "main",
|
||||
"java",
|
||||
genConfigFormData.value.backendAppName,
|
||||
genConfigFormData.value.frontendAppName,
|
||||
(genConfigFormData.value.packageName + "." + genConfigFormData.value.moduleName).replace(
|
||||
/\./g,
|
||||
separator
|
||||
),
|
||||
];
|
||||
|
||||
// 检查路径中的特殊部分并合并它们
|
||||
const mergedParts: string[] = [];
|
||||
let buffer: string[] = [];
|
||||
|
||||
parts.forEach((part) => {
|
||||
buffer.push(part);
|
||||
const currentPath = buffer.join(separator);
|
||||
if (specialPaths.includes(currentPath)) {
|
||||
mergedParts.push(currentPath);
|
||||
buffer = [];
|
||||
}
|
||||
});
|
||||
|
||||
// 将 mergedParts 路径中的分隔符\替换为/
|
||||
mergedParts.forEach((part, index) => {
|
||||
mergedParts[index] = part.replace(/\\/g, "/");
|
||||
});
|
||||
|
||||
if (buffer.length > 0) {
|
||||
mergedParts.push(...buffer);
|
||||
}
|
||||
|
||||
let currentNode = root;
|
||||
|
||||
mergedParts.forEach((part) => {
|
||||
// 查找或创建当前部分的子节点
|
||||
let node = currentNode.children?.find((child) => child.label === part);
|
||||
if (!node) {
|
||||
node = { label: part, children: [] };
|
||||
currentNode.children?.push(node);
|
||||
}
|
||||
currentNode = node;
|
||||
});
|
||||
|
||||
// 添加文件节点
|
||||
currentNode.children?.push({
|
||||
label: item.fileName,
|
||||
content: item?.content,
|
||||
});
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归查找第一个叶子节点
|
||||
* @param node - 树形节点
|
||||
* @returns 第一个叶子节点
|
||||
*/
|
||||
function findFirstLeafNode(node: TreeNode): TreeNode | null {
|
||||
if (!node.children || node.children.length === 0) {
|
||||
return node;
|
||||
}
|
||||
for (const child of node.children) {
|
||||
const leafNode = findFirstLeafNode(child);
|
||||
if (leafNode) {
|
||||
return leafNode;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** 文件树节点 Click */
|
||||
function handleFileTreeNodeClick(data: TreeNode) {
|
||||
if (!data.children || data.children.length === 0) {
|
||||
code.value = data.content || "";
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取文件树节点图标 */
|
||||
function getFileTreeNodeIcon(label: string) {
|
||||
if (label.endsWith(".java")) {
|
||||
return "java";
|
||||
}
|
||||
if (label.endsWith(".html")) {
|
||||
return "html";
|
||||
}
|
||||
if (label.endsWith(".vue")) {
|
||||
return "vue";
|
||||
}
|
||||
if (label.endsWith(".ts")) {
|
||||
return "typescript";
|
||||
}
|
||||
if (label.endsWith(".xml")) {
|
||||
return "xml";
|
||||
}
|
||||
return "file";
|
||||
}
|
||||
|
||||
/** 一键复制 */
|
||||
const handleCopyCode = () => {
|
||||
if (code.value) {
|
||||
copy(code.value);
|
||||
}
|
||||
};
|
||||
|
||||
/** 组件挂载后执行 */
|
||||
onMounted(() => {
|
||||
handleQuery();
|
||||
cmRef.value?.destroy();
|
||||
});
|
||||
</script>
|
||||
@@ -28,6 +28,6 @@
|
||||
"types": ["node", "vite/client", "element-plus/global"]
|
||||
},
|
||||
|
||||
"include": ["mock/**/*.ts", "src/**/*.ts", "src/**/*.vue", "vite.config.ts"],
|
||||
"include": ["mock/**/*.ts", "src/**/*.ts", "src/**/*.vue", "vite.config.ts", "eslint.config.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import { type ConfigEnv, loadEnv, defineConfig } from "vite";
|
||||
import { type ConfigEnv, type UserConfig, loadEnv, defineConfig, PluginOption } from "vite";
|
||||
|
||||
import AutoImport from "unplugin-auto-import/vite";
|
||||
import Components from "unplugin-vue-components/vite";
|
||||
@@ -47,7 +47,7 @@ export default defineConfig(({ mode }: ConfigEnv) => {
|
||||
target: env.VITE_API_BASE_URL, // 代理目标地址:https://后端地址
|
||||
secure: false, // 请求是否https
|
||||
changeOrigin: true, // 是否跨域
|
||||
rewrite: (path) => path.replace(new RegExp("^" + env.VITE_APP_BASE_API), ""),
|
||||
rewrite: (path: string) => path.replace(new RegExp("^" + env.VITE_APP_BASE_API), ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user