20260810223432
This commit is contained in:
1 parent
ed5ab3885d
commit
5adbf59425
364 files changed
+7559
-4358
No files matched your search
+227
-101
@@ -1,143 +1,269 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { defineStore } from "pinia";
|
||||
import { computed, ref, watch } from "vue";
|
||||
|
||||
export type ColorScheme = {
|
||||
label: string
|
||||
primary: string
|
||||
primaryFg: string
|
||||
ring: string
|
||||
sidebarPrimary: string
|
||||
sidebarRing: string
|
||||
}
|
||||
label: string;
|
||||
primary: string;
|
||||
primaryFg: string;
|
||||
ring: string;
|
||||
sidebarPrimary: string;
|
||||
sidebarRing: string;
|
||||
};
|
||||
|
||||
const colorSchemes: { light: ColorScheme; dark: ColorScheme }[] = [
|
||||
{
|
||||
light: { label: '#1a1a2e', primary: 'oklch(0.205 0 0)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.708 0 0)', sidebarPrimary: 'oklch(0.205 0 0)', sidebarRing: 'oklch(0.708 0 0)' },
|
||||
dark: { label: '#1a1a2e', primary: 'oklch(0.922 0 0)', primaryFg: 'oklch(0.205 0 0)', ring: 'oklch(0.556 0 0)', sidebarPrimary: 'oklch(0.488 0.243 264.376)', sidebarRing: 'oklch(0.556 0 0)' },
|
||||
light: {
|
||||
label: "#1a1a2e",
|
||||
primary: "oklch(0.205 0 0)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.708 0 0)",
|
||||
sidebarPrimary: "oklch(0.205 0 0)",
|
||||
sidebarRing: "oklch(0.708 0 0)",
|
||||
},
|
||||
dark: {
|
||||
label: "#1a1a2e",
|
||||
primary: "oklch(0.922 0 0)",
|
||||
primaryFg: "oklch(0.205 0 0)",
|
||||
ring: "oklch(0.556 0 0)",
|
||||
sidebarPrimary: "oklch(0.488 0.243 264.376)",
|
||||
sidebarRing: "oklch(0.556 0 0)",
|
||||
},
|
||||
},
|
||||
{
|
||||
light: { label: '#3b82f6', primary: 'oklch(0.546 0.245 262.881)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.546 0.245 262.881)', sidebarPrimary: 'oklch(0.546 0.245 262.881)', sidebarRing: 'oklch(0.546 0.245 262.881)' },
|
||||
dark: { label: '#3b82f6', primary: 'oklch(0.623 0.214 259.815)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.623 0.214 259.815)', sidebarPrimary: 'oklch(0.623 0.214 259.815)', sidebarRing: 'oklch(0.623 0.214 259.815)' },
|
||||
light: {
|
||||
label: "#3b82f6",
|
||||
primary: "oklch(0.546 0.245 262.881)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.546 0.245 262.881)",
|
||||
sidebarPrimary: "oklch(0.546 0.245 262.881)",
|
||||
sidebarRing: "oklch(0.546 0.245 262.881)",
|
||||
},
|
||||
dark: {
|
||||
label: "#3b82f6",
|
||||
primary: "oklch(0.623 0.214 259.815)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.623 0.214 259.815)",
|
||||
sidebarPrimary: "oklch(0.623 0.214 259.815)",
|
||||
sidebarRing: "oklch(0.623 0.214 259.815)",
|
||||
},
|
||||
},
|
||||
{
|
||||
light: { label: '#22c55e', primary: 'oklch(0.527 0.154 150.069)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.527 0.154 150.069)', sidebarPrimary: 'oklch(0.527 0.154 150.069)', sidebarRing: 'oklch(0.527 0.154 150.069)' },
|
||||
dark: { label: '#22c55e', primary: 'oklch(0.596 0.145 163.225)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.596 0.145 163.225)', sidebarPrimary: 'oklch(0.596 0.145 163.225)', sidebarRing: 'oklch(0.596 0.145 163.225)' },
|
||||
light: {
|
||||
label: "#22c55e",
|
||||
primary: "oklch(0.527 0.154 150.069)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.527 0.154 150.069)",
|
||||
sidebarPrimary: "oklch(0.527 0.154 150.069)",
|
||||
sidebarRing: "oklch(0.527 0.154 150.069)",
|
||||
},
|
||||
dark: {
|
||||
label: "#22c55e",
|
||||
primary: "oklch(0.596 0.145 163.225)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.596 0.145 163.225)",
|
||||
sidebarPrimary: "oklch(0.596 0.145 163.225)",
|
||||
sidebarRing: "oklch(0.596 0.145 163.225)",
|
||||
},
|
||||
},
|
||||
{
|
||||
light: { label: '#8b5cf6', primary: 'oklch(0.496 0.265 301.924)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.496 0.265 301.924)', sidebarPrimary: 'oklch(0.496 0.265 301.924)', sidebarRing: 'oklch(0.496 0.265 301.924)' },
|
||||
dark: { label: '#8b5cf6', primary: 'oklch(0.558 0.238 301.358)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.558 0.238 301.358)', sidebarPrimary: 'oklch(0.558 0.238 301.358)', sidebarRing: 'oklch(0.558 0.238 301.358)' },
|
||||
light: {
|
||||
label: "#8b5cf6",
|
||||
primary: "oklch(0.496 0.265 301.924)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.496 0.265 301.924)",
|
||||
sidebarPrimary: "oklch(0.496 0.265 301.924)",
|
||||
sidebarRing: "oklch(0.496 0.265 301.924)",
|
||||
},
|
||||
dark: {
|
||||
label: "#8b5cf6",
|
||||
primary: "oklch(0.558 0.238 301.358)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.558 0.238 301.358)",
|
||||
sidebarPrimary: "oklch(0.558 0.238 301.358)",
|
||||
sidebarRing: "oklch(0.558 0.238 301.358)",
|
||||
},
|
||||
},
|
||||
{
|
||||
light: { label: '#f97316', primary: 'oklch(0.57 0.2 49.5)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.57 0.2 49.5)', sidebarPrimary: 'oklch(0.57 0.2 49.5)', sidebarRing: 'oklch(0.57 0.2 49.5)' },
|
||||
dark: { label: '#f97316', primary: 'oklch(0.643 0.215 41.5)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.643 0.215 41.5)', sidebarPrimary: 'oklch(0.643 0.215 41.5)', sidebarRing: 'oklch(0.643 0.215 41.5)' },
|
||||
light: {
|
||||
label: "#f97316",
|
||||
primary: "oklch(0.57 0.2 49.5)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.57 0.2 49.5)",
|
||||
sidebarPrimary: "oklch(0.57 0.2 49.5)",
|
||||
sidebarRing: "oklch(0.57 0.2 49.5)",
|
||||
},
|
||||
dark: {
|
||||
label: "#f97316",
|
||||
primary: "oklch(0.643 0.215 41.5)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.643 0.215 41.5)",
|
||||
sidebarPrimary: "oklch(0.643 0.215 41.5)",
|
||||
sidebarRing: "oklch(0.643 0.215 41.5)",
|
||||
},
|
||||
},
|
||||
{
|
||||
light: { label: '#ef4444', primary: 'oklch(0.506 0.232 25.7)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.506 0.232 25.7)', sidebarPrimary: 'oklch(0.506 0.232 25.7)', sidebarRing: 'oklch(0.506 0.232 25.7)' },
|
||||
dark: { label: '#ef4444', primary: 'oklch(0.577 0.245 27.325)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.577 0.245 27.325)', sidebarPrimary: 'oklch(0.577 0.245 27.325)', sidebarRing: 'oklch(0.577 0.245 27.325)' },
|
||||
light: {
|
||||
label: "#ef4444",
|
||||
primary: "oklch(0.506 0.232 25.7)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.506 0.232 25.7)",
|
||||
sidebarPrimary: "oklch(0.506 0.232 25.7)",
|
||||
sidebarRing: "oklch(0.506 0.232 25.7)",
|
||||
},
|
||||
dark: {
|
||||
label: "#ef4444",
|
||||
primary: "oklch(0.577 0.245 27.325)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.577 0.245 27.325)",
|
||||
sidebarPrimary: "oklch(0.577 0.245 27.325)",
|
||||
sidebarRing: "oklch(0.577 0.245 27.325)",
|
||||
},
|
||||
},
|
||||
{
|
||||
light: { label: '#ec4899', primary: 'oklch(0.523 0.214 349.4)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.523 0.214 349.4)', sidebarPrimary: 'oklch(0.523 0.214 349.4)', sidebarRing: 'oklch(0.523 0.214 349.4)' },
|
||||
dark: { label: '#ec4899', primary: 'oklch(0.592 0.225 349.5)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.592 0.225 349.5)', sidebarPrimary: 'oklch(0.592 0.225 349.5)', sidebarRing: 'oklch(0.592 0.225 349.5)' },
|
||||
light: {
|
||||
label: "#ec4899",
|
||||
primary: "oklch(0.523 0.214 349.4)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.523 0.214 349.4)",
|
||||
sidebarPrimary: "oklch(0.523 0.214 349.4)",
|
||||
sidebarRing: "oklch(0.523 0.214 349.4)",
|
||||
},
|
||||
dark: {
|
||||
label: "#ec4899",
|
||||
primary: "oklch(0.592 0.225 349.5)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.592 0.225 349.5)",
|
||||
sidebarPrimary: "oklch(0.592 0.225 349.5)",
|
||||
sidebarRing: "oklch(0.592 0.225 349.5)",
|
||||
},
|
||||
},
|
||||
{
|
||||
light: { label: '#14b8a6', primary: 'oklch(0.563 0.144 180)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.563 0.144 180)', sidebarPrimary: 'oklch(0.563 0.144 180)', sidebarRing: 'oklch(0.563 0.144 180)' },
|
||||
dark: { label: '#14b8a6', primary: 'oklch(0.627 0.124 180)', primaryFg: 'oklch(0.985 0 0)', ring: 'oklch(0.627 0.124 180)', sidebarPrimary: 'oklch(0.627 0.124 180)', sidebarRing: 'oklch(0.627 0.124 180)' },
|
||||
light: {
|
||||
label: "#14b8a6",
|
||||
primary: "oklch(0.563 0.144 180)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.563 0.144 180)",
|
||||
sidebarPrimary: "oklch(0.563 0.144 180)",
|
||||
sidebarRing: "oklch(0.563 0.144 180)",
|
||||
},
|
||||
dark: {
|
||||
label: "#14b8a6",
|
||||
primary: "oklch(0.627 0.124 180)",
|
||||
primaryFg: "oklch(0.985 0 0)",
|
||||
ring: "oklch(0.627 0.124 180)",
|
||||
sidebarPrimary: "oklch(0.627 0.124 180)",
|
||||
sidebarRing: "oklch(0.627 0.124 180)",
|
||||
},
|
||||
},
|
||||
]
|
||||
];
|
||||
|
||||
function loadPersisted<T>(key: string, fallback: T): T {
|
||||
try {
|
||||
const raw = localStorage.getItem(key)
|
||||
if (raw != null) return JSON.parse(raw) as T
|
||||
} catch { /* ignore */ }
|
||||
return fallback
|
||||
const raw = localStorage.getItem(key);
|
||||
if (raw != null) return JSON.parse(raw) as T;
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
function persist(key: string, value: unknown) {
|
||||
try { localStorage.setItem(key, JSON.stringify(value)) } catch { /* ignore */ }
|
||||
try {
|
||||
localStorage.setItem(key, JSON.stringify(value));
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
export type TabItem = {
|
||||
key: string
|
||||
label: string
|
||||
closable: boolean
|
||||
}
|
||||
key: string;
|
||||
label: string;
|
||||
closable: boolean;
|
||||
};
|
||||
|
||||
export const useAppStore = defineStore('app', () => {
|
||||
// -- dark mode --
|
||||
const isDark = ref(loadPersisted<boolean>('fms-dark', false))
|
||||
function toggleTheme() {
|
||||
isDark.value = !isDark.value
|
||||
}
|
||||
// Sync to DOM
|
||||
watch(isDark, (v) => {
|
||||
document.documentElement.classList.toggle('dark', v)
|
||||
persist('fms-dark', v)
|
||||
}, { immediate: true })
|
||||
export const useAppStore = defineStore(
|
||||
"app",
|
||||
() => {
|
||||
// -- dark mode --
|
||||
const isDark = ref(loadPersisted<boolean>("fms-dark", false));
|
||||
function toggleTheme() {
|
||||
isDark.value = !isDark.value;
|
||||
}
|
||||
// Sync to DOM
|
||||
watch(
|
||||
isDark,
|
||||
(v) => {
|
||||
document.documentElement.classList.toggle("dark", v);
|
||||
persist("fms-dark", v);
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
// -- color scheme & locale (persisted by pinia-plugin-persistedstate) --
|
||||
const schemeIndex = ref(0)
|
||||
const locale = ref('zh-CN')
|
||||
// -- color scheme & locale (persisted by pinia-plugin-persistedstate) --
|
||||
const schemeIndex = ref(0);
|
||||
const locale = ref("zh-CN");
|
||||
|
||||
// -- tabs --
|
||||
const visitedTabs = ref<TabItem[]>([{ key: '/dashboard', label: '工作台', closable: false }])
|
||||
const routeRefreshKeys = ref<Record<string, number>>({})
|
||||
// -- tabs --
|
||||
const visitedTabs = ref<TabItem[]>([{ key: "/dashboard", label: "工作台", closable: false }]);
|
||||
const routeRefreshKeys = ref<Record<string, number>>({});
|
||||
|
||||
const schemeKeys = colorSchemes
|
||||
const totalSchemes = colorSchemes.length
|
||||
const schemeKeys = colorSchemes;
|
||||
const totalSchemes = colorSchemes.length;
|
||||
|
||||
const currentScheme = computed<ColorScheme>(() => {
|
||||
const entry = colorSchemes[schemeIndex.value] ?? colorSchemes[0]
|
||||
return isDark.value ? entry.dark : entry.light
|
||||
})
|
||||
const currentScheme = computed<ColorScheme>(() => {
|
||||
const entry = colorSchemes[schemeIndex.value] ?? colorSchemes[0];
|
||||
return isDark.value ? entry.dark : entry.light;
|
||||
});
|
||||
|
||||
function selectColorScheme(index: number) {
|
||||
schemeIndex.value = index
|
||||
}
|
||||
function selectColorScheme(index: number) {
|
||||
schemeIndex.value = index;
|
||||
}
|
||||
|
||||
function toggleLocale() {
|
||||
locale.value = locale.value === 'zh-CN' ? 'en-US' : 'zh-CN'
|
||||
}
|
||||
function toggleLocale() {
|
||||
locale.value = locale.value === "zh-CN" ? "en-US" : "zh-CN";
|
||||
}
|
||||
|
||||
// -- tab management --
|
||||
function addVisitedTab(tab: TabItem) {
|
||||
const exists = visitedTabs.value.find(t => t.key === tab.key)
|
||||
if (exists) return
|
||||
visitedTabs.value.push(tab)
|
||||
}
|
||||
// -- tab management --
|
||||
function addVisitedTab(tab: TabItem) {
|
||||
const exists = visitedTabs.value.find((t) => t.key === tab.key);
|
||||
if (exists) return;
|
||||
visitedTabs.value.push(tab);
|
||||
}
|
||||
|
||||
function removeVisitedTab(key: string) {
|
||||
const index = visitedTabs.value.findIndex(t => t.key === key)
|
||||
if (index >= 0) visitedTabs.value.splice(index, 1)
|
||||
}
|
||||
function removeVisitedTab(key: string) {
|
||||
const index = visitedTabs.value.findIndex((t) => t.key === key);
|
||||
if (index >= 0) visitedTabs.value.splice(index, 1);
|
||||
}
|
||||
|
||||
function getRouteRefreshKey(key: string) {
|
||||
return routeRefreshKeys.value[key] ?? 0
|
||||
}
|
||||
function getRouteRefreshKey(key: string) {
|
||||
return routeRefreshKeys.value[key] ?? 0;
|
||||
}
|
||||
|
||||
function refreshRoute(key: string) {
|
||||
routeRefreshKeys.value[key] = (routeRefreshKeys.value[key] ?? 0) + 1
|
||||
}
|
||||
function refreshRoute(key: string) {
|
||||
routeRefreshKeys.value[key] = (routeRefreshKeys.value[key] ?? 0) + 1;
|
||||
}
|
||||
|
||||
return {
|
||||
isDark,
|
||||
toggleTheme,
|
||||
schemeIndex,
|
||||
locale,
|
||||
visitedTabs,
|
||||
routeRefreshKeys,
|
||||
schemeKeys,
|
||||
totalSchemes,
|
||||
currentScheme,
|
||||
selectColorScheme,
|
||||
toggleLocale,
|
||||
addVisitedTab,
|
||||
removeVisitedTab,
|
||||
getRouteRefreshKey,
|
||||
refreshRoute,
|
||||
}
|
||||
}, {
|
||||
persist: {
|
||||
pick: ['schemeIndex', 'locale'],
|
||||
return {
|
||||
isDark,
|
||||
toggleTheme,
|
||||
schemeIndex,
|
||||
locale,
|
||||
visitedTabs,
|
||||
routeRefreshKeys,
|
||||
schemeKeys,
|
||||
totalSchemes,
|
||||
currentScheme,
|
||||
selectColorScheme,
|
||||
toggleLocale,
|
||||
addVisitedTab,
|
||||
removeVisitedTab,
|
||||
getRouteRefreshKey,
|
||||
refreshRoute,
|
||||
};
|
||||
},
|
||||
})
|
||||
{
|
||||
persist: {
|
||||
pick: ["schemeIndex", "locale"],
|
||||
},
|
||||
},
|
||||
);
|
||||
@@ -1,47 +1,47 @@
|
||||
import { computed, ref } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { computed, ref } from "vue";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
const AUTH_STORAGE_KEY = 'fms-auth'
|
||||
const AUTH_STORAGE_KEY = "fms-auth";
|
||||
|
||||
try {
|
||||
const session = sessionStorage.getItem(AUTH_STORAGE_KEY)
|
||||
const session = sessionStorage.getItem(AUTH_STORAGE_KEY);
|
||||
if (session && !localStorage.getItem(AUTH_STORAGE_KEY)) {
|
||||
localStorage.setItem(AUTH_STORAGE_KEY, session)
|
||||
localStorage.setItem(AUTH_STORAGE_KEY, session);
|
||||
}
|
||||
} catch {
|
||||
// Storage can be unavailable in restricted browser contexts.
|
||||
}
|
||||
|
||||
interface UserInfo {
|
||||
id: string
|
||||
account?: string
|
||||
name: string
|
||||
id: string;
|
||||
account?: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface SessionData {
|
||||
token?: string
|
||||
access_token?: string
|
||||
orgid?: string
|
||||
user?: UserInfo
|
||||
user_info?: UserInfo
|
||||
token?: string;
|
||||
access_token?: string;
|
||||
orgid?: string;
|
||||
user?: UserInfo;
|
||||
user_info?: UserInfo;
|
||||
}
|
||||
|
||||
export const useAuthStore = defineStore(
|
||||
'auth',
|
||||
"auth",
|
||||
() => {
|
||||
const token = ref('')
|
||||
const orgId = ref('')
|
||||
const user = ref<UserInfo | null>(null)
|
||||
const isAuthenticated = computed(() => Boolean(token.value))
|
||||
const token = ref("");
|
||||
const orgId = ref("");
|
||||
const user = ref<UserInfo | null>(null);
|
||||
const isAuthenticated = computed(() => Boolean(token.value));
|
||||
|
||||
function setSession(session: SessionData, organizationId?: string) {
|
||||
token.value = session.token ?? session.access_token ?? ''
|
||||
orgId.value = session.orgid ?? organizationId ?? ''
|
||||
user.value = session.user ?? session.user_info ?? null
|
||||
token.value = session.token ?? session.access_token ?? "";
|
||||
orgId.value = session.orgid ?? organizationId ?? "";
|
||||
user.value = session.user ?? session.user_info ?? null;
|
||||
}
|
||||
|
||||
function clearSession() {
|
||||
token.value = ''
|
||||
token.value = "";
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -51,13 +51,13 @@ export const useAuthStore = defineStore(
|
||||
isAuthenticated,
|
||||
setSession,
|
||||
clearSession,
|
||||
}
|
||||
};
|
||||
},
|
||||
{
|
||||
persist: {
|
||||
key: AUTH_STORAGE_KEY,
|
||||
storage: localStorage,
|
||||
pick: ['token', 'orgId', 'user'],
|
||||
pick: ["token", "orgId", "user"],
|
||||
},
|
||||
},
|
||||
)
|
||||
);
|
||||
@@ -1,168 +1,172 @@
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { loadDataApi } from '@/services/api'
|
||||
import { useAuthStore } from './auth'
|
||||
import { computed, ref, watch } from "vue";
|
||||
import { defineStore } from "pinia";
|
||||
import { loadDataApi } from "@/services/api";
|
||||
import { useAuthStore } from "./auth";
|
||||
|
||||
interface Module {
|
||||
b_id: number | string
|
||||
b_code: string
|
||||
b_module_type: string
|
||||
b_parent_id?: number | string
|
||||
[key: string]: unknown
|
||||
b_id: number | string;
|
||||
b_code: string;
|
||||
b_module_type: string;
|
||||
b_parent_id?: number | string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface UserModule {
|
||||
b_module_id: number | string
|
||||
[key: string]: unknown
|
||||
b_module_id: number | string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface ModulePower {
|
||||
b_id: number | string
|
||||
b_module_id: number | string
|
||||
b_code: string
|
||||
[key: string]: unknown
|
||||
b_id: number | string;
|
||||
b_module_id: number | string;
|
||||
b_code: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export const usePermissionStore = defineStore('permissions', () => {
|
||||
const authStore = useAuthStore()
|
||||
const loadedPrincipalKey = ref('')
|
||||
const modules = ref<Module[]>([])
|
||||
const grantedPageIds = ref<string[]>([])
|
||||
const moduleCodes = ref<string[]>([])
|
||||
const powerCodes = ref<string[]>([])
|
||||
let loadingPromise: Promise<void> | null = null
|
||||
let loadingPrincipalKey = ''
|
||||
let loadVersion = 0
|
||||
export const usePermissionStore = defineStore("permissions", () => {
|
||||
const authStore = useAuthStore();
|
||||
const loadedPrincipalKey = ref("");
|
||||
const modules = ref<Module[]>([]);
|
||||
const grantedPageIds = ref<string[]>([]);
|
||||
const moduleCodes = ref<string[]>([]);
|
||||
const powerCodes = ref<string[]>([]);
|
||||
let loadingPromise: Promise<void> | null = null;
|
||||
let loadingPrincipalKey = "";
|
||||
let loadVersion = 0;
|
||||
|
||||
const moduleByCode = computed(
|
||||
() => new Map(modules.value.map((m) => [String(m.b_code || ''), m])),
|
||||
)
|
||||
const moduleById = computed(
|
||||
() => new Map(modules.value.map((m) => [String(m.b_id || ''), m])),
|
||||
)
|
||||
const grantedPageSet = computed(() => new Set(grantedPageIds.value))
|
||||
const powerSet = computed(() => new Set(powerCodes.value))
|
||||
() => new Map(modules.value.map((m) => [String(m.b_code || ""), m])),
|
||||
);
|
||||
const moduleById = computed(() => new Map(modules.value.map((m) => [String(m.b_id || ""), m])));
|
||||
const grantedPageSet = computed(() => new Set(grantedPageIds.value));
|
||||
const powerSet = computed(() => new Set(powerCodes.value));
|
||||
const isG3soft = computed(() => {
|
||||
return String(authStore.user?.account || '').trim().toLowerCase() === 'g3soft'
|
||||
})
|
||||
return (
|
||||
String(authStore.user?.account || "")
|
||||
.trim()
|
||||
.toLowerCase() === "g3soft"
|
||||
);
|
||||
});
|
||||
|
||||
async function load(): Promise<void> {
|
||||
const userId = String(authStore.user?.id || '')
|
||||
const principalKey = `${String(authStore.orgId || '')}:${userId}`
|
||||
const userId = String(authStore.user?.id || "");
|
||||
const principalKey = `${String(authStore.orgId || "")}:${userId}`;
|
||||
|
||||
if (isG3soft.value) {
|
||||
const elevatedKey = `g3soft:${principalKey}`
|
||||
if (loadedPrincipalKey.value === elevatedKey) return
|
||||
loadingPromise = null
|
||||
loadingPrincipalKey = ''
|
||||
const elevatedKey = `g3soft:${principalKey}`;
|
||||
if (loadedPrincipalKey.value === elevatedKey) return;
|
||||
loadingPromise = null;
|
||||
loadingPrincipalKey = "";
|
||||
|
||||
const requestVersion = ++loadVersion
|
||||
const request = loadDataApi<Module[]>('s_module', 'b_canuse = 1', 'b_id ASC')
|
||||
const requestVersion = ++loadVersion;
|
||||
const request = loadDataApi<Module[]>("s_module", "b_canuse = 1", "b_id ASC")
|
||||
.then((res) => {
|
||||
if (requestVersion !== loadVersion) return
|
||||
modules.value = res.data || []
|
||||
grantedPageIds.value = []
|
||||
moduleCodes.value = []
|
||||
powerCodes.value = []
|
||||
loadedPrincipalKey.value = elevatedKey
|
||||
if (requestVersion !== loadVersion) return;
|
||||
modules.value = res.data || [];
|
||||
grantedPageIds.value = [];
|
||||
moduleCodes.value = [];
|
||||
powerCodes.value = [];
|
||||
loadedPrincipalKey.value = elevatedKey;
|
||||
})
|
||||
.finally(() => {
|
||||
if (requestVersion !== loadVersion) return
|
||||
loadingPromise = null
|
||||
loadingPrincipalKey = ''
|
||||
})
|
||||
loadingPromise = request
|
||||
return request
|
||||
if (requestVersion !== loadVersion) return;
|
||||
loadingPromise = null;
|
||||
loadingPrincipalKey = "";
|
||||
});
|
||||
loadingPromise = request;
|
||||
return request;
|
||||
}
|
||||
|
||||
if (!/^\d+$/.test(userId)) throw new Error('登录用户 ID 无效,请重新登录')
|
||||
if (loadedPrincipalKey.value === principalKey) return
|
||||
if (loadingPromise && loadingPrincipalKey === principalKey) return loadingPromise
|
||||
if (!/^\d+$/.test(userId)) throw new Error("登录用户 ID 无效,请重新登录");
|
||||
if (loadedPrincipalKey.value === principalKey) return;
|
||||
if (loadingPromise && loadingPrincipalKey === principalKey) return loadingPromise;
|
||||
|
||||
const requestVersion = ++loadVersion
|
||||
loadingPrincipalKey = principalKey
|
||||
const requestVersion = ++loadVersion;
|
||||
loadingPrincipalKey = principalKey;
|
||||
const request = Promise.all([
|
||||
loadDataApi<Module[]>('s_module', 'b_canuse = 1', 'b_id ASC'),
|
||||
loadDataApi<UserModule[]>('b_user_module', `b_user_id = ${userId}`, 'b_id ASC'),
|
||||
loadDataApi<UserModule[]>('b_user_power', `b_user_id = ${userId}`, 'b_id ASC'),
|
||||
loadDataApi<ModulePower[]>('s_module_power', 'b_canuse = 1', 'b_id ASC'),
|
||||
loadDataApi<Module[]>("s_module", "b_canuse = 1", "b_id ASC"),
|
||||
loadDataApi<UserModule[]>("b_user_module", `b_user_id = ${userId}`, "b_id ASC"),
|
||||
loadDataApi<UserModule[]>("b_user_power", `b_user_id = ${userId}`, "b_id ASC"),
|
||||
loadDataApi<ModulePower[]>("s_module_power", "b_canuse = 1", "b_id ASC"),
|
||||
])
|
||||
.then(([moduleResponse, userModules, userPowers, powers]) => {
|
||||
if (requestVersion !== loadVersion) return
|
||||
const activeModules = moduleResponse.data || []
|
||||
const mById = new Map(activeModules.map((m) => [String(m.b_id), m]))
|
||||
const pById = new Map(powers.data.map((p) => [String(p.b_id), p]))
|
||||
const pageIds = userModules.data.map((item) => String(item.b_module_id || '')).filter(Boolean)
|
||||
modules.value = activeModules
|
||||
grantedPageIds.value = pageIds
|
||||
if (requestVersion !== loadVersion) return;
|
||||
const activeModules = moduleResponse.data || [];
|
||||
const mById = new Map(activeModules.map((m) => [String(m.b_id), m]));
|
||||
const pById = new Map(powers.data.map((p) => [String(p.b_id), p]));
|
||||
const pageIds = userModules.data
|
||||
.map((item) => String(item.b_module_id || ""))
|
||||
.filter(Boolean);
|
||||
modules.value = activeModules;
|
||||
grantedPageIds.value = pageIds;
|
||||
moduleCodes.value = userModules.data
|
||||
.map((item) => mById.get(String(item.b_module_id))?.b_code)
|
||||
.filter(Boolean) as string[]
|
||||
.filter(Boolean) as string[];
|
||||
powerCodes.value = userPowers.data
|
||||
.map((item) => pById.get(String(item.b_power_id)))
|
||||
.filter((p): p is ModulePower => Boolean(p))
|
||||
.map((power) => `${String(power.b_module_id)}.${power.b_code}`)
|
||||
loadedPrincipalKey.value = principalKey
|
||||
.map((power) => `${String(power.b_module_id)}.${power.b_code}`);
|
||||
loadedPrincipalKey.value = principalKey;
|
||||
})
|
||||
.finally(() => {
|
||||
if (requestVersion !== loadVersion) return
|
||||
loadingPromise = null
|
||||
loadingPrincipalKey = ''
|
||||
})
|
||||
loadingPromise = request
|
||||
return request
|
||||
if (requestVersion !== loadVersion) return;
|
||||
loadingPromise = null;
|
||||
loadingPrincipalKey = "";
|
||||
});
|
||||
loadingPromise = request;
|
||||
return request;
|
||||
}
|
||||
|
||||
function resolvePageId(code: string): string {
|
||||
let module = moduleByCode.value.get(String(code || ''))
|
||||
const visited = new Set<string>()
|
||||
let module = moduleByCode.value.get(String(code || ""));
|
||||
const visited = new Set<string>();
|
||||
while (module) {
|
||||
const moduleId = String(module.b_id || '')
|
||||
if (!moduleId || visited.has(moduleId)) return ''
|
||||
visited.add(moduleId)
|
||||
if (module.b_module_type === 'page') return moduleId
|
||||
const parentId = String(module.b_parent_id || '')
|
||||
module = parentId ? moduleById.value.get(parentId) : undefined
|
||||
const moduleId = String(module.b_id || "");
|
||||
if (!moduleId || visited.has(moduleId)) return "";
|
||||
visited.add(moduleId);
|
||||
if (module.b_module_type === "page") return moduleId;
|
||||
const parentId = String(module.b_parent_id || "");
|
||||
module = parentId ? moduleById.value.get(parentId) : undefined;
|
||||
}
|
||||
return ''
|
||||
return "";
|
||||
}
|
||||
|
||||
function canAccess(moduleCode?: string): boolean {
|
||||
if (isG3soft.value || !moduleCode) return true
|
||||
const module = moduleByCode.value.get(String(moduleCode))
|
||||
if (!module) return false
|
||||
const moduleId = String(module.b_id || '')
|
||||
const pageId = resolvePageId(moduleCode)
|
||||
return grantedPageSet.value.has(moduleId) || (!!pageId && grantedPageSet.value.has(pageId))
|
||||
if (isG3soft.value || !moduleCode) return true;
|
||||
const module = moduleByCode.value.get(String(moduleCode));
|
||||
if (!module) return false;
|
||||
const moduleId = String(module.b_id || "");
|
||||
const pageId = resolvePageId(moduleCode);
|
||||
return grantedPageSet.value.has(moduleId) || (!!pageId && grantedPageSet.value.has(pageId));
|
||||
}
|
||||
|
||||
function canPower(scopeCode?: string, powerCode?: string): boolean {
|
||||
if (isG3soft.value) return true
|
||||
const module = moduleByCode.value.get(String(scopeCode || ''))
|
||||
if (!module || !canAccess(scopeCode)) return false
|
||||
const moduleId = String(module.b_id || '')
|
||||
const pageId = resolvePageId(scopeCode || '')
|
||||
if (isG3soft.value) return true;
|
||||
const module = moduleByCode.value.get(String(scopeCode || ""));
|
||||
if (!module || !canAccess(scopeCode)) return false;
|
||||
const moduleId = String(module.b_id || "");
|
||||
const pageId = resolvePageId(scopeCode || "");
|
||||
return (
|
||||
powerSet.value.has(`${moduleId}.${powerCode}`) ||
|
||||
(!!pageId && powerSet.value.has(`${pageId}.${powerCode}`))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function clear() {
|
||||
loadVersion++
|
||||
loadingPromise = null
|
||||
loadingPrincipalKey = ''
|
||||
loadedPrincipalKey.value = ''
|
||||
modules.value = []
|
||||
grantedPageIds.value = []
|
||||
moduleCodes.value = []
|
||||
powerCodes.value = []
|
||||
loadVersion++;
|
||||
loadingPromise = null;
|
||||
loadingPrincipalKey = "";
|
||||
loadedPrincipalKey.value = "";
|
||||
modules.value = [];
|
||||
grantedPageIds.value = [];
|
||||
moduleCodes.value = [];
|
||||
powerCodes.value = [];
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [authStore.orgId, authStore.user?.id, authStore.user?.account, authStore.token],
|
||||
clear,
|
||||
)
|
||||
);
|
||||
|
||||
return {
|
||||
load,
|
||||
@@ -174,5 +178,5 @@ export const usePermissionStore = defineStore('permissions', () => {
|
||||
moduleCodes,
|
||||
powerCodes,
|
||||
isG3soft,
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
Reference in new issue
Block a user