Jelajahi Sumber

调整依赖,调整目录,优化细节

神仙都没用 1 tahun lalu
induk
melakukan
d380613ba1
38 mengubah file dengan 720 tambahan dan 593 penghapusan
  1. 3 1
      .eslintignore
  2. 12 21
      .eslintrc.js
  3. 2 1
      env.d.ts
  4. 51 53
      nginx.conf
  5. 20 20
      package.json
  6. 8 2
      packages/vite-plugin/dist/index.js
  7. 1 1
      packages/vite-plugin/package.json
  8. 9 2
      packages/vite-plugin/src/eps/index.ts
  9. 307 229
      pnpm-lock.yaml
  10. 60 56
      src/cool/bootstrap/module.ts
  11. 0 4
      src/cool/utils/index.ts
  12. 4 1
      src/cool/utils/loading.ts
  13. 8 3
      src/modules/base/components/code/json.vue
  14. 2 11
      src/modules/base/config.ts
  15. 3 6
      src/modules/base/pages/main/components/bmenu.tsx
  16. 1 1
      src/modules/base/pages/main/components/process.vue
  17. 0 1
      src/modules/base/static/css/index.scss
  18. 3 2
      src/modules/base/views/menu/index.vue
  19. 2 2
      src/modules/helper/views/ai-code.vue
  20. 1 1
      src/modules/helper/views/plugins/serve.vue
  21. 1 1
      src/modules/helper/views/plugins/vue.vue
  22. 2 2
      src/modules/user/components/select.vue
  23. 1 1
      src/plugins/crud/components/select/index.tsx
  24. 1 0
      src/plugins/crud/config.ts
  25. 16 0
      src/plugins/echarts/config.ts
  26. 3 1
      src/plugins/editor-monaco/utils/format.ts
  27. 17 0
      src/plugins/element-ui/config.ts
  28. 6 0
      src/plugins/element-ui/css/index.scss
  29. 2 1
      src/plugins/excel/components/import-btn.vue
  30. 0 0
      src/plugins/theme/components/theme.vue
  31. 6 1
      src/plugins/theme/config.ts
  32. 0 0
      src/plugins/theme/static/css/index.scss
  33. 0 0
      src/plugins/theme/types/index.d.ts
  34. 0 0
      src/plugins/theme/utils/index.ts
  35. 1 1
      src/plugins/upload/components/upload-item/index.vue
  36. 140 152
      src/plugins/upload/hooks/index.ts
  37. 14 2
      src/plugins/upload/types/index.d.ts
  38. 13 13
      vite.config.mts

+ 3 - 1
.eslintignore

@@ -1 +1,3 @@
-vite.config.ts
+packages/
+dist/
+node_modules/

+ 12 - 21
.eslintrc.js

@@ -1,27 +1,17 @@
+/* eslint-env node */
+require("@rushstack/eslint-patch/modern-module-resolution");
+
 module.exports = {
 	root: true,
-	env: {
-		browser: true,
-		node: true,
-		es6: true
-	},
-	parser: "vue-eslint-parser",
-	parserOptions: {
-		parser: "@typescript-eslint/parser",
-		ecmaVersion: 2020,
-		sourceType: "module",
-		jsxPragma: "React",
-		ecmaFeatures: {
-			jsx: true,
-			tsx: true
-		}
-	},
 	extends: [
-		"plugin:vue/vue3-recommended",
-		"plugin:@typescript-eslint/recommended",
-		"prettier",
-		"plugin:prettier/recommended"
+		"plugin:vue/vue3-essential",
+		"eslint:recommended",
+		"@vue/eslint-config-typescript",
+		"@vue/eslint-config-prettier/skip-formatting"
 	],
+	parserOptions: {
+		ecmaVersion: "latest"
+	},
 	rules: {
 		"@typescript-eslint/ban-ts-ignore": "off",
 		"@typescript-eslint/explicit-function-return-type": "off",
@@ -51,6 +41,7 @@ module.exports = {
 		"vue/attribute-hyphenation": "off",
 		"vue/html-self-closing": "off",
 		"vue/require-default-prop": "off",
-		"vue/v-on-event-hyphenation": "off"
+		"vue/v-on-event-hyphenation": "off",
+		"no-self-assign": "off"
 	}
 };

+ 2 - 1
src/env.d.ts → env.d.ts

@@ -1,5 +1,6 @@
 /// <reference types="@cool-vue/crud/index.d.ts" />
-/// <reference types="../build/cool/eps.d.ts" />
+/// <reference types="./build/cool/eps.d.ts" />
+/// <reference types="vite/client" />
 
 interface ImportMetaEnv {
 	readonly VITE_NAME: string;

+ 51 - 53
nginx.conf

@@ -1,74 +1,72 @@
-user  nginx;
-worker_processes  1;
-error_log  /var/log/nginx/error.log warn;
-pid        /var/run/nginx.pid;
+user nginx;
+worker_processes 1;
+error_log /var/log/nginx/error.log warn;
+pid /var/run/nginx.pid;
 events {
-  worker_connections  1024;
+  worker_connections 1024;
 }
 http {
-  include       /etc/nginx/mime.types;
-  default_type  application/octet-stream;
-  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
-                    '$status $body_bytes_sent "$http_referer" '
-                    '"$http_user_agent" "$http_x_forwarded_for"';
-  access_log  /var/log/nginx/access.log  main;
-  sendfile        on;
-  keepalive_timeout  65;
+  include /etc/nginx/mime.types;
+  default_type application/octet-stream;
+  log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+  '$status $body_bytes_sent "$http_referer" '
+  '"$http_user_agent" "$http_x_forwarded_for"';
+  access_log /var/log/nginx/access.log main;
+  sendfile on;
+  keepalive_timeout 65;
   upstream cool {
-      server midway:8001;
+    server midway:8001;
   }
 
   server {
-    listen       80;
-    server_name  localhost;
+    listen 80;
+    server_name localhost;
     location / {
-      root   /app;
-      index  index.html;
+      root /app;
+      index index.html;
       try_files $uri $uri/ /index.html;
     }
-    location /api/ 
-    {
-        proxy_pass http://cool/;
-        proxy_set_header Host $host;
-        proxy_set_header X-Real-IP $remote_addr;
-        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
-        proxy_set_header REMOTE-HOST $remote_addr;
+    location /api/ {
+      proxy_pass http://cool/;
+      proxy_set_header Host $host;
+      proxy_set_header X-Real-IP $remote_addr;
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+      proxy_set_header REMOTE-HOST $remote_addr;
 
-        #缓存相关配置
-        #proxy_cache cache_one;
-        #proxy_cache_key $host$request_uri$is_args$args;
-        #proxy_cache_valid 200 304 301 302 1h;
+      #缓存相关配置
+      #proxy_cache cache_one;
+      #proxy_cache_key $host$request_uri$is_args$args;
+      #proxy_cache_valid 200 304 301 302 1h;
 
-        #持久化连接相关配置
-        proxy_connect_timeout 3000s;
-        proxy_read_timeout 86400s;
-        proxy_send_timeout 3000s;
-        #proxy_http_version 1.1;
-        #proxy_set_header Upgrade $http_upgrade;
-        #proxy_set_header Connection "upgrade";
+      #持久化连接相关配置
+      proxy_connect_timeout 3000s;
+      proxy_read_timeout 86400s;
+      proxy_send_timeout 3000s;
+      #proxy_http_version 1.1;
+      #proxy_set_header Upgrade $http_upgrade;
+      #proxy_set_header Connection "upgrade";
 
-        add_header X-Cache $upstream_cache_status;
+      add_header X-Cache $upstream_cache_status;
 
-        #expires 12h;
+      #expires 12h;
     }
 
     # socket需额外配置
     location /socket {
-        proxy_pass http://cool/socket;
-        proxy_connect_timeout 3600s; #配置点1
-        proxy_read_timeout 3600s; #配置点2,如果没效,可以考虑这个时间配置长一点
-        proxy_send_timeout 3600s; #配置点3
-        proxy_set_header Host $host;
-        proxy_set_header X-Real-IP $remote_addr;
-        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
-        proxy_set_header REMOTE-HOST $remote_addr;
-        #proxy_bind $remote_addr transparent;
-        proxy_http_version 1.1;
-        proxy_set_header Upgrade $http_upgrade;
-        proxy_set_header Connection "upgrade";
-        rewrite /socket/(.*) /$1 break;
-        proxy_redirect off;
-
+      proxy_pass http://cool/socket;
+      proxy_connect_timeout 3600s; #配置点1
+      proxy_read_timeout 3600s; #配置点2,如果没效,可以考虑这个时间配置长一点
+      proxy_send_timeout 3600s; #配置点3
+      proxy_set_header Host $host;
+      proxy_set_header X-Real-IP $remote_addr;
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+      proxy_set_header REMOTE-HOST $remote_addr;
+      #proxy_bind $remote_addr transparent;
+      proxy_http_version 1.1;
+      proxy_set_header Upgrade $http_upgrade;
+      proxy_set_header Connection "upgrade";
+      rewrite /socket/(.*) /$1 break;
+      proxy_redirect off;
     }
   }
 }

+ 20 - 20
package.json

@@ -1,12 +1,12 @@
 {
 	"name": "cool-admin",
-	"version": "7.1.1",
+	"version": "7.1.2",
 	"scripts": {
 		"dev": "vite --host",
 		"build": "vite build",
-		"serve": "vite preview",
-		"lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
-		"lint:eslint": "eslint \"./src/**/*.{vue,ts,tsx}\" --fix"
+		"preview": "vite preview",
+		"format": "prettier --write src/",
+		"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .eslintignore"
 	},
 	"dependencies": {
 		"@cool-vue/crud": "^7.1.26",
@@ -14,12 +14,12 @@
 		"@vueuse/core": "^10.4.0",
 		"@wangeditor/editor": "^5.1.23",
 		"@wangeditor/editor-for-vue": "^5.1.12",
-		"axios": "^1.6.7",
+		"axios": "^1.7.2",
 		"chardet": "^2.0.0",
 		"core-js": "^3.32.1",
 		"dayjs": "^1.11.10",
 		"echarts": "^5.4.3",
-		"element-plus": "^2.7.3",
+		"element-plus": "^2.7.7",
 		"file-saver": "^2.0.5",
 		"lodash-es": "^4.17.21",
 		"marked": "^11.1.1",
@@ -32,33 +32,33 @@
 		"store": "^2.0.12",
 		"vue": "^3.4.15",
 		"vue-echarts": "^6.6.1",
-		"vue-router": "^4.3.2",
+		"vue-router": "^4.4.0",
 		"vuedraggable": "^4.1.0",
 		"xlsx": "^0.18.5"
 	},
 	"devDependencies": {
-		"@cool-vue/vite-plugin": "^7.1.4",
+		"@rushstack/eslint-patch": "^1.8.0",
+		"@cool-vue/vite-plugin": "^7.1.5",
 		"@types/file-saver": "^2.0.7",
 		"@types/lodash-es": "^4.17.8",
 		"@types/mockjs": "^1.0.7",
-		"@types/node": "^20.5.6",
+		"@types/node": "^20.14.5",
 		"@types/nprogress": "^0.2.0",
 		"@types/store": "^2.0.2",
-		"@typescript-eslint/eslint-plugin": "^6.20.0",
-		"@typescript-eslint/parser": "^6.4.1",
 		"@vitejs/plugin-vue": "^5.0.3",
 		"@vitejs/plugin-vue-jsx": "^3.1.0",
 		"@vue/compiler-sfc": "^3.4.15",
-		"eslint": "^8.48.0",
-		"eslint-config-prettier": "^9.0.0",
-		"eslint-plugin-prettier": "^5.0.0",
-		"eslint-plugin-vue": "^9.17.0",
-		"prettier": "^3.1.0",
+		"@vue/eslint-config-prettier": "^9.0.0",
+		"@vue/eslint-config-typescript": "^13.0.0",
+		"eslint": "^8.57.0",
+		"eslint-plugin-vue": "^9.23.0",
+		"prettier": "^3.3.3",
 		"rollup-plugin-visualizer": "^5.9.2",
-		"sass": "^1.66.1",
+		"sass": "^1.53.0",
 		"terser": "^5.27.0",
-		"typescript": "^5.2.2",
-		"vite": "^5.0.12",
-		"vite-plugin-compression": "^0.5.1"
+		"typescript": "^5.4.0",
+		"vite": "^5.3.4",
+		"vite-plugin-compression": "^0.5.1",
+		"vite-plugin-vue-devtools": "^7.3.1"
 	}
 }

+ 8 - 2
packages/vite-plugin/dist/index.js

@@ -245,6 +245,7 @@
         // 创建 Entity
         function createEntity() {
             const t0 = [];
+            const arr = [];
             for (const item of list) {
                 if (!item.name)
                     continue;
@@ -266,7 +267,10 @@
                 t.push(" */\n");
                 t.push(`[key: string]: any;`);
                 t.push("}");
-                t0.push(t);
+                if (!arr.includes(item.name)) {
+                    arr.push(item.name);
+                    t0.push(t);
+                }
             }
             return t0.map((e) => e.join("")).join("\n\n");
         }
@@ -364,7 +368,9 @@
                                         t.push(` * ${a.summary || n}\n`);
                                         t.push(" */\n");
                                         t.push(`${n}(data${q.length == 1 ? "?" : ""}: ${q.join("")}): Promise<${res}>;`);
-                                        permission.push(n);
+                                        if (!permission.includes(n)) {
+                                            permission.push(n);
+                                        }
                                     }
                                 });
                                 // 权限标识

+ 1 - 1
packages/vite-plugin/package.json

@@ -1,6 +1,6 @@
 {
 	"name": "@cool-vue/vite-plugin",
-	"version": "7.1.4",
+	"version": "7.1.5",
 	"description": "cool-admin/cool-uni builder",
 	"main": "/dist/index.js",
 	"scripts": {

+ 9 - 2
packages/vite-plugin/src/eps/index.ts

@@ -164,6 +164,7 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
 	// 创建 Entity
 	function createEntity() {
 		const t0: string[][] = [];
+		const arr: string[] = [];
 
 		for (const item of list) {
 			if (!item.name) continue;
@@ -187,7 +188,11 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
 			t.push(" */\n");
 			t.push(`[key: string]: any;`);
 			t.push("}");
-			t0.push(t);
+
+			if (!arr.includes(item.name)) {
+				arr.push(item.name);
+				t0.push(t);
+			}
 		}
 
 		return t0.map((e) => e.join("")).join("\n\n");
@@ -316,7 +321,9 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
 										)}): Promise<${res}>;`,
 									);
 
-									permission.push(n);
+									if (!permission.includes(n)) {
+										permission.push(n);
+									}
 								}
 							});
 

File diff ditekan karena terlalu besar
+ 307 - 229
pnpm-lock.yaml


+ 60 - 56
src/cool/bootstrap/module.ts

@@ -1,16 +1,14 @@
-import { App } from "vue";
-import { isFunction, orderBy, chain } from "lodash-es";
+import { type App, type Directive } from "vue";
+import { assign, chain, isFunction } from "lodash-es";
 import { filename } from "../utils";
 import { module } from "../module";
 import { hmr } from "../hooks";
 
 // 扫描文件
-const files: any = import.meta.glob(
-	"/src/{modules,plugins}/*/{config.ts,service/**,directives/**}",
-	{
-		eager: true
-	}
-);
+const files = import.meta.glob("/src/{modules,plugins}/*/{config.ts,service/**,directives/**}", {
+	eager: true,
+	import: "default"
+});
 
 // 模块列表
 module.list = hmr.getData("modules", []);
@@ -21,10 +19,10 @@ for (const i in files) {
 	const [, , type, name, action] = i.split("/");
 
 	// 文件名
-	const fname = filename(i);
+	const n = filename(i);
 
 	// 文件内容
-	const v = files[i]?.default;
+	const v = files[i];
 
 	// 模块是否存在
 	const m = module.get(name);
@@ -38,28 +36,24 @@ for (const i in files) {
 		directives: []
 	};
 
-	switch (action) {
-		// 配置参数
-		case "config.ts":
-			d.value = v;
-			break;
-
-		// 请求服务
-		case "service":
-			const s = new v();
-
-			if (s) {
-				d.services?.push({
-					path: s.namespace,
-					value: s
-				});
-			}
-			break;
-
-		// 指令
-		case "directives":
-			d.directives?.push({ name: fname, value: v });
-			break;
+	// 配置
+	if (action == "config.ts") {
+		d.value = v;
+	}
+	// 服务
+	else if (action == "service") {
+		const s = new (v as any)();
+
+		if (s) {
+			d.services?.push({
+				path: s.namespace,
+				value: s
+			});
+		}
+	}
+	// 指令
+	else if (action == "directives") {
+		d.directives?.push({ name: n, value: v as Directive });
 	}
 
 	if (!m) {
@@ -69,34 +63,44 @@ for (const i in files) {
 
 // 创建
 export function createModule(app: App) {
-	// 模块加载
-	const list = orderBy(module.list, "order").map((e) => {
-		const d = isFunction(e.value) ? e.value(app) : e.value;
+	const list = chain(module.list)
+		.map((e) => {
+			const d = isFunction(e.value) ? e.value(app) : e.value;
 
-		if (d) {
-			Object.assign(e, d);
-		}
-
-		// 安装事件
-		e.install?.(app, d.options);
-
-		// 注册组件
-		e.components?.forEach(async (c: any) => {
-			const v = await (isFunction(c) ? c() : c);
-			const n = v.default || v;
+			if (d) {
+				assign(e, d);
+			}
 
-			if (n.name) {
-				app.component(n.name, n);
+			if (!d.order) {
+				e.order = 0;
 			}
-		});
 
-		// 注册指令
-		e.directives?.forEach((v: any) => {
-			app.directive(v.name, v.value);
-		});
+			return e;
+		})
+		.orderBy("order", "desc")
+		.map((e) => {
+			// 初始化
+			e.install?.(app, e.options);
+
+			// 注册组件
+			e.components?.forEach(async (c) => {
+				// @ts-ignore
+				const v = await (isFunction(c) ? c() : c);
+				const n = v.default || v;
+
+				if (n.name) {
+					app.component(n.name, n);
+				}
+			});
+
+			// 注册指令
+			e.directives?.forEach((v) => {
+				app.directive(v.name, v.value);
+			});
 
-		return e;
-	});
+			return e;
+		})
+		.value();
 
 	return {
 		// 模块列表
@@ -107,7 +111,7 @@ export function createModule(app: App) {
 
 			for (let i = 0; i < list.length; i++) {
 				if (list[i].onLoad) {
-					Object.assign(events, await list[i]?.onLoad?.(events));
+					assign(events, await list[i]?.onLoad?.(events));
 				}
 			}
 		}

+ 0 - 4
src/cool/utils/index.ts

@@ -140,9 +140,6 @@ export function getBrowser() {
 	// 是否 ios
 	const isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
 
-	// 浏览器版本
-	const version = (ua.match(/[\s\S]+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1];
-
 	// 是否 PC 端
 	const isPC = tag === "pc";
 
@@ -155,7 +152,6 @@ export function getBrowser() {
 	return {
 		height: clientHeight,
 		width: clientWidth,
-		version,
 		type,
 		plat,
 		tag,

+ 4 - 1
src/cool/utils/loading.ts

@@ -5,7 +5,10 @@ export const Loading = {
 	async set(list: Promise<any>[]) {
 		try {
 			await Promise.all(list);
-		} catch (e) {}
+		} catch (e) {
+			console.error("[Loading] Error: ", e);
+		}
+
 		if (this.resolve) {
 			this.resolve();
 		}

+ 8 - 3
src/modules/base/components/code/json.vue

@@ -1,6 +1,11 @@
 <template v-if="text">
 	<div class="cl-code-json__wrap" v-if="popover">
-		<el-popover width="auto" placement="right" popper-class="cl-code-json__popper">
+		<el-popover
+			width="auto"
+			placement="right"
+			popper-class="cl-code-json__popper"
+			effect="dark"
+		>
 			<template #reference>
 				<span class="text">{{ text }}</span>
 			</template>
@@ -87,10 +92,10 @@ const viewer = defineComponent({
 
 <style lang="scss">
 .cl-code-json {
-	background-color: var(--el-fill-color-lighter);
 	border-radius: 6px;
 	position: relative;
 	min-width: 200px;
+	max-width: 500px;
 
 	.op {
 		position: absolute;
@@ -123,7 +128,7 @@ const viewer = defineComponent({
 	}
 
 	&__popper {
-		padding: 5px !important;
+		padding: 0 !important;
 	}
 }
 </style>

+ 2 - 11
src/modules/base/config.ts

@@ -1,9 +1,6 @@
-import VueECharts from "vue-echarts";
-import ElementPlus from "element-plus";
+import type { ModuleConfig } from "/@/cool";
 import { useStore } from "./store";
 import { config } from "/@/config";
-import type { ModuleConfig } from "/@/cool";
-import "element-plus/theme-chalk/src/index.scss";
 import "./static/css/index.scss";
 
 export default (): ModuleConfig => {
@@ -60,13 +57,7 @@ export default (): ModuleConfig => {
 				component: () => import("./pages/error/502.vue")
 			}
 		],
-		install(app) {
-			// element-plus
-			app.use(ElementPlus);
-
-			// charts
-			app.component("v-chart", VueECharts);
-
+		install() {
 			// 设置标题
 			document.title = config.app.name;
 		},

+ 3 - 6
src/modules/base/pages/main/components/bmenu.tsx

@@ -1,4 +1,4 @@
-import { defineComponent, h } from "vue";
+import { defineComponent, h, VNode } from "vue";
 import { useBase, Menu } from "/$/base";
 import { useCool } from "/@/cool";
 
@@ -27,8 +27,6 @@ export default defineComponent({
 				return list
 					.filter((e) => e.isShow)
 					.map((e) => {
-						let html = null;
-
 						const item = (e: Menu.Item) => {
 							return (
 								<div class="wrap">
@@ -39,7 +37,7 @@ export default defineComponent({
 						};
 
 						if (e.type == 0) {
-							html = h(
+							return h(
 								<el-sub-menu />,
 								{
 									index: String(e.id),
@@ -56,7 +54,7 @@ export default defineComponent({
 								}
 							);
 						} else {
-							html = h(
+							return h(
 								<el-menu-item />,
 								{
 									index:
@@ -75,7 +73,6 @@ export default defineComponent({
 							);
 						}
 
-						return html;
 					});
 			}
 

+ 1 - 1
src/modules/base/pages/main/components/process.vue

@@ -144,7 +144,7 @@ watch(
 
 onMounted(() => {
 	// 添加滚轮事件监听器
-	refs.scroller.wrapRef.addEventListener("wheel", function (event: WheelEvent) {
+	refs.scroller.wrapRef?.addEventListener("wheel", function (event: WheelEvent) {
 		// 阻止默认滚动行为
 		event.preventDefault();
 

+ 0 - 1
src/modules/base/static/css/index.scss

@@ -23,5 +23,4 @@ input {
 	}
 }
 
-@import "./theme.scss";
 @import "./animation.scss";

+ 3 - 2
src/modules/base/views/menu/index.vue

@@ -71,8 +71,9 @@
 							and: [service.base.sys.menu.permission.add, scope.row.type != 2]
 						}"
 						@click="append(scope.row)"
-						>新增</el-button
 					>
+						新增
+					</el-button>
 				</template>
 			</cl-table>
 		</cl-row>
@@ -209,7 +210,7 @@ const Table = useTable({
 			prop: "updateTime",
 			label: "更新时间",
 			sortable: "custom",
-			width: 160
+			width: 170
 		},
 		{
 			label: "操作",

+ 2 - 2
src/modules/helper/views/ai-code.vue

@@ -899,7 +899,7 @@ const desc = reactive({
 			const val = desc.list[n];
 
 			if (val) {
-				function next2(n2: number) {
+				const next2 = (n2: number) => {
 					const v = val[n2];
 
 					if (v) {
@@ -921,7 +921,7 @@ const desc = reactive({
 							}
 						}, 1500);
 					}
-				}
+				};
 
 				next2(0);
 			} else {

+ 1 - 1
src/modules/helper/views/plugins/serve.vue

@@ -127,7 +127,7 @@ const tab = reactive({
 		if (val == "shop") {
 			nextTick(() => {
 				tab.active = "installed";
-				window.open("https://cool-js.com/");
+				window.open("https://cool-js.com/plugin");
 			});
 		}
 	}

+ 1 - 1
src/modules/helper/views/plugins/vue.vue

@@ -88,7 +88,7 @@ const tab = reactive({
 		if (val == "shop") {
 			nextTick(() => {
 				tab.active = "installed";
-				window.open("https://cool-js.com/");
+				window.open("https://cool-js.com/plugin");
 			});
 		}
 	}

+ 2 - 2
src/modules/user/components/select.vue

@@ -152,12 +152,12 @@ const Table = useTable({
 					type: "selection",
 					width: 60,
 					reserveSelection: true
-			  }
+				}
 			: {
 					label: "操作",
 					prop: "check",
 					width: 100
-			  },
+				},
 		{
 			prop: "avatarUrl",
 			label: "头像",

+ 1 - 1
src/plugins/crud/components/select/index.tsx

@@ -52,7 +52,7 @@ export default defineComponent({
 				const ids: any[] = [];
 
 				// 获取所有的值
-				function deep(arr: Dict.Item[], f: boolean) {
+				const deep = (arr: Dict.Item[], f: boolean) => {
 					arr.forEach((e) => {
 						const f2 = e[props.valueKey] == val;
 

+ 1 - 0
src/plugins/crud/config.ts

@@ -10,6 +10,7 @@ import "@cool-vue/crud/dist/index.css";
 
 export default (): Merge<ModuleConfig, CrudOptions> => {
 	return {
+		order: 100,
 		label: "CRUD",
 		description: "快速增删改查及一系列辅助组件",
 		author: "COOL",

+ 16 - 0
src/plugins/echarts/config.ts

@@ -0,0 +1,16 @@
+import type { ModuleConfig } from "/@/cool";
+import VueECharts from "vue-echarts";
+
+export default (): ModuleConfig => {
+	return {
+		order: 100,
+		label: "ECharts 图表",
+		description: "echarts、vue-echarts 配置",
+		author: "COOL",
+		version: "1.0.0",
+		updateTime: "2024-07-22",
+		install(app) {
+			app.component("v-chart", VueECharts);
+		}
+	};
+};

+ 3 - 1
src/plugins/editor-monaco/utils/format.ts

@@ -44,7 +44,9 @@ export function useFormat() {
 							singleQuote: true,
 							trailingComma: "none"
 						});
-					} catch (err) {}
+					} catch (err) {
+						// ...
+					}
 
 					return [
 						{

+ 17 - 0
src/plugins/element-ui/config.ts

@@ -0,0 +1,17 @@
+import type { ModuleConfig } from "/@/cool";
+import ElementPlus from "element-plus";
+import "./css/index.scss";
+
+export default (): ModuleConfig => {
+	return {
+		order: 100,
+		label: "Element Ui",
+		description: "Element Plus 变量、样式配置",
+		author: "COOL",
+		version: "1.0.0",
+		updateTime: "2024-07-22",
+		install(app) {
+			app.use(ElementPlus);
+		}
+	};
+};

+ 6 - 0
src/modules/base/static/css/theme.scss → src/plugins/element-ui/css/index.scss

@@ -1,3 +1,9 @@
+@forward "element-plus/theme-chalk/src/common/var.scss" with (
+	$scrollbar: ()
+);
+
+@use "element-plus/theme-chalk/src/index.scss" as *;
+
 // Element-plus
 .el-input-number {
 	&__decrease,

+ 2 - 1
src/plugins/excel/components/import-btn.vue

@@ -122,6 +122,7 @@ import { reactive, type PropType, computed } from "vue";
 import * as XLSX from "xlsx";
 import chardet from "chardet";
 import { extname } from "/@/cool/utils";
+import { has } from "lodash-es";
 
 const props = defineProps({
 	onConfig: Function,
@@ -286,7 +287,7 @@ function onUpload(raw: File, _: any, { next }: any) {
 
 		let json: any[] = [];
 		for (const sheet in workbook.Sheets) {
-			if (workbook.Sheets.hasOwnProperty(sheet)) {
+			if (has(workbook.Sheets, sheet)) {
 				json = json.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]));
 			}
 		}

+ 0 - 0
src/modules/theme/components/theme.vue → src/plugins/theme/components/theme.vue


+ 6 - 1
src/modules/theme/config.ts → src/plugins/theme/config.ts

@@ -1,12 +1,17 @@
 import { setTheme } from "./utils";
 import { config } from "/@/config";
 import { storage, type ModuleConfig } from "/@/cool";
-
 import "element-plus/theme-chalk/dark/css-vars.css";
 import "./static/css/index.scss";
 
 export default (): ModuleConfig => {
 	return {
+		label: "主题",
+		description: "自定义主色、菜单分组、暗黑模式",
+		author: "COOL",
+		version: "1.0.0",
+		updateTime: "2024-07-22",
+
 		toolbar: {
 			component: import("./components/theme.vue")
 		},

+ 0 - 0
src/modules/theme/static/css/index.scss → src/plugins/theme/static/css/index.scss


+ 0 - 0
src/modules/theme/types/index.d.ts → src/plugins/theme/types/index.d.ts


+ 0 - 0
src/modules/theme/utils/index.ts → src/plugins/theme/utils/index.ts


+ 1 - 1
src/plugins/upload/components/upload-item/index.vue

@@ -49,7 +49,7 @@
 				<div
 					class="cl-upload-item__progress"
 					:class="{
-						'is-show': item.progress >= 0 && item.progress < 100,
+						'is-show': item.progress! >= 0 && item.progress! < 100,
 						'is-hide': item.progress == 100
 					}"
 				>

+ 140 - 152
src/plugins/upload/hooks/index.ts

@@ -12,168 +12,156 @@ export function useUpload() {
 	const { user } = useBase();
 
 	// 上传
-	async function toUpload(
-		file: File,
-		opts: Upload.Options = {}
-	): Promise<{
-		key: string;
-		url: string;
-		fileId: string;
-	}> {
-		return new Promise(async (resolve, reject) => {
-			// 合并配置
-			const { prefixPath, onProgress } = merge(options, opts);
-
-			// 文件id
-			const fileId = uuid("");
-
-			try {
-				// 上传模式、类型
-				const { mode, type } = await service.base.comm.uploadMode();
-
-				// 本地上传
-				const isLocal = mode == "local";
-
-				// 文件名
-				const fileName = fileId + "_" + file.name;
-
-				// Key
-				let key = isLocal ? fileName : pathJoin(prefixPath!, fileName);
-
-				// 多种上传请求
-				// 上传到云端
-				async function next({
-					host,
-					preview,
-					data
-				}: {
-					host: string;
-					preview?: string;
-					data?: any;
-				}) {
-					const fd = new FormData();
-
-					// key
-					fd.append("key", key);
-
-					// 签名数据
-					for (const i in data) {
-						if (!fd.has(i)) {
-							fd.append(i, data[i]);
-						}
-					}
+	async function toUpload(file: File, opts: Upload.Options = {}): Upload.Respose {
+		return new Promise((resolve, reject) => {
+			const executor = async () => {
+				// 合并配置
+				const { prefixPath, onProgress } = merge(options, opts);
 
-					// 文件
-					fd.append("file", file);
-
-					// 上传进度
-					let progress = 0;
-
-					// 上传
-					await service
-						.request({
-							url: host,
-							method: "POST",
-							headers: {
-								"Content-Type": "multipart/form-data",
-								Authorization: isLocal ? user.token : null
-							},
-							timeout: 600000,
-							data: fd,
-							onUploadProgress(e: AxiosProgressEvent) {
-								progress = e.total ? Math.floor((e.loaded / e.total) * 100) : 0;
-								onProgress?.(progress);
-							},
-							proxy: isLocal,
-							NProgress: false
-						})
-						.then((res) => {
-							if (progress != 100) {
-								onProgress?.(100);
-							}
+				// 文件id
+				const fileId = uuid("");
+
+				try {
+					// 上传模式、类型
+					const { mode, type } = await service.base.comm.uploadMode();
 
-							key = encodeURIComponent(key);
+					// 本地上传
+					const isLocal = mode == "local";
 
-							let url = "";
+					// 文件名
+					const fileName = fileId + "_" + file.name;
 
-							if (isLocal) {
-								url = res;
-							} else {
-								url = pathJoin(preview || host, key);
+					// Key
+					let key = isLocal ? fileName : pathJoin(prefixPath!, fileName);
+
+					// 多种上传请求
+					const next = async ({ host, preview, data }: Upload.Request) => {
+						const fd = new FormData();
+
+						// key
+						fd.append("key", key);
+
+						// 签名数据
+						for (const i in data) {
+							if (!fd.has(i)) {
+								fd.append(i, data[i]);
 							}
+						}
 
-							resolve({
-								key,
-								url,
-								fileId
+						// 文件
+						fd.append("file", file);
+
+						// 上传进度
+						let progress = 0;
+
+						// 上传
+						await service
+							.request({
+								url: host,
+								method: "POST",
+								headers: {
+									"Content-Type": "multipart/form-data",
+									Authorization: isLocal ? user.token : null
+								},
+								timeout: 600000,
+								data: fd,
+								onUploadProgress(e: AxiosProgressEvent) {
+									progress = e.total ? Math.floor((e.loaded / e.total) * 100) : 0;
+									onProgress?.(progress);
+								},
+								proxy: isLocal,
+								NProgress: false
+							})
+							.then((res) => {
+								if (progress != 100) {
+									onProgress?.(100);
+								}
+
+								key = encodeURIComponent(key);
+
+								let url = "";
+
+								if (isLocal) {
+									url = res;
+								} else {
+									url = pathJoin(preview || host, key);
+								}
+
+								resolve({
+									key,
+									url,
+									fileId
+								});
+							})
+							.catch((err) => {
+								ElMessage.error(err.message);
+								reject(err);
 							});
-						})
-						.catch((err) => {
-							ElMessage.error(err.message);
-							reject(err);
-						});
-				}
+					};
 
-				if (isLocal) {
-					next({
-						host: "/admin/base/comm/upload"
-					});
-				} else {
-					service.base.comm
-						.upload(
-							type == "aws"
-								? {
-										key
-								  }
-								: {}
-						)
-						.then((res) => {
-							switch (type) {
-								// 腾讯
-								case "cos":
-									next({
-										host: res.url,
-										data: res.credentials
-									});
-									break;
-								// 阿里
-								case "oss":
-									next({
-										host: res.host,
-										preview: res.publicDomain,
-										data: {
-											OSSAccessKeyId: res.OSSAccessKeyId,
-											policy: res.policy,
-											signature: res.signature
-										}
-									});
-									break;
-								// 七牛
-								case "qiniu":
-									next({
-										host: res.uploadUrl,
-										preview: res.publicDomain,
-										data: {
-											token: res.token
+					if (isLocal) {
+						next({
+							host: "/admin/base/comm/upload"
+						});
+					} else {
+						service.base.comm
+							.upload(
+								type == "aws"
+									? {
+											key
 										}
-									});
-									break;
-								// aws
-								case "aws":
-									next({
-										host: res.url,
-										data: res.fields
-									});
-									break;
-							}
-						})
-						.catch(reject);
+									: {}
+							)
+							.then((res) => {
+								switch (type) {
+									// 腾讯
+									case "cos":
+										next({
+											host: res.url,
+											data: res.credentials
+										});
+										break;
+									// 阿里
+									case "oss":
+										next({
+											host: res.host,
+											preview: res.publicDomain,
+											data: {
+												OSSAccessKeyId: res.OSSAccessKeyId,
+												policy: res.policy,
+												signature: res.signature
+											}
+										});
+										break;
+									// 七牛
+									case "qiniu":
+										next({
+											host: res.uploadUrl,
+											preview: res.publicDomain,
+											data: {
+												token: res.token
+											}
+										});
+										break;
+									// aws
+									case "aws":
+										next({
+											host: res.url,
+											data: res.fields
+										});
+										break;
+								}
+							})
+							.catch(reject);
+					}
+				} catch (err) {
+					ElMessage.error("文件上传失败");
+					console.error("[upload]", err);
+					reject(err);
 				}
-			} catch (err) {
-				ElMessage.error("文件上传失败");
-				console.error("[upload]", err);
-				reject(err);
-			}
+			};
+
+			executor();
 		});
 	}
 

+ 14 - 2
src/plugins/upload/types/index.d.ts

@@ -8,8 +8,8 @@ export declare namespace Upload {
 
 	interface Item {
 		url?: string;
-		uid: string;
-		progress: number;
+		uid?: string;
+		progress?: number;
 		preload?: string;
 		error?: string;
 		isPlay?: boolean;
@@ -21,4 +21,16 @@ export declare namespace Upload {
 		onProgress?(progress: number): void;
 		[key: string]: any;
 	}
+
+	type Respose = Promise<{
+		key: string;
+		url: string;
+		fileId: string;
+	}>;
+
+	interface Request {
+		host: string;
+		preview?: string;
+		data?: any;
+	}
 }

+ 13 - 13
vite.config.mts

@@ -1,27 +1,27 @@
-import path from "path";
+import { fileURLToPath, URL } from "node:url";
 import { ConfigEnv, UserConfig } from "vite";
 import vue from "@vitejs/plugin-vue";
 import vueJsx from "@vitejs/plugin-vue-jsx";
+import vueDevTools from "vite-plugin-vue-devtools";
 import compression from "vite-plugin-compression";
 import { visualizer } from "rollup-plugin-visualizer";
 import { proxy } from "./src/config/proxy";
 import { cool } from "@cool-vue/vite-plugin";
 
-function resolve(dir: string) {
-	return path.resolve(__dirname, ".", dir);
-}
-
-function isDev(mode: string | undefined): boolean {
-	return mode === "development";
+function toPath(dir: string) {
+	return fileURLToPath(new URL(dir, import.meta.url));
 }
 
 // https://vitejs.dev/config
 export default ({ mode }: ConfigEnv): UserConfig => {
+	const isDev = mode === "development";
+
 	return {
 		plugins: [
 			vue(),
 			compression(),
 			vueJsx(),
+			// vueDevTools(),
 			cool({
 				type: "admin",
 				proxy
@@ -49,14 +49,14 @@ export default ({ mode }: ConfigEnv): UserConfig => {
 		},
 		resolve: {
 			alias: {
-				"/@": resolve("src"),
-				"/$": resolve("src/modules"),
-				"/#": resolve("src/plugins"),
-				"/~": resolve("packages")
+				"/@": toPath("./src"),
+				"/$": toPath("./src/modules"),
+				"/#": toPath("./src/plugins"),
+				"/~": toPath("./packages")
 			}
 		},
 		esbuild: {
-			drop: isDev(mode) ? [] : ["console", "debugger"]
+			drop: isDev ? [] : ["console", "debugger"]
 		},
 
 		build: {
@@ -67,7 +67,7 @@ export default ({ mode }: ConfigEnv): UserConfig => {
 			// 		drop_debugger: true
 			// 	}
 			// },
-			sourcemap: isDev(mode),
+			sourcemap: isDev,
 			rollupOptions: {
 				output: {
 					chunkFileNames: "static/js/[name]-[hash].js",

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini