diff --git a/.vscode/crud.code-snippets b/.vscode/crud.code-snippets index d9a75fd..9bf91e3 100644 --- a/.vscode/crud.code-snippets +++ b/.vscode/crud.code-snippets @@ -34,8 +34,8 @@ "", "`; + + const content = prettier.format(temp, { + parser: "vue", + useTabs: true, + tabWidth: 4, + endOfLine: "lf", + semi: true, + jsxBracketSameLine: true, + singleQuote: false, + printWidth: 100, + trailingComma: "none" + }); + + // views 目录是否存在 + const dir = path.join(coolPath, `modules/${module}/views`); + if (!fs.existsSync(dir)) fs.mkdirSync(dir); + + // 创建文件 + fs.createWriteStream(path.join(dir, `${filename}.vue`), { + flags: "w" + }).write(content); +} + +export const cool = (): Plugin | null => { + return { + name: "vite-cool", + configureServer(server) { + server.middlewares.use(async (req, res, next) => { + function done(data) { + res.writeHead(200, { "Content-Type": "text/html;charset=UTF-8" }); + res.end(JSON.stringify(data)); + } + + if (req.url.includes("/__cool_createMenu")) { + try { + const body: any = await parseJson(req); + await createVue(body); + done({ + code: 1000 + }); + } catch (e) { + done({ + code: 1001, + message: e.message + }); + } + } else if (req.url.includes("/__cool_modules")) { + const dirs = fs.readdirSync(path.join(coolPath, "modules")); + done({ + code: 1000, + data: dirs.filter((e) => !e.includes(".")) + }); + } else { + next(); + } + }); + } + }; +}; diff --git a/src/core/utils/svg.ts b/build/plugins/svg.ts similarity index 100% rename from src/core/utils/svg.ts rename to build/plugins/svg.ts diff --git a/package.json b/package.json index 0325056..fa7750f 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,17 @@ { "name": "front-next", - "version": "0.8.1", + "version": "4.0.0", "scripts": { - "dev": "vite", + "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,mock}/**/*.{vue,ts,tsx}\" --fix" }, "dependencies": { + "@cool-vue/crud": "^1.0.4", "array.prototype.flat": "^1.2.4", "axios": "^0.21.1", - "cl-admin-crud-vue3": "^0.9.6", "clipboard": "^2.0.8", "clone-deep": "^4.0.1", "codemirror": "^5.62.0", @@ -22,6 +22,7 @@ "glob": "^7.1.6", "js-beautify": "^1.13.5", "merge": "^2.1.1", + "merge-deep": "^3.0.3", "mitt": "^2.1.0", "mockjs": "^1.1.0", "nprogress": "^0.2.0", @@ -50,14 +51,16 @@ "eslint-config-prettier": "^8.1.0", "eslint-plugin-prettier": "^3.3.1", "eslint-plugin-vue": "^7.13.0", + "iconv-lite": "^0.6.3", "prettier": "^2.2.1", "sass": "^1.42.1", "sass-loader": "^11.1.1", "svg-sprite-loader": "^6.0.2", "typescript": "4.4.3", "unplugin-vue-components": "0.15.4", - "vite": "^2.6.7", + "vite": "2.6.7", "vite-plugin-compression": "^0.3.5", + "vite-plugin-mock": "^2.9.6", "vite-plugin-style-import": "^1.0.1", "vite-svg-loader": "^2.1.0" } diff --git a/src/App.vue b/src/App.vue index 6e7cd9d..acb0447 100644 --- a/src/App.vue +++ b/src/App.vue @@ -2,7 +2,7 @@
-

COOL-ADMIN

+

{{ app.name }}

正在加载菜单...

初次加载资源可能需要较多时间 请耐心等待

@@ -21,7 +21,7 @@ import { computed, defineComponent } from "vue"; import { ElConfigProvider } from "element-plus"; import zhCn from "element-plus/lib/locale/lang/zh-cn"; -import { useCool } from "/@/core"; +import { useCool } from "/@/cool"; export default defineComponent({ components: { @@ -29,13 +29,14 @@ export default defineComponent({ }, setup() { - const { store } = useCool(); + const { store, app } = useCool(); const locale = zhCn; const loading = computed(() => store.getters.appLoading); return { locale, - loading + loading, + app }; } }); diff --git a/src/config/env.ts b/src/config/env.ts index acce4f0..0eb528e 100644 --- a/src/config/env.ts +++ b/src/config/env.ts @@ -1,5 +1,5 @@ import store from "store"; -import { getUrlParam } from "/@/core/utils"; +import { getUrlParam } from "/@/cool/utils"; import { MenuItem } from "/$/base/types"; // 路由模式 diff --git a/src/core/hook/core.ts b/src/cool/core/hook/index.ts similarity index 64% rename from src/core/hook/core.ts rename to src/cool/core/hook/index.ts index 99ad301..81a2190 100644 --- a/src/core/hook/core.ts +++ b/src/cool/core/hook/index.ts @@ -1,4 +1,4 @@ -import { onBeforeUpdate, ref, inject } from "vue"; +import { onBeforeUpdate, ref, inject, computed } from "vue"; import { useRoute, useRouter } from "vue-router"; import { useStore } from "vuex"; @@ -23,6 +23,7 @@ export function useCool() { const store = useStore(); const route = useRoute(); const router = useRouter(); + const app = computed(() => store.getters.app); return { store, @@ -31,6 +32,18 @@ export function useCool() { refs, setRefs, service, - mitt + mitt, + app + }; +} + +export function useModule() { + const store = useStore(); + const moduleList = computed(() => store.getters.moduleList); + const modules = computed(() => store.getters.modules); + + return { + moduleList, + modules }; } diff --git a/src/core/index.ts b/src/cool/core/index.ts similarity index 77% rename from src/core/index.ts rename to src/cool/core/index.ts index 648bc58..7bc090a 100644 --- a/src/core/index.ts +++ b/src/cool/core/index.ts @@ -1,11 +1,8 @@ -import BaseService from "./service/base"; -import { Service, Permission, useService } from "./service"; -import { useRouter } from "./router"; -import { useModule } from "./module"; import router from "/@/router"; import store from "/@/store"; - -const service = useService(); +import { service } from "./service"; +import { useRouter } from "./router"; +import { useModule } from "./module"; async function bootstrap(app: any) { app.config.globalProperties.service = store.service = service; @@ -37,5 +34,6 @@ function usePermission(list: any[]) { deep(service); } -export { Service, Permission, BaseService, service, bootstrap, usePermission }; +export { service, bootstrap, usePermission }; +export { BaseService, Service, Permission, useEps } from "./service"; export * from "./hook"; diff --git a/src/core/module/index.ts b/src/cool/core/module/index.ts similarity index 95% rename from src/core/module/index.ts rename to src/cool/core/module/index.ts index 9c99638..1e06252 100644 --- a/src/core/module/index.ts +++ b/src/cool/core/module/index.ts @@ -1,11 +1,11 @@ -import cool from "/@/cool"; +import { modules as mods } from "/@/cool/modules"; import store from "/@/store"; import router from "/@/router"; import { deepMerge, isFunction, isObject, isEmpty } from "../utils"; import { deepFiles } from "../service"; // 模块列表 -const modules: any[] = [...cool.modules]; +const modules: any[] = [...mods]; function useModule(app: any) { // 安装模块 @@ -78,6 +78,10 @@ function useModule(app: any) { const value: any = files[i].default; const fname: string = (cname || "").split(".")[0]; + if (name == "index.ts") { + continue; + } + function next(d: any) { // 配置参数入口 if (fn == "config.ts") { @@ -159,7 +163,8 @@ function useModule(app: any) { pages: [], views: [], store: {}, - _services: [] + _services: [], + _local: true }) ); } diff --git a/src/core/router/index.ts b/src/cool/core/router/index.ts similarity index 96% rename from src/core/router/index.ts rename to src/cool/core/router/index.ts index bbdd4bd..f2810f9 100644 --- a/src/core/router/index.ts +++ b/src/cool/core/router/index.ts @@ -1,8 +1,7 @@ import { ElMessage } from "element-plus"; import store from "/@/store"; import router, { ignore } from "/@/router"; -import storage from "../utils/storage"; -import { cloneDeep } from "../utils"; +import { cloneDeep, storage } from "../utils"; const views = import.meta.globEager("/src/**/views/**/*.vue"); diff --git a/src/core/service/base.ts b/src/cool/core/service/base.ts similarity index 81% rename from src/core/service/base.ts rename to src/cool/core/service/base.ts index 0cf6dc7..761466a 100644 --- a/src/core/service/base.ts +++ b/src/cool/core/service/base.ts @@ -3,7 +3,7 @@ import request from "/@/service/request"; import { baseUrl, isDev } from "/@/config/env"; export default class BaseService { - constructor() { + constructor(options: any = {}) { const crud: any = { page: "page", list: "list", @@ -13,6 +13,10 @@ export default class BaseService { update: "update" }; + if (options?.namespace) { + this.namespace = options?.namespace; + } + if (!this.permission) this.permission = {}; for (const i in crud) { @@ -51,62 +55,50 @@ export default class BaseService { return request(options); } - list(params: any) { + list(data: any) { return this.request({ url: "/list", method: "POST", - data: { - ...params - } + data }); } - page(params: any) { + page(data: any) { return this.request({ url: "/page", method: "POST", - data: { - ...params - } + data }); } info(params: any) { return this.request({ url: "/info", - params: { - ...params - } + params }); } - update(params: any) { + update(data: any) { return this.request({ url: "/update", method: "POST", - data: { - ...params - } + data }); } - delete(params: any) { + delete(data: any) { return this.request({ url: "/delete", method: "POST", - data: { - ...params - } + data }); } - add(params: any) { + add(data: any) { return this.request({ url: "/add", method: "POST", - data: { - ...params - } + data }); } } diff --git a/src/core/service/decorator.ts b/src/cool/core/service/decorator.ts similarity index 96% rename from src/core/service/decorator.ts rename to src/cool/core/service/decorator.ts index 592b0aa..22e353e 100644 --- a/src/core/service/decorator.ts +++ b/src/cool/core/service/decorator.ts @@ -1,7 +1,5 @@ import { isObject } from "../utils"; -console.log(__PROXY_LIST__); - export function Permission(value: string) { return function (target: any, key: any, descriptor: any) { if (!target.permission) { diff --git a/src/cool/core/service/index.ts b/src/cool/core/service/index.ts new file mode 100644 index 0000000..9d2c788 --- /dev/null +++ b/src/cool/core/service/index.ts @@ -0,0 +1,141 @@ +import BaseService from "./base"; +import { Service, Permission } from "./decorator"; +import { basename } from "../utils"; + +function deepFiles(list: any[]) { + const modules: any = {}; + + list.forEach((e) => { + const arr: any[] = e.path.split("/"); + const parents: any[] = arr.slice(0, arr.length - 1); + const name: string = basename(e.path).replace(".ts", ""); + + let curr: any = modules; + let prev: any = null; + let key: any = null; + + parents.forEach((k) => { + if (!curr[k]) { + curr[k] = {}; + } + + prev = curr; + curr = curr[k]; + key = k; + }); + + if (name == "index") { + prev[key] = e.value; + } else { + curr[name] = e.value; + } + }); + + return modules; +} + +function useService() { + const files = import.meta.globEager("/src/service/**/*.ts"); + const d: any = []; + + for (const i in files) { + if (!i.includes("request.ts")) { + const value = files[i].default; + d.push({ + path: i.replace("/src/service/", ""), + value: new value() + }); + } + } + + const s = deepFiles(d); + s.request = new BaseService().request; + + return s; +} + +const service = useService(); + +function useEps() { + return service.base.common + .eps() + .then((res: any) => { + for (const i in res) { + res[i].forEach((e: any) => { + // 分隔路径 + const arr = e.prefix + .replace(/\//, "") + .replace("admin", "") + .split("/") + .filter(Boolean); + + function deep(d: any, i: number) { + const k = arr[i]; + + if (k) { + // 是否最后一个 + if (arr[i + 1]) { + if (!d[k]) { + d[k] = {}; + } + + deep(d[k], i + 1); + } else { + // 本地不存在则创建实例 + if (!d[k]) { + d[k] = new BaseService({ + namespace: e.prefix.replace("/admin/", "") + }); + } + + // 创建方法 + e.api.forEach((a: any) => { + const n = a.path.replace("/", ""); + + if ( + ![ + "add", + "info", + "update", + "page", + "list", + "delete" + ].includes(n) + ) { + // 设置权限 + d[k].permission[n] = ( + (d[k].namespace ? d[k].namespace + "/" : "") + n + ).replace(/\//g, ":"); + + // 本地不存在则创建 + if (!d[k][n]) { + d[k][n] = function (data: any) { + return this.request({ + url: a.path, + method: a.method, + [a.method.toLocaleLowerCase() == "post" + ? "data" + : "params"]: data + }); + }; + } + } + }); + } + } + } + + deep(service, 0); + }); + } + + console.log(service); + + return res; + }) + .catch((err: string) => { + console.error("Eps error", err); + }); +} + +export { BaseService, Service, Permission, service, deepFiles, useService, useEps }; diff --git a/src/core/utils/index.ts b/src/cool/core/utils/index.ts similarity index 100% rename from src/core/utils/index.ts rename to src/cool/core/utils/index.ts diff --git a/src/core/utils/storage.ts b/src/cool/core/utils/storage.ts similarity index 100% rename from src/core/utils/storage.ts rename to src/cool/core/utils/storage.ts diff --git a/src/cool/index.ts b/src/cool/index.ts index 537087b..8c3b5fc 100644 --- a/src/cool/index.ts +++ b/src/cool/index.ts @@ -1,22 +1,2 @@ -import Crud from "cl-admin-crud-vue3"; -import "cl-admin-crud-vue3/dist/index.css"; - -export default { - modules: [ - // crud 模块 - { - name: "crud", - value: Crud, - options: { - crud: { - dict: { - sort: { - prop: "order", - order: "sort" - } - } - } - } - } - ] -}; +export * from "./core"; +export * from "./modules"; diff --git a/src/cool/modules/base/common/theme.ts b/src/cool/modules/base/common/theme.ts index e2f97ea..88fcf51 100644 --- a/src/cool/modules/base/common/theme.ts +++ b/src/cool/modules/base/common/theme.ts @@ -1,5 +1,5 @@ import { iconfontUrl, app } from "/@/config/env"; -import { basename } from "/@/core/utils"; +import { basename } from "/@/cool/utils"; import { createLink } from "../utils"; // 主题初始化 diff --git a/src/cool/modules/base/components/avatar/index.vue b/src/cool/modules/base/components/avatar/index.vue index a8022f3..679f71f 100644 --- a/src/cool/modules/base/components/avatar/index.vue +++ b/src/cool/modules/base/components/avatar/index.vue @@ -1,6 +1,6 @@