mirror of
https://github.com/un-pany/v3-admin-vite.git
synced 2025-04-20 10:59:21 +08:00
docs: 统一注释风格 (允许顶层变量采用 /** 内层变量采用默认的 //)
This commit is contained in:
parent
0b517855b6
commit
23ab6b7ab5
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
:root {
|
||||
/*color*/
|
||||
/* color */
|
||||
--vxe-font-color: var(--el-text-color-regular);
|
||||
--vxe-primary-color: var(--el-color-primary);
|
||||
--vxe-success-color: var(--el-color-success);
|
||||
@ -34,16 +34,16 @@
|
||||
--vxe-warning-disabled-color: var(--el-color-warning-light-5);
|
||||
--vxe-danger-disabled-color: var(--el-color-danger-light-5);
|
||||
|
||||
/*input/radio/checkbox*/
|
||||
/* input/radio/checkbox */
|
||||
--vxe-input-border-color: var(--el-border-color);
|
||||
--vxe-input-disabled-color: var(--el-text-color-disabled);
|
||||
--vxe-input-disabled-background-color: var(--el-fill-color-light);
|
||||
--vxe-input-placeholder-color: var(--el-text-color-placeholder);
|
||||
|
||||
/*popup*/
|
||||
/* popup */
|
||||
--vxe-table-popup-border-color: var(--el-border-color);
|
||||
|
||||
/*table*/
|
||||
/* table */
|
||||
--vxe-table-header-font-color: var(--el-text-color-regular);
|
||||
--vxe-table-footer-font-color: var(--el-text-color-regular);
|
||||
--vxe-table-border-color: var(--el-border-color-lighter);
|
||||
@ -57,41 +57,41 @@
|
||||
|
||||
--vxe-table-checkbox-range-background-color: var(--el-fill-color-light);
|
||||
|
||||
/*menu*/
|
||||
/* menu */
|
||||
--vxe-table-menu-background-color: var(--el-bg-color-overlay);
|
||||
|
||||
/*loading*/
|
||||
/* loading */
|
||||
--vxe-loading-color: var(--el-color-primary);
|
||||
--vxe-loading-background-color: var(--el-mask-color);
|
||||
|
||||
/*validate*/
|
||||
/* validate */
|
||||
--vxe-table-validate-error-color: var(--el-color-danger);
|
||||
|
||||
/*toolbar*/
|
||||
/* toolbar */
|
||||
--vxe-toolbar-background-color: var(--el-bg-color);
|
||||
--vxe-toolbar-custom-active-background-color: var(--el-bg-color-overlay);
|
||||
--vxe-toolbar-panel-background-color: var(--el-bg-color-overlay);
|
||||
|
||||
/*pager*/
|
||||
/* pager */
|
||||
--vxe-pager-background-color: var(--el-bg-color);
|
||||
|
||||
/*modal*/
|
||||
/* modal */
|
||||
--vxe-modal-header-background-color: var(--el-bg-color);
|
||||
--vxe-modal-body-background-color: var(--el-bg-color);
|
||||
--vxe-modal-border-color: var(--el-border-color);
|
||||
|
||||
/*button*/
|
||||
/* button */
|
||||
--vxe-button-default-background-color: var(--el-bg-color-overlay);
|
||||
|
||||
/*input*/
|
||||
/* input */
|
||||
--vxe-input-background-color: var(--el-fill-color-blank);
|
||||
--vxe-input-panel-background-color: var(--el-fill-color-blank);
|
||||
|
||||
/*form*/
|
||||
/* form */
|
||||
--vxe-form-background-color: var(--el-bg-color);
|
||||
--vxe-form-validate-error-color: var(--el-color-danger);
|
||||
|
||||
/*select*/
|
||||
/* select */
|
||||
--vxe-select-option-hover-background-color: var(--el-bg-color-overlay);
|
||||
--vxe-select-panel-background-color: var(--el-bg-color);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ const appStore = useAppStore()
|
||||
const isMobile = computed(() => appStore.device === DeviceEnum.Mobile)
|
||||
const isDesktop = computed(() => appStore.device === DeviceEnum.Desktop)
|
||||
|
||||
/** 设备类型 Composable */
|
||||
export function useDevice() {
|
||||
return { isMobile, isDesktop }
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ interface FetchSelectProps {
|
||||
api: () => Promise<ApiData>
|
||||
}
|
||||
|
||||
/** 下拉选择器 Composable */
|
||||
export function useFetchSelect(props: FetchSelectProps) {
|
||||
const { api } = props
|
||||
|
||||
@ -24,7 +25,7 @@ export function useFetchSelect(props: FetchSelectProps) {
|
||||
const options = ref<SelectOption[]>([])
|
||||
const value = ref<OptionValue>("")
|
||||
|
||||
/** 调用接口获取数据 */
|
||||
// 调用接口获取数据
|
||||
const loadData = () => {
|
||||
loading.value = true
|
||||
options.value = []
|
||||
|
@ -18,7 +18,8 @@ const DEFAULT_OPTIONS = {
|
||||
}
|
||||
|
||||
/**
|
||||
* 传入一个函数 fn,在它执行周期内,加上「全屏」Loading
|
||||
* @name 全屏加载 Composable
|
||||
* @description 传入一个函数 fn,在它执行周期内,加上「全屏」Loading
|
||||
* @param fn 要执行的函数
|
||||
* @param options LoadingOptions
|
||||
* @returns 返回一个新的函数,该函数返回一个 Promise
|
||||
|
@ -11,6 +11,7 @@ function setLayoutMode(mode: LayoutModeEnum) {
|
||||
settingsStore.layoutMode = mode
|
||||
}
|
||||
|
||||
/** 布局模式 Composable */
|
||||
export function useLayoutMode() {
|
||||
return { isLeft, isTop, isLeftTop, setLayoutMode }
|
||||
}
|
||||
|
@ -17,14 +17,15 @@ const DEFAULT_PAGINATION_DATA = {
|
||||
layout: "total, sizes, prev, pager, next, jumper"
|
||||
}
|
||||
|
||||
/** 分页 Composable */
|
||||
export function usePagination(initPaginationData: PaginationData = {}) {
|
||||
/** 合并分页参数 */
|
||||
// 合并分页参数
|
||||
const paginationData = reactive({ ...DEFAULT_PAGINATION_DATA, ...initPaginationData })
|
||||
/** 改变当前页码 */
|
||||
// 改变当前页码
|
||||
const handleCurrentChange = (value: number) => {
|
||||
paginationData.currentPage = value
|
||||
}
|
||||
/** 改变页面大小 */
|
||||
// 改变每页显示条数
|
||||
const handleSizeChange = (value: number) => {
|
||||
paginationData.pageSize = value
|
||||
}
|
||||
|
@ -17,12 +17,16 @@ export function setRouteChange(to: RouteLocationNormalized) {
|
||||
latestRoute = to
|
||||
}
|
||||
|
||||
/** 单独监听路由会浪费渲染性能,使用发布订阅模式去进行分发管理 */
|
||||
/**
|
||||
* 订阅路由变化 Composable
|
||||
* 1. 单独用 watch 监听路由会浪费渲染性能
|
||||
* 2. 可优先选择使用该发布订阅模式去进行分发管理
|
||||
*/
|
||||
export function useRouteListener() {
|
||||
// 回调函数集合
|
||||
const callbackList: Callback[] = []
|
||||
|
||||
/** 监听路由变化(可以选择立即执行) */
|
||||
// 监听路由变化(可以选择立即执行)
|
||||
const listenerRouteChange = (callback: Callback, immediate = false) => {
|
||||
// 缓存回调函数
|
||||
callbackList.push(callback)
|
||||
@ -32,12 +36,12 @@ export function useRouteListener() {
|
||||
immediate && latestRoute && callback(latestRoute)
|
||||
}
|
||||
|
||||
/** 移除路由变化事件监听器 */
|
||||
// 移除路由变化事件监听器
|
||||
const removeRouteListener = (callback: Callback) => {
|
||||
emitter.off(key, callback as Handler)
|
||||
}
|
||||
|
||||
/** 组件销毁前移除监听器 */
|
||||
// 组件销毁前移除监听器
|
||||
onBeforeUnmount(() => {
|
||||
for (let i = 0; i < callbackList.length; i++) {
|
||||
removeRouteListener(callbackList[i])
|
||||
|
@ -18,6 +18,7 @@ watch(dynamicTitle, (value, oldValue) => {
|
||||
}
|
||||
})
|
||||
|
||||
/** 标题 Composable */
|
||||
export function useTitle() {
|
||||
return { setTitle }
|
||||
}
|
||||
|
@ -34,25 +34,25 @@ const DEFAULT_CONFIG = {
|
||||
const bodyEl = ref<HTMLElement>(document.body)
|
||||
|
||||
/**
|
||||
* 创建水印
|
||||
* 水印 Composable
|
||||
* 1. 可以选择传入挂载水印的容器元素,默认是 body
|
||||
* 2. 做了水印防御,能有效防御别人打开控制台删除或隐藏水印
|
||||
*/
|
||||
export function useWatermark(parentEl: Ref<HTMLElement | null> = bodyEl) {
|
||||
/** 备份文本 */
|
||||
// 备份文本
|
||||
let backupText: string
|
||||
/** 最终配置 */
|
||||
// 最终配置
|
||||
let mergeConfig: DefaultConfig
|
||||
/** 水印元素 */
|
||||
// 水印元素
|
||||
let watermarkEl: HTMLElement | null = null
|
||||
/** 观察器 */
|
||||
// 观察器
|
||||
const observer: Observer = {
|
||||
watermarkElMutationObserver: undefined,
|
||||
parentElMutationObserver: undefined,
|
||||
parentElResizeObserver: undefined
|
||||
}
|
||||
|
||||
/** 设置水印 */
|
||||
// 设置水印
|
||||
const setWatermark = (text: string, config: Partial<DefaultConfig> = {}) => {
|
||||
if (!parentEl.value) return console.warn("请在 DOM 挂载完成后再调用 setWatermark 方法设置水印")
|
||||
// 备份文本
|
||||
@ -65,7 +65,7 @@ export function useWatermark(parentEl: Ref<HTMLElement | null> = bodyEl) {
|
||||
addElListener(parentEl.value)
|
||||
}
|
||||
|
||||
/** 创建水印元素 */
|
||||
// 创建水印元素
|
||||
const createWatermarkEl = () => {
|
||||
const isBody = parentEl.value!.tagName.toLowerCase() === bodyEl.value.tagName.toLowerCase()
|
||||
const watermarkElPosition = isBody ? "fixed" : "absolute"
|
||||
@ -84,7 +84,7 @@ export function useWatermark(parentEl: Ref<HTMLElement | null> = bodyEl) {
|
||||
parentEl.value!.appendChild(watermarkEl)
|
||||
}
|
||||
|
||||
/** 更新水印元素 */
|
||||
// 更新水印元素
|
||||
const updateWatermarkEl = (
|
||||
options: Partial<{
|
||||
width: number
|
||||
@ -97,7 +97,7 @@ export function useWatermark(parentEl: Ref<HTMLElement | null> = bodyEl) {
|
||||
options.height && (watermarkEl.style.height = `${options.height}px`)
|
||||
}
|
||||
|
||||
/** 创建 base64 图片 */
|
||||
// 创建 base64 图片
|
||||
const createBase64 = () => {
|
||||
const { color, opacity, size, family, angle, width, height } = mergeConfig
|
||||
const canvasEl = document.createElement("canvas")
|
||||
@ -114,7 +114,7 @@ export function useWatermark(parentEl: Ref<HTMLElement | null> = bodyEl) {
|
||||
return canvasEl.toDataURL()
|
||||
}
|
||||
|
||||
/** 清除水印 */
|
||||
// 清除水印
|
||||
const clearWatermark = () => {
|
||||
if (!parentEl.value || !watermarkEl) return
|
||||
// 移除对水印元素和容器元素的监听
|
||||
@ -130,14 +130,14 @@ export function useWatermark(parentEl: Ref<HTMLElement | null> = bodyEl) {
|
||||
}
|
||||
}
|
||||
|
||||
/** 刷新水印(防御时调用) */
|
||||
// 刷新水印(防御时调用)
|
||||
const updateWatermark = debounce(() => {
|
||||
clearWatermark()
|
||||
createWatermarkEl()
|
||||
addElListener(parentEl.value!)
|
||||
}, 100)
|
||||
|
||||
/** 监听水印元素和容器元素的变化(DOM 变化 & DOM 大小变化) */
|
||||
// 监听水印元素和容器元素的变化(DOM 变化 & DOM 大小变化)
|
||||
const addElListener = (targetNode: HTMLElement) => {
|
||||
// 判断是否开启防御
|
||||
if (mergeConfig.defense) {
|
||||
@ -157,7 +157,7 @@ export function useWatermark(parentEl: Ref<HTMLElement | null> = bodyEl) {
|
||||
}
|
||||
}
|
||||
|
||||
/** 移除对水印元素和容器元素的监听,传参可指定要移除哪个监听,不传默认移除全部监听 */
|
||||
// 移除对水印元素和容器元素的监听,传参可指定要移除哪个监听,不传默认移除全部监听
|
||||
const removeListener = (kind: "mutation" | "resize" | "all" = "all") => {
|
||||
// 移除 mutation 监听
|
||||
if (kind === "mutation" || kind === "all") {
|
||||
@ -173,7 +173,7 @@ export function useWatermark(parentEl: Ref<HTMLElement | null> = bodyEl) {
|
||||
}
|
||||
}
|
||||
|
||||
/** 监听 DOM 变化 */
|
||||
// 监听 DOM 变化
|
||||
const addMutationListener = (targetNode: HTMLElement) => {
|
||||
// 当观察到变动时执行的回调
|
||||
const mutationCallback = debounce((mutationList: MutationRecord[]) => {
|
||||
@ -212,7 +212,7 @@ export function useWatermark(parentEl: Ref<HTMLElement | null> = bodyEl) {
|
||||
})
|
||||
}
|
||||
|
||||
/** 监听 DOM 大小变化 */
|
||||
// 监听 DOM 大小变化
|
||||
const addResizeListener = (targetNode: HTMLElement) => {
|
||||
// 当 targetNode 元素大小变化时去更新整个水印的大小
|
||||
const resizeCallback = debounce(() => {
|
||||
|
@ -33,7 +33,7 @@ function handleLink(item: RouteLocationMatched) {
|
||||
router.push(pathCompile(path))
|
||||
}
|
||||
|
||||
/** 监听路由变化,更新面包屑导航信息 */
|
||||
// 监听路由变化,更新面包屑导航信息
|
||||
listenerRouteChange((route) => {
|
||||
if (route.path.startsWith("/redirect/")) return
|
||||
getBreadcrumb()
|
||||
|
@ -44,11 +44,11 @@ function wheelScroll({ deltaY }: WheelEvent) {
|
||||
|
||||
/** 获取可能需要的宽度 */
|
||||
function getWidth() {
|
||||
/** 可滚动内容的长度 */
|
||||
// 可滚动内容的长度
|
||||
const scrollbarContentRefWidth = scrollbarContentRef.value!.clientWidth
|
||||
/** 滚动可视区宽度 */
|
||||
// 滚动可视区宽度
|
||||
const scrollbarRefWidth = scrollbarRef.value!.wrapRef!.clientWidth
|
||||
/** 最后剩余可滚动的宽度 */
|
||||
// 最后剩余可滚动的宽度
|
||||
const lastDistance = scrollbarContentRefWidth - scrollbarRefWidth - currentScrollLeft
|
||||
|
||||
return { scrollbarContentRefWidth, scrollbarRefWidth, lastDistance }
|
||||
@ -96,7 +96,7 @@ function moveTo() {
|
||||
}
|
||||
}
|
||||
|
||||
/** 监听路由变化,移动到目标位置 */
|
||||
// 监听路由变化,移动到目标位置
|
||||
listenerRouteChange(() => {
|
||||
nextTick(moveTo)
|
||||
})
|
||||
|
@ -6,18 +6,21 @@ import { onBeforeMount, onBeforeUnmount, onMounted } from "vue"
|
||||
/** 参考 Bootstrap 的响应式设计将最大移动端宽度设置为 992 */
|
||||
const MAX_MOBILE_WIDTH = 992
|
||||
|
||||
/** 根据浏览器宽度变化,变换 Layout 布局 */
|
||||
/**
|
||||
* @name 浏览器宽度变化 Composable
|
||||
* @description 根据浏览器宽度变化,变换 Layout 布局
|
||||
*/
|
||||
export default () => {
|
||||
const appStore = useAppStore()
|
||||
const { listenerRouteChange } = useRouteListener()
|
||||
|
||||
/** 用于判断当前设备是否为移动端 */
|
||||
// 用于判断当前设备是否为移动端
|
||||
const _isMobile = () => {
|
||||
const rect = document.body.getBoundingClientRect()
|
||||
return rect.width - 1 < MAX_MOBILE_WIDTH
|
||||
}
|
||||
|
||||
/** 用于处理窗口大小变化事件 */
|
||||
// 用于处理窗口大小变化事件
|
||||
const _resizeHandler = () => {
|
||||
if (!document.hidden) {
|
||||
const isMobile = _isMobile()
|
||||
@ -25,19 +28,20 @@ export default () => {
|
||||
isMobile && appStore.closeSidebar(true)
|
||||
}
|
||||
}
|
||||
/** 监听路由变化,根据设备类型调整布局 */
|
||||
|
||||
// 监听路由变化,根据设备类型调整布局
|
||||
listenerRouteChange(() => {
|
||||
if (appStore.device === DeviceEnum.Mobile && appStore.sidebar.opened) {
|
||||
appStore.closeSidebar(false)
|
||||
}
|
||||
})
|
||||
|
||||
/** 在组件挂载前添加窗口大小变化事件监听器 */
|
||||
// 在组件挂载前添加窗口大小变化事件监听器
|
||||
onBeforeMount(() => {
|
||||
window.addEventListener("resize", _resizeHandler)
|
||||
})
|
||||
|
||||
/** 在组件挂载后根据窗口大小判断设备类型并调整布局 */
|
||||
// 在组件挂载后根据窗口大小判断设备类型并调整布局
|
||||
onMounted(() => {
|
||||
if (_isMobile()) {
|
||||
appStore.toggleDevice(DeviceEnum.Mobile)
|
||||
@ -45,7 +49,7 @@ export default () => {
|
||||
}
|
||||
})
|
||||
|
||||
/** 在组件卸载前移除窗口大小变化事件监听器 */
|
||||
// 在组件卸载前移除窗口大小变化事件监听器
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener("resize", _resizeHandler)
|
||||
})
|
||||
|
@ -1,14 +1,16 @@
|
||||
import { ref } from "vue"
|
||||
|
||||
/** 焦点 Composable */
|
||||
export function useFocus() {
|
||||
/** 是否有焦点 */
|
||||
// 是否有焦点
|
||||
const isFocus = ref<boolean>(false)
|
||||
|
||||
/** 失去焦点 */
|
||||
// 失去焦点
|
||||
const handleBlur = () => {
|
||||
isFocus.value = false
|
||||
}
|
||||
/** 获取焦点 */
|
||||
|
||||
// 获取焦点
|
||||
const handleFocus = () => {
|
||||
isFocus.value = true
|
||||
}
|
||||
|
@ -15,12 +15,12 @@ function handleSidebarStatus(opened: boolean) {
|
||||
}
|
||||
|
||||
export const useAppStore = defineStore("app", () => {
|
||||
/** 侧边栏状态 */
|
||||
// 侧边栏状态
|
||||
const sidebar: Sidebar = reactive({
|
||||
opened: getSidebarStatus() !== SIDEBAR_CLOSED,
|
||||
withoutAnimation: false
|
||||
})
|
||||
/** 设备类型 */
|
||||
// 设备类型
|
||||
const device = ref<DeviceEnum>(DeviceEnum.Desktop)
|
||||
|
||||
// 监听侧边栏 opened 状态
|
||||
@ -29,17 +29,17 @@ export const useAppStore = defineStore("app", () => {
|
||||
opened => handleSidebarStatus(opened)
|
||||
)
|
||||
|
||||
/** 切换侧边栏 */
|
||||
// 切换侧边栏
|
||||
const toggleSidebar = (withoutAnimation: boolean) => {
|
||||
sidebar.opened = !sidebar.opened
|
||||
sidebar.withoutAnimation = withoutAnimation
|
||||
}
|
||||
/** 关闭侧边栏 */
|
||||
// 关闭侧边栏
|
||||
const closeSidebar = (withoutAnimation: boolean) => {
|
||||
sidebar.opened = false
|
||||
sidebar.withoutAnimation = withoutAnimation
|
||||
}
|
||||
/** 切换设备类型 */
|
||||
// 切换设备类型
|
||||
const toggleDevice = (value: DeviceEnum) => {
|
||||
device.value = value
|
||||
}
|
||||
@ -48,8 +48,8 @@ export const useAppStore = defineStore("app", () => {
|
||||
})
|
||||
|
||||
/**
|
||||
* 在 SPA 应用中可用于在 pinia 实例被激活前使用 store
|
||||
* 在 SSR 应用中可用于在 setup 外使用 store
|
||||
* @description 在 SPA 应用中可用于在 pinia 实例被激活前使用 store
|
||||
* @description 在 SSR 应用中可用于在 setup 外使用 store
|
||||
*/
|
||||
export function useAppStoreOutside() {
|
||||
return useAppStore(pinia)
|
||||
|
@ -26,18 +26,18 @@ function filterDynamicRoutes(routes: RouteRecordRaw[], roles: string[]) {
|
||||
}
|
||||
|
||||
export const usePermissionStore = defineStore("permission", () => {
|
||||
/** 可访问的路由 */
|
||||
// 可访问的路由
|
||||
const routes = ref<RouteRecordRaw[]>([])
|
||||
/** 有访问权限的动态路由 */
|
||||
// 有访问权限的动态路由
|
||||
const addRoutes = ref<RouteRecordRaw[]>([])
|
||||
|
||||
/** 根据角色生成可访问的 Routes(可访问的路由 = 常驻路由 + 有访问权限的动态路由) */
|
||||
// 根据角色生成可访问的 Routes(可访问的路由 = 常驻路由 + 有访问权限的动态路由)
|
||||
const setRoutes = (roles: string[]) => {
|
||||
const accessedRoutes = filterDynamicRoutes(dynamicRoutes, roles)
|
||||
_set(accessedRoutes)
|
||||
}
|
||||
|
||||
/** 所有路由 = 所有常驻路由 + 所有动态路由 */
|
||||
// 所有路由 = 所有常驻路由 + 所有动态路由
|
||||
const setAllRoutes = () => {
|
||||
_set(dynamicRoutes)
|
||||
}
|
||||
@ -51,8 +51,8 @@ export const usePermissionStore = defineStore("permission", () => {
|
||||
})
|
||||
|
||||
/**
|
||||
* 在 SPA 应用中可用于在 pinia 实例被激活前使用 store
|
||||
* 在 SSR 应用中可用于在 setup 外使用 store
|
||||
* @description 在 SPA 应用中可用于在 pinia 实例被激活前使用 store
|
||||
* @description 在 SSR 应用中可用于在 setup 外使用 store
|
||||
*/
|
||||
export function usePermissionStoreOutside() {
|
||||
return usePermissionStore(pinia)
|
||||
|
@ -14,7 +14,7 @@ type SettingsStore = {
|
||||
type SettingsStoreKey = keyof SettingsStore
|
||||
|
||||
export const useSettingsStore = defineStore("settings", () => {
|
||||
/** 状态对象 */
|
||||
// 状态对象
|
||||
const state = {} as SettingsStore
|
||||
// 遍历 layoutSettings 对象的键值对
|
||||
for (const [key, value] of Object.entries(layoutSettings)) {
|
||||
@ -29,7 +29,7 @@ export const useSettingsStore = defineStore("settings", () => {
|
||||
setConfigLayout(settings)
|
||||
})
|
||||
}
|
||||
/** 获取要缓存的数据:将 state 对象转化为 settings 对象 */
|
||||
// 获取要缓存的数据:将 state 对象转化为 settings 对象
|
||||
const _getCacheData = () => {
|
||||
const settings = {} as LayoutSettings
|
||||
for (const [key, value] of Object.entries(state)) {
|
||||
@ -43,8 +43,8 @@ export const useSettingsStore = defineStore("settings", () => {
|
||||
})
|
||||
|
||||
/**
|
||||
* 在 SPA 应用中可用于在 pinia 实例被激活前使用 store
|
||||
* 在 SSR 应用中可用于在 setup 外使用 store
|
||||
* @description 在 SPA 应用中可用于在 pinia 实例被激活前使用 store
|
||||
* @description 在 SSR 应用中可用于在 setup 外使用 store
|
||||
*/
|
||||
export function useSettingsStoreOutside() {
|
||||
return useSettingsStore(pinia)
|
||||
|
@ -96,8 +96,8 @@ export const useTagsViewStore = defineStore("tags-view", () => {
|
||||
})
|
||||
|
||||
/**
|
||||
* 在 SPA 应用中可用于在 pinia 实例被激活前使用 store
|
||||
* 在 SSR 应用中可用于在 setup 外使用 store
|
||||
* @description 在 SPA 应用中可用于在 pinia 实例被激活前使用 store
|
||||
* @description 在 SSR 应用中可用于在 setup 外使用 store
|
||||
*/
|
||||
export function useTagsViewStoreOutside() {
|
||||
return useTagsViewStore(pinia)
|
||||
|
@ -17,20 +17,20 @@ export const useUserStore = defineStore("user", () => {
|
||||
const tagsViewStore = useTagsViewStore()
|
||||
const settingsStore = useSettingsStore()
|
||||
|
||||
/** 登录 */
|
||||
// 登录
|
||||
const login = async ({ username, password, code }: LoginRequestData) => {
|
||||
const { data } = await loginApi({ username, password, code })
|
||||
setToken(data.token)
|
||||
token.value = data.token
|
||||
}
|
||||
/** 获取用户详情 */
|
||||
// 获取用户详情
|
||||
const getInfo = async () => {
|
||||
const { data } = await getUserInfoApi()
|
||||
username.value = data.username
|
||||
// 验证返回的 roles 是否为一个非空数组,否则塞入一个没有任何作用的默认角色,防止路由守卫逻辑进入无限循环
|
||||
roles.value = data.roles?.length > 0 ? data.roles : routeSettings.defaultRoles
|
||||
}
|
||||
/** 模拟角色变化 */
|
||||
// 模拟角色变化
|
||||
const changeRoles = async (role: string) => {
|
||||
const newToken = `token-${role}`
|
||||
token.value = newToken
|
||||
@ -38,7 +38,7 @@ export const useUserStore = defineStore("user", () => {
|
||||
// 用刷新页面代替重新登录
|
||||
window.location.reload()
|
||||
}
|
||||
/** 登出 */
|
||||
// 登出
|
||||
const logout = () => {
|
||||
removeToken()
|
||||
token.value = ""
|
||||
@ -46,13 +46,13 @@ export const useUserStore = defineStore("user", () => {
|
||||
resetRouter()
|
||||
_resetTagsView()
|
||||
}
|
||||
/** 重置 Token */
|
||||
// 重置 Token
|
||||
const resetToken = () => {
|
||||
removeToken()
|
||||
token.value = ""
|
||||
roles.value = []
|
||||
}
|
||||
/** 重置 Visited Views 和 Cached Views */
|
||||
// 重置 Visited Views 和 Cached Views
|
||||
const _resetTagsView = () => {
|
||||
if (!settingsStore.cacheTagsView) {
|
||||
tagsViewStore.delAllVisitedViews()
|
||||
@ -64,8 +64,8 @@ export const useUserStore = defineStore("user", () => {
|
||||
})
|
||||
|
||||
/**
|
||||
* 在 SPA 应用中可用于在 pinia 实例被激活前使用 store
|
||||
* 在 SSR 应用中可用于在 setup 外使用 store
|
||||
* @description 在 SPA 应用中可用于在 pinia 实例被激活前使用 store
|
||||
* @description 在 SSR 应用中可用于在 setup 外使用 store
|
||||
*/
|
||||
export function useUserStoreOutside() {
|
||||
return useUserStore(pinia)
|
||||
|
@ -6,8 +6,8 @@ import { flatMultiLevelRoutes, history } from "./helper"
|
||||
const Layouts = () => import("@/layouts/index.vue")
|
||||
|
||||
/**
|
||||
* 常驻路由
|
||||
* 除了 redirect/403/404/login 等隐藏页面,其他页面建议设置 Name 属性
|
||||
* @name 常驻路由
|
||||
* @description 除了 redirect/403/404/login 等隐藏页面,其他页面建议设置 Name 属性
|
||||
*/
|
||||
export const constantRoutes: RouteRecordRaw[] = [
|
||||
{
|
||||
@ -252,9 +252,9 @@ export const constantRoutes: RouteRecordRaw[] = [
|
||||
]
|
||||
|
||||
/**
|
||||
* 动态路由
|
||||
* 用来放置有权限 (Roles 属性) 的路由
|
||||
* 必须带有 Name 属性
|
||||
* @name 动态路由
|
||||
* @description 用来放置有权限 (Roles 属性) 的路由
|
||||
* @description 必须带有 Name 属性
|
||||
*/
|
||||
export const dynamicRoutes: RouteRecordRaw[] = [
|
||||
{
|
||||
|
@ -1,6 +1,8 @@
|
||||
// https://www.typescriptlang.org/tsconfig
|
||||
// https://cn.vuejs.org/guide/typescript/overview#configuring-tsconfig-json
|
||||
// https://cn.vite.dev/guide/features#typescript-compiler-options
|
||||
/**
|
||||
* @link https://www.typescriptlang.org/tsconfig
|
||||
* @link https://cn.vuejs.org/guide/typescript/overview#configuring-tsconfig-json
|
||||
* @link https://cn.vite.dev/guide/features#typescript-compiler-options
|
||||
*/
|
||||
|
||||
{
|
||||
"compilerOptions": {
|
||||
|
32
types/vue-router.d.ts
vendored
32
types/vue-router.d.ts
vendored
@ -5,49 +5,49 @@ export {}
|
||||
declare module "vue-router" {
|
||||
interface RouteMeta {
|
||||
/**
|
||||
* 设置该路由在侧边栏和面包屑中展示的名字
|
||||
* @description 设置该路由在侧边栏和面包屑中展示的名字
|
||||
*/
|
||||
title?: string
|
||||
/**
|
||||
* 设置该路由的图标,记得将 svg 导入 @/assets/icons
|
||||
* @description 设置该路由的图标,记得将 svg 导入 @/assets/icons
|
||||
*/
|
||||
svgIcon?: string
|
||||
/**
|
||||
* 设置该路由的图标,直接使用 Element Plus 的 Icon(与 svgIcon 同时设置时,svgIcon 将优先生效)
|
||||
* @description 设置该路由的图标,直接使用 Element Plus 的 Icon(与 svgIcon 同时设置时,svgIcon 将优先生效)
|
||||
*/
|
||||
elIcon?: string
|
||||
/**
|
||||
* 默认 false,设置 true 的时候该路由不会在侧边栏出现
|
||||
* @description 默认 false,设置 true 的时候该路由不会在侧边栏出现
|
||||
*/
|
||||
hidden?: boolean
|
||||
/**
|
||||
* 设置能进入该路由的角色,支持多个角色叠加
|
||||
* @description 设置能进入该路由的角色,支持多个角色叠加
|
||||
*/
|
||||
roles?: string[]
|
||||
/**
|
||||
* 默认 true,如果设置为 false,则不会在面包屑中显示
|
||||
* @description 默认 true,如果设置为 false,则不会在面包屑中显示
|
||||
*/
|
||||
breadcrumb?: boolean
|
||||
/**
|
||||
* 默认 false,如果设置为 true,它则会固定在 tags-view 中
|
||||
* @description 默认 false,如果设置为 true,它则会固定在 tags-view 中
|
||||
*/
|
||||
affix?: boolean
|
||||
/**
|
||||
* 当一个路由下面的 children 声明的路由大于 1 个时,自动会变成嵌套的模式,
|
||||
* 只有一个时,会将那个子路由当做根路由显示在侧边栏,
|
||||
* 若想不管路由下面的 children 声明的个数都显示你的根路由,
|
||||
* 可以设置 alwaysShow: true,这样就会忽略之前定义的规则,一直显示根路由
|
||||
* @description 当一个路由下面的 children 声明的路由大于 1 个时,自动会变成嵌套的模式,
|
||||
* @description 只有一个时,会将那个子路由当做根路由显示在侧边栏,
|
||||
* @description 若想不管路由下面的 children 声明的个数都显示你的根路由,
|
||||
* @description 可以设置 alwaysShow: true,这样就会忽略之前定义的规则,一直显示根路由
|
||||
*/
|
||||
alwaysShow?: boolean
|
||||
/**
|
||||
* 示例: activeMenu: "/xxx/xxx",
|
||||
* 当设置了该属性进入路由时,则会高亮 activeMenu 属性对应的侧边栏。
|
||||
* 该属性适合使用在有 hidden: true 属性的路由上
|
||||
* @description 示例: activeMenu: "/xxx/xxx",
|
||||
* @description 当设置了该属性进入路由时,则会高亮 activeMenu 属性对应的侧边栏。
|
||||
* @description 该属性适合使用在有 hidden: true 属性的路由上
|
||||
*/
|
||||
activeMenu?: string
|
||||
/**
|
||||
* 是否缓存该路由页面
|
||||
* 默认为 false,为 true 时代表需要缓存,此时该路由和该页面都需要设置一致的 Name
|
||||
* @description 是否缓存该路由页面
|
||||
* @description 默认为 false,为 true 时代表需要缓存,此时该路由和该页面都需要设置一致的 Name
|
||||
*/
|
||||
keepAlive?: boolean
|
||||
}
|
||||
|
@ -54,9 +54,9 @@ export default defineConfig(({ mode }) => {
|
||||
rollupOptions: {
|
||||
output: {
|
||||
/**
|
||||
* 分块策略
|
||||
* 1. 注意这些包名必须存在,否则打包会报错
|
||||
* 2. 如果你不想自定义 chunk 分割策略,可以直接移除这段配置
|
||||
* @name 分块策略
|
||||
* @description 1. 注意这些包名必须存在,否则打包会报错
|
||||
* @description 2. 如果你不想自定义 chunk 分割策略,可以直接移除这段配置
|
||||
*/
|
||||
manualChunks: {
|
||||
vue: ["vue", "vue-router", "pinia"],
|
||||
|
Loading…
x
Reference in New Issue
Block a user