diff --git a/new-ui/projects/admin/src/components/PermissionRender.vue b/new-ui/projects/admin/src/components/PermissionRender.vue
new file mode 100644
index 00000000..07493888
--- /dev/null
+++ b/new-ui/projects/admin/src/components/PermissionRender.vue
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/new-ui/projects/admin/src/composables/useSubmit.ts b/new-ui/projects/admin/src/composables/useSubmit.ts
index 35a34aee..9f44b196 100644
--- a/new-ui/projects/admin/src/composables/useSubmit.ts
+++ b/new-ui/projects/admin/src/composables/useSubmit.ts
@@ -1,5 +1,4 @@
import { ref, reactive, unref } from "vue";
-import { Message } from "@arco-design/web-vue";
import type { BaseResponse } from "@chatgpt-plus/packages/type";
function useSubmit = Record, R = any>(defaultData?: T) {
const formRef = ref();
@@ -10,14 +9,16 @@ function useSubmit = Record, R = any>
submitting.value = true;
try {
const hasError = await formRef.value?.validate();
- if (!hasError) {
- const { data, message } = await api({ ...formData ?? {}, ...unref(params) });
- message && Message.success(message);
- return Promise.resolve({ formData, data });
+ if (hasError) return Promise.reject({ validateErrors: hasError });
+
+ const { data, code, message } = await api({ ...formData ?? {}, ...unref(params) });
+ if (code) {
+ return Promise.reject({ requestErrors: message })
}
- return Promise.reject(false);
+
+ return Promise.resolve({ formData, data });
} catch (err) {
- return Promise.reject(err);
+ return Promise.reject({ errors: err });
} finally {
submitting.value = false;
}
diff --git a/new-ui/projects/admin/src/directives/permission.ts b/new-ui/projects/admin/src/directives/permission.ts
new file mode 100644
index 00000000..35c51897
--- /dev/null
+++ b/new-ui/projects/admin/src/directives/permission.ts
@@ -0,0 +1,32 @@
+import { useAuthStore } from "@/stores/auth";
+
+// 判断操作权限
+export function hasPermission(permissionTag: string | string[] | boolean) {
+ const authStore = useAuthStore();
+ const { is_super_admin, permissions = [] } = authStore;
+ if (is_super_admin) {
+ return true;
+ }
+ if (Array.isArray(permissionTag)) {
+ return permissionTag.every((tag) => permissions.includes(tag));
+ }
+ if (typeof permissionTag === "string") {
+ return permissions.includes(permissionTag);
+ }
+ return permissionTag;
+}
+
+function checkPermission(el, binding) {
+ if (!hasPermission(binding.value)) {
+ el.parentNode && el.parentNode.removeChild(el);
+ }
+}
+
+export const permission = {
+ mounted(el, binding) {
+ checkPermission(el, binding);
+ },
+ updated(el, binding) {
+ checkPermission(el, binding);
+ },
+};
diff --git a/new-ui/projects/admin/src/http/config.ts b/new-ui/projects/admin/src/http/config.ts
index d7f24509..14ddc588 100644
--- a/new-ui/projects/admin/src/http/config.ts
+++ b/new-ui/projects/admin/src/http/config.ts
@@ -8,8 +8,9 @@ export const uploadUrl = import.meta.env.VITE_PROXY_BASE_URL + "/api/admin/uploa
export const instance = createInstance(import.meta.env.VITE_PROXY_BASE_URL)
instance.interceptors.request.use((config) => {
- config.headers[__AUTH_KEY] = localStorage.getItem(__AUTH_KEY);
- config.headers["Authorization"] = localStorage.getItem(__AUTH_KEY);
+ const TOKEN = JSON.parse(localStorage.getItem(__AUTH_KEY))?.token
+ config.headers[__AUTH_KEY] = TOKEN;
+ config.headers["Authorization"] = TOKEN;
return config;
});
diff --git a/new-ui/projects/admin/src/http/login.ts b/new-ui/projects/admin/src/http/login.ts
index 8e159b65..8b083330 100644
--- a/new-ui/projects/admin/src/http/login.ts
+++ b/new-ui/projects/admin/src/http/login.ts
@@ -1,9 +1,6 @@
import http from "@/http/config";
-export const userLogin = (data: {
- username: string;
- password: string;
-}) => {
+export const userLogin = (data) => {
return http({
url: "/api/admin/login",
method: "post",
@@ -26,7 +23,7 @@ export const getSession = () => {
};
-export const loginLog = (params?: Record) => {
+export const loginLog = (params) => {
return http({
url: "/api/admin/user/loginLog",
method: "get",
diff --git a/new-ui/projects/admin/src/main.ts b/new-ui/projects/admin/src/main.ts
index 559f2f7c..08dba0c6 100644
--- a/new-ui/projects/admin/src/main.ts
+++ b/new-ui/projects/admin/src/main.ts
@@ -3,6 +3,8 @@ import { createPinia } from "pinia";
import ArcoVue from "@arco-design/web-vue";
import ArcoVueIcon from "@arco-design/web-vue/es/icon";
import "@arco-design/web-vue/dist/arco.css";
+import PermissionRender from "@/components/PermissionRender.vue";
+import { permission } from "@/directives/permission";
import App from "./App.vue";
import router from "./router";
@@ -14,6 +16,9 @@ app.use(router);
app.use(ArcoVue);
app.use(ArcoVueIcon);
+app.component("PermissionRender", PermissionRender);
+app.directive("permission", permission);
+
app.mount("#app");
app.config.warnHandler = (msg, vm, trace) => {
if (msg.includes('Invalid prop name: "key" is a reserved property.')) {
diff --git a/new-ui/projects/admin/src/router/index.ts b/new-ui/projects/admin/src/router/index.ts
index a578cbd3..dabd58d1 100644
--- a/new-ui/projects/admin/src/router/index.ts
+++ b/new-ui/projects/admin/src/router/index.ts
@@ -1,14 +1,27 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import { useAuthStore } from "@/stores/auth";
import CustomLayout from '@/components/CustomLayout.vue'
+import { hasPermission } from "@/directives/permission";
import menu from './menu'
+declare module 'vue-router' {
+ interface RouteMeta {
+ title?: string
+ permission?: string
+ }
+}
+
const whiteListRoutes = [
{
path: "/login",
name: "Login",
component: () => import("@/views/LoginView.vue"),
},
+ {
+ path: "/403",
+ name: "403",
+ component: () => import("@/views/NoPermission.vue"),
+ },
{
path: "/:pathMatch(.*)*",
name: "404",
@@ -44,9 +57,13 @@ router.beforeEach((to, _, next) => {
return;
}
if (!authStore.token) {
+ authStore.$reset();
next({ name: "Login" });
return;
}
+ if (to.meta.permission) {
+ next(!hasPermission(to.meta.permission) ? { name: "403" } : undefined);
+ }
next();
});
diff --git a/new-ui/projects/admin/src/router/menu.ts b/new-ui/projects/admin/src/router/menu.ts
index 926dac74..4f037cba 100644
--- a/new-ui/projects/admin/src/router/menu.ts
+++ b/new-ui/projects/admin/src/router/menu.ts
@@ -12,6 +12,7 @@ import {
IconCodepen,
IconWechatpay,
IconRobot,
+ IconSafe,
} from "@arco-design/web-vue/es/icon";
const menu = [
@@ -133,6 +134,15 @@ const menu = [
},
component: () => import("@/views/SysAdmin/SysAdminContainer.vue"),
},
+ {
+ path: "/sysPermission",
+ name: "SysPermission",
+ meta: {
+ title: "权限配置",
+ icon: IconSafe,
+ },
+ component: () => import("@/views/SysPermission/SysPermissionContainer.vue"),
+ },
];
export default menu;
diff --git a/new-ui/projects/admin/src/stores/auth.ts b/new-ui/projects/admin/src/stores/auth.ts
index 1e9e90b4..9027648a 100644
--- a/new-ui/projects/admin/src/stores/auth.ts
+++ b/new-ui/projects/admin/src/stores/auth.ts
@@ -3,19 +3,29 @@ import { Message } from '@arco-design/web-vue'
import { userLogin, userLogout } from '@/http/login'
import router from '@/router'
+const defaultState: {
+ token: string
+ is_super_admin?: boolean;
+ permissions?: string[]
+} = {
+ token: null,
+ is_super_admin: false,
+ permissions: []
+}
+
export const useAuthStore = defineStore({
- id: __AUTH_KEY,
- state: () => ({ token: null } as { token: string | null }),
+ id: Symbol(__AUTH_KEY).toString(),
+ state: () => ({ ...defaultState }),
actions: {
init() {
- this.$state.token = localStorage.getItem(__AUTH_KEY);
+ this.$state = JSON.parse(localStorage.getItem(__AUTH_KEY));
},
async login(params: any) {
try {
const { data } = await userLogin(params)
if (data) {
- this.$state.token = data;
- localStorage.setItem(__AUTH_KEY, data)
+ this.$state = data;
+ localStorage.setItem(__AUTH_KEY, JSON.stringify(data))
Message.success('登录成功');
router.replace({ name: 'home' })
return Promise.resolve(data)
diff --git a/new-ui/projects/admin/src/stores/counter.ts b/new-ui/projects/admin/src/stores/counter.ts
deleted file mode 100644
index b6757ba5..00000000
--- a/new-ui/projects/admin/src/stores/counter.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { ref, computed } from 'vue'
-import { defineStore } from 'pinia'
-
-export const useCounterStore = defineStore('counter', () => {
- const count = ref(0)
- const doubleCount = computed(() => count.value * 2)
- function increment() {
- count.value++
- }
-
- return { count, doubleCount, increment }
-})
diff --git a/new-ui/projects/admin/src/views/NoPermission.vue b/new-ui/projects/admin/src/views/NoPermission.vue
new file mode 100644
index 00000000..64b7e278
--- /dev/null
+++ b/new-ui/projects/admin/src/views/NoPermission.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/new-ui/projects/admin/src/views/Order/OrderContainer.vue b/new-ui/projects/admin/src/views/Order/OrderContainer.vue
index 9757d3b5..9358450c 100644
--- a/new-ui/projects/admin/src/views/Order/OrderContainer.vue
+++ b/new-ui/projects/admin/src/views/Order/OrderContainer.vue
@@ -1,8 +1,9 @@
@@ -78,8 +85,15 @@ const columns: SearchTableColumns[] = [
未支付
{{ dateFormat(record.pay_time) }}
-
- 删除
+
+
+ 删除
+
diff --git a/new-ui/projects/admin/src/views/Order/api.ts b/new-ui/projects/admin/src/views/Order/api.ts
index 6bb73492..45abec0d 100644
--- a/new-ui/projects/admin/src/views/Order/api.ts
+++ b/new-ui/projects/admin/src/views/Order/api.ts
@@ -6,4 +6,12 @@ export const getList = (data?: Record) => {
method: "post",
data
})
+}
+
+export const remove = (data) => {
+ return http({
+ url: "/api/admin/order/remove",
+ method: "post",
+ data
+ })
}
\ No newline at end of file
diff --git a/new-ui/projects/admin/src/views/SysPermission/SysPermissionContainer.vue b/new-ui/projects/admin/src/views/SysPermission/SysPermissionContainer.vue
new file mode 100644
index 00000000..4724ebbc
--- /dev/null
+++ b/new-ui/projects/admin/src/views/SysPermission/SysPermissionContainer.vue
@@ -0,0 +1,82 @@
+
+
+
+
+
+ 编辑
+
+ 删除
+
+
+
+
diff --git a/new-ui/projects/admin/src/views/SysPermission/SysPermissionForm.vue b/new-ui/projects/admin/src/views/SysPermission/SysPermissionForm.vue
new file mode 100644
index 00000000..60fdf480
--- /dev/null
+++ b/new-ui/projects/admin/src/views/SysPermission/SysPermissionForm.vue
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/new-ui/projects/admin/src/views/SysPermission/api.ts b/new-ui/projects/admin/src/views/SysPermission/api.ts
new file mode 100644
index 00000000..49ba6b6e
--- /dev/null
+++ b/new-ui/projects/admin/src/views/SysPermission/api.ts
@@ -0,0 +1,25 @@
+import http from "@/http/config";
+
+export const getList = (params) => {
+ return http({
+ url: "/api/admin/sysPermission/list",
+ method: "get",
+ params
+ })
+}
+
+export const save = (data) => {
+ return http({
+ url: "/api/admin/sysPermission/save",
+ method: "post",
+ data
+ })
+}
+
+export const remove = (data) => {
+ return http({
+ url: "/api/admin/sysPermission/remove",
+ method: "post",
+ data
+ })
+}
\ No newline at end of file