Merge branch 'main' into example

This commit is contained in:
Soybean 2025-03-12 23:25:14 +08:00
commit a5c9a19838
58 changed files with 2267 additions and 2505 deletions

3
.env
View File

@ -51,3 +51,6 @@ VITE_STORAGE_PREFIX=SOY_
# used to control whether the program automatically detects updates # used to control whether the program automatically detects updates
VITE_AUTOMATICALLY_DETECT_UPDATE=Y VITE_AUTOMATICALLY_DETECT_UPDATE=Y
# show proxy url log in terminal
VITE_PROXY_LOG=Y

View File

@ -1,6 +1,40 @@
# Changelog # Changelog
## [v1.3.12](https://github.com/soybeanjs/soybean-admin/compare/v1.3.11...v1.3.12) (2025-03-12)
###    🚀 Features
- **projects**:
- support loading page dark mode adaptation. &nbsp;-&nbsp; by @Azir-11 in https://github.com/soybeanjs/soybean-admin/issues/702 [<samp>(9b945)</samp>](https://github.com/soybeanjs/soybean-admin/commit/9b9455d9)
- tab support touch event &nbsp;-&nbsp; by @soybeanjs [<samp>(a03be)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a03becda)
- support proxy log in terminal &nbsp;-&nbsp; by @soybeanjs [<samp>(4cc14)</samp>](https://github.com/soybeanjs/soybean-admin/commit/4cc1487f)
- **projects): feat(projects**:
- TableColumnCheck title support VNode &nbsp;-&nbsp; by @soybeanjs in https://github.com/soybeanjs/soybean-admin/issues/716 [<samp>(a1a5c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a1a5c74c)
- **utils**:
- support replaceTab. &nbsp;-&nbsp; by @Azir-11 in https://github.com/soybeanjs/soybean-admin/issues/713 [<samp>(be608)</samp>](https://github.com/soybeanjs/soybean-admin/commit/be6080ba)
### &nbsp;&nbsp;&nbsp;🐞 Bug Fixes
- **projects**:
- hidden multi-language button in login page. fix #694 &nbsp;-&nbsp; by **Azir** in https://github.com/soybeanjs/soybean-admin/issues/694 [<samp>(54e7d)</samp>](https://github.com/soybeanjs/soybean-admin/commit/54e7d6d0)
- fix multiple calls to the login API when clicking quickly. fixed #697 &nbsp;-&nbsp; by @zsdycs in https://github.com/soybeanjs/soybean-admin/issues/698 and https://github.com/soybeanjs/soybean-admin/issues/697 [<samp>(86da7)</samp>](https://github.com/soybeanjs/soybean-admin/commit/86da767e)
- fix multiple calls to the login API when clicking quickly. fixed #697 " &nbsp;-&nbsp; by @soybeanjs in https://github.com/soybeanjs/soybean-admin/issues/698 and https://github.com/soybeanjs/soybean-admin/issues/697 [<samp>(15163)</samp>](https://github.com/soybeanjs/soybean-admin/commit/15163d70)
### &nbsp;&nbsp;&nbsp;🏡 Chore
- **deps**:
- update deps &nbsp;-&nbsp; by @soybeanjs [<samp>(132e1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/132e1012)
- update deps &nbsp;-&nbsp; by **Azir** [<samp>(52c33)</samp>](https://github.com/soybeanjs/soybean-admin/commit/52c336d7)
- update deps &nbsp;-&nbsp; by @soybeanjs [<samp>(b8112)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b8112613)
- **projects**:
- update unocss preset &nbsp;-&nbsp; by @Wangijun in https://github.com/soybeanjs/soybean-admin/issues/712 [<samp>(3e007)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3e0076d4)
### &nbsp;&nbsp;&nbsp;❤️ Contributors
[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)&nbsp;&nbsp;[![Azir-11](https://github.com/Azir-11.png?size=48)](https://github.com/Azir-11)&nbsp;&nbsp;[![Wangijun](https://github.com/Wangijun.png?size=48)](https://github.com/Wangijun)&nbsp;&nbsp;[![zsdycs](https://github.com/zsdycs.png?size=48)](https://github.com/zsdycs)&nbsp;&nbsp;
[Azir](mailto:2075125282@qq.com),&nbsp;
## [v1.3.11](https://github.com/soybeanjs/soybean-admin/compare/v1.3.10...v1.3.11) (2025-01-19) ## [v1.3.11](https://github.com/soybeanjs/soybean-admin/compare/v1.3.10...v1.3.11) (2025-01-19)
### &nbsp;&nbsp;&nbsp;🚀 Features ### &nbsp;&nbsp;&nbsp;🚀 Features

View File

@ -1,4 +1,6 @@
import type { ProxyOptions } from 'vite'; import type { HttpProxy, ProxyOptions } from 'vite';
import { bgRed, bgYellow, green, lightBlue } from 'kolorist';
import { consola } from 'consola';
import { createServiceConfig } from '../../src/utils/service'; import { createServiceConfig } from '../../src/utils/service';
/** /**
@ -12,23 +14,40 @@ export function createViteProxy(env: Env.ImportMeta, enable: boolean) {
if (!isEnableHttpProxy) return undefined; if (!isEnableHttpProxy) return undefined;
const isEnableProxyLog = env.VITE_PROXY_LOG === 'Y';
const { baseURL, proxyPattern, other } = createServiceConfig(env); const { baseURL, proxyPattern, other } = createServiceConfig(env);
const proxy: Record<string, ProxyOptions> = createProxyItem({ baseURL, proxyPattern }); const proxy: Record<string, ProxyOptions> = createProxyItem({ baseURL, proxyPattern }, isEnableProxyLog);
other.forEach(item => { other.forEach(item => {
Object.assign(proxy, createProxyItem(item)); Object.assign(proxy, createProxyItem(item, isEnableProxyLog));
}); });
return proxy; return proxy;
} }
function createProxyItem(item: App.Service.ServiceConfigItem) { function createProxyItem(item: App.Service.ServiceConfigItem, enableLog: boolean) {
const proxy: Record<string, ProxyOptions> = {}; const proxy: Record<string, ProxyOptions> = {};
proxy[item.proxyPattern] = { proxy[item.proxyPattern] = {
target: item.baseURL, target: item.baseURL,
changeOrigin: true, changeOrigin: true,
configure: (_proxy: HttpProxy.Server, options: ProxyOptions) => {
_proxy.on('proxyReq', (_proxyReq, req, _res) => {
if (!enableLog) return;
const requestUrl = `${lightBlue('[proxy url]')}: ${bgYellow(` ${req.method} `)} ${green(`${item.proxyPattern}${req.url}`)}`;
const proxyUrl = `${lightBlue('[real request url]')}: ${green(`${options.target}${req.url}`)}`;
consola.log(`${requestUrl}\n${proxyUrl}`);
});
_proxy.on('error', (_err, req, _res) => {
if (!enableLog) return;
consola.log(bgRed(`Error: ${req.method} `), green(`${options.target}${req.url}`));
});
},
rewrite: path => path.replace(new RegExp(`^${item.proxyPattern}`), '') rewrite: path => path.replace(new RegExp(`^${item.proxyPattern}`), '')
}; };

View File

@ -1,12 +1,12 @@
import process from 'node:process'; import process from 'node:process';
import path from 'node:path'; import path from 'node:path';
import type { PluginOption } from 'vite'; import type { PluginOption } from 'vite';
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
import Icons from 'unplugin-icons/vite'; import Icons from 'unplugin-icons/vite';
import IconsResolver from 'unplugin-icons/resolver'; import IconsResolver from 'unplugin-icons/resolver';
import Components from 'unplugin-vue-components/vite'; import Components from 'unplugin-vue-components/vite';
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'; import { NaiveUiResolver } from 'unplugin-vue-components/resolvers';
import { FileSystemIconLoader } from 'unplugin-icons/loaders'; import { FileSystemIconLoader } from 'unplugin-icons/loaders';
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
export function setupUnplugin(viteEnv: Env.ImportMeta) { export function setupUnplugin(viteEnv: Env.ImportMeta) {
const { VITE_ICON_PREFIX, VITE_ICON_LOCAL_PREFIX } = viteEnv; const { VITE_ICON_PREFIX, VITE_ICON_LOCAL_PREFIX } = viteEnv;

View File

@ -1,7 +1,7 @@
{ {
"name": "soybean-admin", "name": "soybean-admin",
"type": "module", "type": "module",
"version": "1.3.11", "version": "1.3.12",
"description": "A fresh and elegant admin template, based on Vue3、Vite3、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite3、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。", "description": "A fresh and elegant admin template, based on Vue3、Vite3、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite3、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
"author": { "author": {
"name": "Soybean", "name": "Soybean",
@ -48,8 +48,8 @@
}, },
"dependencies": { "dependencies": {
"@antv/data-set": "0.11.8", "@antv/data-set": "0.11.8",
"@antv/g2": "5.2.10", "@antv/g2": "5.2.11",
"@antv/g6": "5.0.42", "@antv/g6": "5.0.44",
"@better-scroll/core": "2.5.1", "@better-scroll/core": "2.5.1",
"@iconify/vue": "4.3.0", "@iconify/vue": "4.3.0",
"@sa/alova": "workspace:*", "@sa/alova": "workspace:*",
@ -58,73 +58,74 @@
"@sa/hooks": "workspace:*", "@sa/hooks": "workspace:*",
"@sa/materials": "workspace:*", "@sa/materials": "workspace:*",
"@sa/utils": "workspace:*", "@sa/utils": "workspace:*",
"@visactor/vchart": "1.13.4", "@visactor/vchart": "1.13.6",
"@visactor/vchart-theme": "1.12.2", "@visactor/vchart-theme": "1.12.2",
"@visactor/vtable-editors": "1.15.1", "@visactor/vtable-editors": "1.17.2",
"@visactor/vtable-gantt": "1.15.1", "@visactor/vtable-gantt": "1.17.2",
"@visactor/vue-vtable": "1.15.1", "@visactor/vue-vtable": "1.17.2",
"@vueuse/components": "12.4.0", "@vueuse/components": "13.0.0",
"@vueuse/core": "12.4.0", "@vueuse/core": "13.0.0",
"clipboard": "2.0.11", "clipboard": "2.0.11",
"dayjs": "1.11.13", "dayjs": "1.11.13",
"defu": "6.1.4", "defu": "6.1.4",
"dhtmlx-gantt": "9.0.3", "dhtmlx-gantt": "9.0.5",
"dompurify": "3.2.3", "dompurify": "3.2.4",
"echarts": "5.6.0", "echarts": "5.6.0",
"jsbarcode": "3.11.6", "jsbarcode": "3.11.6",
"json5": "2.2.3", "json5": "2.2.3",
"naive-ui": "2.41.0", "naive-ui": "2.41.0",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"pinia": "2.3.0", "pinia": "3.0.1",
"pinyin-pro": "3.26.0", "pinyin-pro": "3.26.0",
"print-js": "1.6.0", "print-js": "1.6.0",
"swiper": "11.2.1", "swiper": "11.2.5",
"tailwind-merge": "2.6.0", "tailwind-merge": "3.0.2",
"typeit": "8.8.7", "typeit": "8.8.7",
"vditor": "3.10.8", "vditor": "3.10.9",
"vue": "3.5.13", "vue": "3.5.13",
"vue-draggable-plus": "0.6.0", "vue-draggable-plus": "0.6.0",
"vue-i18n": "11.0.1", "vue-i18n": "11.1.2",
"vue-pdf-embed": "2.1.2", "vue-pdf-embed": "2.1.2",
"vue-router": "4.5.0", "vue-router": "4.5.0",
"wangeditor": "4.7.15", "wangeditor": "4.7.15",
"xgplayer": "3.0.20", "xgplayer": "3.0.21",
"xlsx": "0.18.5" "xlsx": "0.18.5"
}, },
"devDependencies": { "devDependencies": {
"@amap/amap-jsapi-types": "0.0.15", "@amap/amap-jsapi-types": "0.0.15",
"@elegant-router/vue": "0.3.8", "@elegant-router/vue": "0.3.8",
"@iconify/json": "2.2.297", "@iconify/json": "2.2.316",
"@sa/scripts": "workspace:*", "@sa/scripts": "workspace:*",
"@sa/uno-preset": "workspace:*", "@sa/uno-preset": "workspace:*",
"@soybeanjs/eslint-config": "1.4.4", "@soybeanjs/eslint-config": "1.6.0",
"@types/bmapgl": "0.0.7", "@types/bmapgl": "0.0.7",
"@types/dompurify": "3.2.0", "@types/node": "22.13.10",
"@types/node": "22.10.7",
"@types/nprogress": "0.2.3", "@types/nprogress": "0.2.3",
"@unocss/eslint-config": "65.4.2", "@unocss/eslint-config": "66.0.0",
"@unocss/preset-icons": "65.4.2", "@unocss/preset-icons": "66.0.0",
"@unocss/preset-uno": "65.4.2", "@unocss/preset-uno": "66.0.0",
"@unocss/transformer-directives": "65.4.2", "@unocss/transformer-directives": "66.0.0",
"@unocss/transformer-variant-group": "65.4.2", "@unocss/transformer-variant-group": "66.0.0",
"@unocss/vite": "65.4.2", "@unocss/vite": "66.0.0",
"@vitejs/plugin-vue": "5.2.1", "@vitejs/plugin-vue": "5.2.1",
"@vitejs/plugin-vue-jsx": "4.1.1", "@vitejs/plugin-vue-jsx": "4.1.1",
"eslint": "9.18.0", "consola": "3.4.0",
"eslint-plugin-vue": "9.32.0", "eslint": "9.22.0",
"lint-staged": "15.4.1", "eslint-plugin-vue": "10.0.0",
"sass": "1.83.4", "kolorist": "1.8.0",
"lint-staged": "15.5.0",
"sass": "1.85.1",
"simple-git-hooks": "2.11.1", "simple-git-hooks": "2.11.1",
"tsx": "4.19.2", "tsx": "4.19.3",
"typescript": "5.7.3", "typescript": "5.8.2",
"unplugin-icons": "22.0.0", "unplugin-icons": "22.1.0",
"unplugin-vue-components": "28.0.0", "unplugin-vue-components": "28.4.1",
"vite": "6.0.7", "vite": "6.2.1",
"vite-plugin-progress": "0.0.7", "vite-plugin-progress": "0.0.7",
"vite-plugin-svg-icons": "2.0.1", "vite-plugin-svg-icons": "2.0.1",
"vite-plugin-vue-devtools": "7.7.0", "vite-plugin-vue-devtools": "7.7.2",
"vue-eslint-parser": "9.4.3", "vue-eslint-parser": "10.1.1",
"vue-tsc": "2.2.0" "vue-tsc": "2.2.8"
}, },
"simple-git-hooks": { "simple-git-hooks": {
"commit-msg": "pnpm sa git-commit-verify", "commit-msg": "pnpm sa git-commit-verify",

View File

@ -1,6 +1,6 @@
{ {
"name": "@sa/alova", "name": "@sa/alova",
"version": "1.3.11", "version": "1.3.12",
"exports": { "exports": {
".": "./src/index.ts", ".": "./src/index.ts",
"./fetch": "./src/fetch.ts", "./fetch": "./src/fetch.ts",
@ -13,8 +13,8 @@
} }
}, },
"dependencies": { "dependencies": {
"@alova/mock": "2.0.11", "@alova/mock": "2.0.12",
"@sa/utils": "workspace:*", "@sa/utils": "workspace:*",
"alova": "3.2.8" "alova": "3.2.10"
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@sa/axios", "name": "@sa/axios",
"version": "1.3.11", "version": "1.3.12",
"exports": { "exports": {
".": "./src/index.ts" ".": "./src/index.ts"
}, },
@ -11,7 +11,7 @@
}, },
"dependencies": { "dependencies": {
"@sa/utils": "workspace:*", "@sa/utils": "workspace:*",
"axios": "1.7.9", "axios": "1.8.3",
"axios-retry": "4.5.0", "axios-retry": "4.5.0",
"qs": "6.14.0" "qs": "6.14.0"
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "@sa/color", "name": "@sa/color",
"version": "1.3.11", "version": "1.3.12",
"exports": { "exports": {
".": "./src/index.ts" ".": "./src/index.ts"
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "@sa/hooks", "name": "@sa/hooks",
"version": "1.3.11", "version": "1.3.12",
"exports": { "exports": {
".": "./src/index.ts" ".": "./src/index.ts"
}, },

View File

@ -1,5 +1,5 @@
import { computed, reactive, ref } from 'vue'; import { computed, reactive, ref } from 'vue';
import type { Ref } from 'vue'; import type { Ref, VNodeChild } from 'vue';
import { jsonClone } from '@sa/utils'; import { jsonClone } from '@sa/utils';
import useBoolean from './use-boolean'; import useBoolean from './use-boolean';
import useLoading from './use-loading'; import useLoading from './use-loading';
@ -8,9 +8,11 @@ export type MaybePromise<T> = T | Promise<T>;
export type ApiFn = (args: any) => Promise<unknown>; export type ApiFn = (args: any) => Promise<unknown>;
export type TableColumnCheckTitle = string | ((...args: any) => VNodeChild);
export type TableColumnCheck = { export type TableColumnCheck = {
key: string; key: string;
title: string; title: TableColumnCheckTitle;
checked: boolean; checked: boolean;
}; };

View File

@ -1,6 +1,6 @@
{ {
"name": "@sa/materials", "name": "@sa/materials",
"version": "1.3.11", "version": "1.3.12",
"exports": { "exports": {
".": "./src/index.ts" ".": "./src/index.ts"
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "@sa/fetch", "name": "@sa/fetch",
"version": "1.3.11", "version": "1.3.12",
"exports": { "exports": {
".": "./src/index.ts" ".": "./src/index.ts"
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "@sa/scripts", "name": "@sa/scripts",
"version": "1.3.11", "version": "1.3.12",
"bin": { "bin": {
"sa": "./bin.ts" "sa": "./bin.ts"
}, },
@ -14,14 +14,14 @@
}, },
"devDependencies": { "devDependencies": {
"@soybeanjs/changelog": "0.3.24", "@soybeanjs/changelog": "0.3.24",
"bumpp": "9.10.1", "bumpp": "10.1.0",
"c12": "2.0.1", "c12": "3.0.2",
"cac": "6.7.14", "cac": "6.7.14",
"consola": "3.4.0", "consola": "3.4.0",
"enquirer": "2.4.1", "enquirer": "2.4.1",
"execa": "9.5.2", "execa": "9.5.2",
"kolorist": "1.8.0", "kolorist": "1.8.0",
"npm-check-updates": "17.1.14", "npm-check-updates": "17.1.15",
"rimraf": "6.0.1" "rimraf": "6.0.1"
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@sa/uno-preset", "name": "@sa/uno-preset",
"version": "1.3.11", "version": "1.3.12",
"exports": { "exports": {
".": "./src/index.ts" ".": "./src/index.ts"
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "@sa/utils", "name": "@sa/utils",
"version": "1.3.11", "version": "1.3.12",
"exports": { "exports": {
".": "./src/index.ts" ".": "./src/index.ts"
}, },
@ -14,7 +14,7 @@
"crypto-js": "4.2.0", "crypto-js": "4.2.0",
"klona": "2.0.6", "klona": "2.0.6",
"localforage": "1.10.0", "localforage": "1.10.0",
"nanoid": "5.0.9" "nanoid": "5.1.3"
}, },
"devDependencies": { "devDependencies": {
"@types/crypto-js": "4.2.2" "@types/crypto-js": "4.2.2"

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,10 @@ const columns = defineModel<NaiveUI.TableColumnCheck[]>('columns', {
<div v-for="item in columns" :key="item.key" class="h-36px flex-y-center rd-4px hover:(bg-primary bg-opacity-20)"> <div v-for="item in columns" :key="item.key" class="h-36px flex-y-center rd-4px hover:(bg-primary bg-opacity-20)">
<icon-mdi-drag class="mr-8px h-full cursor-move text-icon" /> <icon-mdi-drag class="mr-8px h-full cursor-move text-icon" />
<NCheckbox v-model:checked="item.checked" class="none_draggable flex-1"> <NCheckbox v-model:checked="item.checked" class="none_draggable flex-1">
{{ item.title }} <template v-if="typeof item.title === 'function'">
<component :is="item.title" />
</template>
<template v-else>{{ item.title }}</template>
</NCheckbox> </NCheckbox>
</div> </div>
</VueDraggable> </VueDraggable>

View File

@ -1,7 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed } from 'vue'; import { computed } from 'vue';
import { $t } from '@/locales';
import { useRouterPush } from '@/hooks/common/router'; import { useRouterPush } from '@/hooks/common/router';
import { $t } from '@/locales';
defineOptions({ name: 'ExceptionBase' }); defineOptions({ name: 'ExceptionBase' });

View File

@ -61,3 +61,5 @@ export const resetCacheStrategyRecord: Record<UnionKey.ResetCacheStrategy, App.I
}; };
export const resetCacheStrategyOptions = transformRecordToOption(resetCacheStrategyRecord); export const resetCacheStrategyOptions = transformRecordToOption(resetCacheStrategyRecord);
export const DARK_CLASS = 'dark';

View File

@ -1,7 +1,7 @@
import { computed } from 'vue'; import { computed } from 'vue';
import { useCountDown, useLoading } from '@sa/hooks'; import { useCountDown, useLoading } from '@sa/hooks';
import { $t } from '@/locales';
import { REG_PHONE } from '@/constants/reg'; import { REG_PHONE } from '@/constants/reg';
import { $t } from '@/locales';
export function useCaptcha() { export function useCaptcha() {
const { loading, startLoading, endLoading } = useLoading(); const { loading, startLoading, endLoading } = useLoading();

View File

@ -1,4 +1,5 @@
import { computed, effectScope, nextTick, onScopeDispose, ref, watch } from 'vue'; import { computed, effectScope, nextTick, onScopeDispose, ref, watch } from 'vue';
import { useElementSize } from '@vueuse/core';
import * as echarts from 'echarts/core'; import * as echarts from 'echarts/core';
import { BarChart, GaugeChart, LineChart, PictorialBarChart, PieChart, RadarChart, ScatterChart } from 'echarts/charts'; import { BarChart, GaugeChart, LineChart, PictorialBarChart, PieChart, RadarChart, ScatterChart } from 'echarts/charts';
import type { import type {
@ -29,7 +30,6 @@ import type {
} from 'echarts/components'; } from 'echarts/components';
import { LabelLayout, UniversalTransition } from 'echarts/features'; import { LabelLayout, UniversalTransition } from 'echarts/features';
import { CanvasRenderer } from 'echarts/renderers'; import { CanvasRenderer } from 'echarts/renderers';
import { useElementSize } from '@vueuse/core';
import { useThemeStore } from '@/store/modules/theme'; import { useThemeStore } from '@/store/modules/theme';
export type ECOption = echarts.ComposeOption< export type ECOption = echarts.ComposeOption<

View File

@ -18,12 +18,7 @@ export function useRouterPush(inSetup = true) {
const routerBack = router.back; const routerBack = router.back;
interface RouterPushOptions { async function routerPushByKey(key: RouteKey, options?: App.Global.RouterPushOptions) {
query?: Record<string, string>;
params?: Record<string, string>;
}
async function routerPushByKey(key: RouteKey, options?: RouterPushOptions) {
const { query, params } = options || {}; const { query, params } = options || {};
const routeLocation: RouteLocationRaw = { const routeLocation: RouteLocationRaw = {
@ -67,7 +62,7 @@ export function useRouterPush(inSetup = true) {
async function toLogin(loginModule?: UnionKey.LoginModule, redirectUrl?: string) { async function toLogin(loginModule?: UnionKey.LoginModule, redirectUrl?: string) {
const module = loginModule || 'pwd-login'; const module = loginModule || 'pwd-login';
const options: RouterPushOptions = { const options: App.Global.RouterPushOptions = {
params: { params: {
module module
} }

View File

@ -64,7 +64,7 @@ export function useTable<A extends NaiveUI.TableApiFn>(config: NaiveUI.NaiveTabl
if (isTableColumnHasKey(column)) { if (isTableColumnHasKey(column)) {
checks.push({ checks.push({
key: column.key as string, key: column.key as string,
title: column.title as string, title: column.title!,
checked: true checked: true
}); });
} else if (column.type === 'selection') { } else if (column.type === 'selection') {

View File

@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { useFullscreen } from '@vueuse/core'; import { useFullscreen } from '@vueuse/core';
import { GLOBAL_HEADER_MENU_ID } from '@/constants/app';
import { useAppStore } from '@/store/modules/app'; import { useAppStore } from '@/store/modules/app';
import { useThemeStore } from '@/store/modules/theme'; import { useThemeStore } from '@/store/modules/theme';
import { GLOBAL_HEADER_MENU_ID } from '@/constants/app';
import GlobalLogo from '../global-logo/index.vue'; import GlobalLogo from '../global-logo/index.vue';
import GlobalBreadcrumb from '../global-breadcrumb/index.vue'; import GlobalBreadcrumb from '../global-breadcrumb/index.vue';
import GlobalSearch from '../global-search/index.vue'; import GlobalSearch from '../global-search/index.vue';

View File

@ -2,11 +2,11 @@
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { SimpleScrollbar } from '@sa/materials'; import { SimpleScrollbar } from '@sa/materials';
import { GLOBAL_SIDER_MENU_ID } from '@/constants/app';
import { useAppStore } from '@/store/modules/app'; import { useAppStore } from '@/store/modules/app';
import { useThemeStore } from '@/store/modules/theme'; import { useThemeStore } from '@/store/modules/theme';
import { useRouteStore } from '@/store/modules/route'; import { useRouteStore } from '@/store/modules/route';
import { useRouterPush } from '@/hooks/common/router'; import { useRouterPush } from '@/hooks/common/router';
import { GLOBAL_SIDER_MENU_ID } from '@/constants/app';
import { useMenu } from '../../../context'; import { useMenu } from '../../../context';
defineOptions({ defineOptions({

View File

@ -3,12 +3,12 @@ import { computed, ref, watch } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { SimpleScrollbar } from '@sa/materials'; import { SimpleScrollbar } from '@sa/materials';
import { useBoolean } from '@sa/hooks'; import { useBoolean } from '@sa/hooks';
import { GLOBAL_SIDER_MENU_ID } from '@/constants/app';
import { useAppStore } from '@/store/modules/app'; import { useAppStore } from '@/store/modules/app';
import { useThemeStore } from '@/store/modules/theme'; import { useThemeStore } from '@/store/modules/theme';
import { useRouteStore } from '@/store/modules/route'; import { useRouteStore } from '@/store/modules/route';
import { useRouterPush } from '@/hooks/common/router'; import { useRouterPush } from '@/hooks/common/router';
import { $t } from '@/locales'; import { $t } from '@/locales';
import { GLOBAL_SIDER_MENU_ID } from '@/constants/app';
import { useMenu, useMixMenuContext } from '../../../context'; import { useMenu, useMixMenuContext } from '../../../context';
import FirstLevelMenu from '../components/first-level-menu.vue'; import FirstLevelMenu from '../components/first-level-menu.vue';
import GlobalLogo from '../../global-logo/index.vue'; import GlobalLogo from '../../global-logo/index.vue';

View File

@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from 'vue';
import { GLOBAL_SIDER_MENU_ID } from '@/constants/app';
import { useAppStore } from '@/store/modules/app'; import { useAppStore } from '@/store/modules/app';
import { useThemeStore } from '@/store/modules/theme'; import { useThemeStore } from '@/store/modules/theme';
import { GLOBAL_SIDER_MENU_ID } from '@/constants/app';
import GlobalLogo from '../global-logo/index.vue'; import GlobalLogo from '../global-logo/index.vue';
defineOptions({ defineOptions({

View File

@ -1,9 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from 'vue';
import type { VNode } from 'vue'; import type { VNode } from 'vue';
import { $t } from '@/locales';
import { useTabStore } from '@/store/modules/tab'; import { useTabStore } from '@/store/modules/tab';
import { useSvgIcon } from '@/hooks/common/icon'; import { useSvgIcon } from '@/hooks/common/icon';
import { $t } from '@/locales';
defineOptions({ defineOptions({
name: 'ContextMenu' name: 'ContextMenu'

View File

@ -3,12 +3,12 @@ import { nextTick, reactive, ref, watch } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useElementBounding } from '@vueuse/core'; import { useElementBounding } from '@vueuse/core';
import { PageTab } from '@sa/materials'; import { PageTab } from '@sa/materials';
import BetterScroll from '@/components/custom/better-scroll.vue';
import { useAppStore } from '@/store/modules/app'; import { useAppStore } from '@/store/modules/app';
import { useThemeStore } from '@/store/modules/theme'; import { useThemeStore } from '@/store/modules/theme';
import { useRouteStore } from '@/store/modules/route'; import { useRouteStore } from '@/store/modules/route';
import { useTabStore } from '@/store/modules/tab'; import { useTabStore } from '@/store/modules/tab';
import { isPC } from '@/utils/agent'; import { isPC } from '@/utils/agent';
import BetterScroll from '@/components/custom/better-scroll.vue';
import ContextMenu from './context-menu.vue'; import ContextMenu from './context-menu.vue';
defineOptions({ defineOptions({
@ -114,7 +114,7 @@ function setDropdown(config: Partial<DropdownConfig>) {
let isClickContextMenu = false; let isClickContextMenu = false;
function handleDropdownVisible(visible: boolean) { function handleDropdownVisible(visible: boolean | undefined) {
if (!isClickContextMenu) { if (!isClickContextMenu) {
setDropdown({ visible }); setDropdown({ visible });
} }
@ -186,7 +186,7 @@ init();
:active="tab.id === tabStore.activeTabId" :active="tab.id === tabStore.activeTabId"
:active-color="themeStore.themeColor" :active-color="themeStore.themeColor"
:closable="!tabStore.isTabRetain(tab.id)" :closable="!tabStore.isTabRetain(tab.id)"
@click="tabStore.switchRouteByTab(tab)" @pointerdown="tabStore.switchRouteByTab(tab)"
@close="handleCloseTab(tab)" @close="handleCloseTab(tab)"
@contextmenu="handleContextMenu($event, tab.id)" @contextmenu="handleContextMenu($event, tab.id)"
> >

View File

@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import Clipboard from 'clipboard'; import Clipboard from 'clipboard';
import { $t } from '@/locales';
import { useThemeStore } from '@/store/modules/theme'; import { useThemeStore } from '@/store/modules/theme';
import { $t } from '@/locales';
defineOptions({ defineOptions({
name: 'ConfigOperation' name: 'ConfigOperation'

View File

@ -1,14 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from 'vue';
import { $t } from '@/locales';
import { useThemeStore } from '@/store/modules/theme';
import { import {
resetCacheStrategyOptions, resetCacheStrategyOptions,
themePageAnimationModeOptions, themePageAnimationModeOptions,
themeScrollModeOptions, themeScrollModeOptions,
themeTabModeOptions themeTabModeOptions
} from '@/constants/app'; } from '@/constants/app';
import { useThemeStore } from '@/store/modules/theme';
import { translateOptions } from '@/utils/common'; import { translateOptions } from '@/utils/common';
import { $t } from '@/locales';
import SettingItem from '../components/setting-item.vue'; import SettingItem from '../components/setting-item.vue';
defineOptions({ defineOptions({

View File

@ -1,16 +1,22 @@
// @unocss-include // @unocss-include
import { getRgb } from '@sa/color'; import { getRgb } from '@sa/color';
import { $t } from '@/locales'; import { DARK_CLASS } from '@/constants/app';
import { localStg } from '@/utils/storage'; import { localStg } from '@/utils/storage';
import { toggleHtmlClass } from '@/utils/common';
import systemLogo from '@/assets/svg-icon/logo.svg?raw'; import systemLogo from '@/assets/svg-icon/logo.svg?raw';
import { $t } from '@/locales';
export function setupLoading() { export function setupLoading() {
const themeColor = localStg.get('themeColor') || '#646cff'; const themeColor = localStg.get('themeColor') || '#646cff';
const darkMode = localStg.get('darkMode') || false;
const { r, g, b } = getRgb(themeColor); const { r, g, b } = getRgb(themeColor);
const primaryColor = `--primary-color: ${r} ${g} ${b}`; const primaryColor = `--primary-color: ${r} ${g} ${b}`;
if (darkMode) {
toggleHtmlClass(DARK_CLASS).add();
}
const loadingClasses = [ const loadingClasses = [
'left-0 top-0', 'left-0 top-0',
'left-0 bottom-0 animate-delay-500', 'left-0 bottom-0 animate-delay-500',
@ -27,14 +33,14 @@ export function setupLoading() {
.join('\n'); .join('\n');
const loading = ` const loading = `
<div class="fixed-center flex-col" style="${primaryColor}"> <div class="fixed-center flex-col bg-layout" style="${primaryColor}">
${logoWithClass} ${logoWithClass}
<div class="w-56px h-56px my-36px"> <div class="w-56px h-56px my-36px">
<div class="relative h-full animate-spin"> <div class="relative h-full animate-spin">
${dot} ${dot}
</div> </div>
</div> </div>
<h2 class="text-28px font-500 text-#646464">${$t('system.title')}</h2> <h2 class="text-28px font-500 text-primary">${$t('system.title')}</h2>
</div>`; </div>`;
const app = document.getElementById('app'); const app = document.getElementById('app');

View File

@ -6,10 +6,10 @@ import type {
Router Router
} from 'vue-router'; } from 'vue-router';
import type { RouteKey, RoutePath } from '@elegant-router/types'; import type { RouteKey, RoutePath } from '@elegant-router/types';
import { getRouteName } from '@/router/elegant/transform';
import { useAuthStore } from '@/store/modules/auth'; import { useAuthStore } from '@/store/modules/auth';
import { useRouteStore } from '@/store/modules/route'; import { useRouteStore } from '@/store/modules/route';
import { localStg } from '@/utils/storage'; import { localStg } from '@/utils/storage';
import { getRouteName } from '@/router/elegant/transform';
/** /**
* create route guard * create route guard

View File

@ -1,5 +1,5 @@
import { useTitle } from '@vueuse/core';
import type { Router } from 'vue-router'; import type { Router } from 'vue-router';
import { useTitle } from '@vueuse/core';
import { $t } from '@/locales'; import { $t } from '@/locales';
export function createDocumentTitleGuard(router: Router) { export function createDocumentTitleGuard(router: Router) {

View File

@ -1,9 +1,9 @@
import type { AxiosResponse } from 'axios'; import type { AxiosResponse } from 'axios';
import { BACKEND_ERROR_CODE, createFlatRequest, createRequest } from '@sa/axios'; import { BACKEND_ERROR_CODE, createFlatRequest, createRequest } from '@sa/axios';
import { useAuthStore } from '@/store/modules/auth'; import { useAuthStore } from '@/store/modules/auth';
import { $t } from '@/locales';
import { localStg } from '@/utils/storage'; import { localStg } from '@/utils/storage';
import { getServiceBaseURL } from '@/utils/service'; import { getServiceBaseURL } from '@/utils/service';
import { $t } from '@/locales';
import { getAuthorization, handleExpiredRequest, showErrorMsg } from './shared'; import { getAuthorization, handleExpiredRequest, showErrorMsg } from './shared';
import type { RequestInstanceState } from './type'; import type { RequestInstanceState } from './type';

View File

@ -1,12 +1,12 @@
import { effectScope, nextTick, onScopeDispose, ref, watch } from 'vue'; import { effectScope, nextTick, onScopeDispose, ref, watch } from 'vue';
import { defineStore } from 'pinia';
import { breakpointsTailwind, useBreakpoints, useEventListener, useTitle } from '@vueuse/core'; import { breakpointsTailwind, useBreakpoints, useEventListener, useTitle } from '@vueuse/core';
import { defineStore } from 'pinia';
import { useBoolean } from '@sa/hooks'; import { useBoolean } from '@sa/hooks';
import { SetupStoreId } from '@/enum';
import { router } from '@/router'; import { router } from '@/router';
import { localStg } from '@/utils/storage';
import { SetupStoreId } from '@/enum';
import { $t, setLocale } from '@/locales'; import { $t, setLocale } from '@/locales';
import { setDayjsLocale } from '@/locales/dayjs'; import { setDayjsLocale } from '@/locales/dayjs';
import { localStg } from '@/utils/storage';
import { useRouteStore } from '../route'; import { useRouteStore } from '../route';
import { useTabStore } from '../tab'; import { useTabStore } from '../tab';
import { useThemeStore } from '../theme'; import { useThemeStore } from '../theme';

View File

@ -2,10 +2,10 @@ import { computed, reactive, ref } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { useLoading } from '@sa/hooks'; import { useLoading } from '@sa/hooks';
import { SetupStoreId } from '@/enum';
import { useRouterPush } from '@/hooks/common/router';
import { fetchGetUserInfo, fetchLogin } from '@/service/api'; import { fetchGetUserInfo, fetchLogin } from '@/service/api';
import { useRouterPush } from '@/hooks/common/router';
import { localStg } from '@/utils/storage'; import { localStg } from '@/utils/storage';
import { SetupStoreId } from '@/enum';
import { $t } from '@/locales'; import { $t } from '@/locales';
import { useRouteStore } from '../route'; import { useRouteStore } from '../route';
import { useTabStore } from '../tab'; import { useTabStore } from '../tab';

View File

@ -3,12 +3,12 @@ import type { RouteRecordRaw } from 'vue-router';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { useBoolean } from '@sa/hooks'; import { useBoolean } from '@sa/hooks';
import type { CustomRoute, ElegantConstRoute, LastLevelRouteKey, RouteKey, RouteMap } from '@elegant-router/types'; import type { CustomRoute, ElegantConstRoute, LastLevelRouteKey, RouteKey, RouteMap } from '@elegant-router/types';
import { SetupStoreId } from '@/enum';
import { router } from '@/router'; import { router } from '@/router';
import { fetchGetConstantRoutes, fetchGetUserRoutes, fetchIsRouteExist } from '@/service/api';
import { SetupStoreId } from '@/enum';
import { createStaticRoutes, getAuthVueRoutes } from '@/router/routes'; import { createStaticRoutes, getAuthVueRoutes } from '@/router/routes';
import { ROOT_ROUTE } from '@/router/routes/builtin'; import { ROOT_ROUTE } from '@/router/routes/builtin';
import { getRouteName, getRoutePath } from '@/router/elegant/transform'; import { getRouteName, getRoutePath } from '@/router/elegant/transform';
import { fetchGetConstantRoutes, fetchGetUserRoutes, fetchIsRouteExist } from '@/service/api';
import { useAuthStore } from '../auth'; import { useAuthStore } from '../auth';
import { useTabStore } from '../tab'; import { useTabStore } from '../tab';
import { import {

View File

@ -1,7 +1,7 @@
import type { RouteLocationNormalizedLoaded, RouteRecordRaw, _RouteRecordBase } from 'vue-router'; import type { RouteLocationNormalizedLoaded, RouteRecordRaw, _RouteRecordBase } from 'vue-router';
import type { ElegantConstRoute, LastLevelRouteKey, RouteKey, RouteMap } from '@elegant-router/types'; import type { ElegantConstRoute, LastLevelRouteKey, RouteKey, RouteMap } from '@elegant-router/types';
import { $t } from '@/locales';
import { useSvgIcon } from '@/hooks/common/icon'; import { useSvgIcon } from '@/hooks/common/icon';
import { $t } from '@/locales';
/** /**
* Filter auth routes by roles * Filter auth routes by roles

View File

@ -1,12 +1,12 @@
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { defineStore } from 'pinia';
import { useEventListener } from '@vueuse/core'; import { useEventListener } from '@vueuse/core';
import { defineStore } from 'pinia';
import type { RouteKey } from '@elegant-router/types'; import type { RouteKey } from '@elegant-router/types';
import { router } from '@/router'; import { router } from '@/router';
import { SetupStoreId } from '@/enum'; import { useRouteStore } from '@/store/modules/route';
import { useRouterPush } from '@/hooks/common/router'; import { useRouterPush } from '@/hooks/common/router';
import { localStg } from '@/utils/storage'; import { localStg } from '@/utils/storage';
import { useRouteStore } from '@/store/modules/route'; import { SetupStoreId } from '@/enum';
import { useThemeStore } from '../theme'; import { useThemeStore } from '../theme';
import { import {
extractTabsByAllRoutes, extractTabsByAllRoutes,
@ -160,6 +160,25 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
update(); update();
} }
const { routerPushByKey } = useRouterPush();
/**
* Replace tab
*
* @param key Route key
* @param options Router push options
*/
async function replaceTab(key: RouteKey, options?: App.Global.RouterPushOptions) {
const oldTabId = activeTabId.value;
// push new route
await routerPushByKey(key, options);
// remove old tab (exclude fixed tab)
if (!isTabRetain(oldTabId)) {
await removeTab(oldTabId);
}
}
/** /**
* Switch route by tab * Switch route by tab
* *
@ -282,6 +301,7 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
removeTab, removeTab,
removeActiveTab, removeActiveTab,
removeTabByRouteName, removeTabByRouteName,
replaceTab,
clearTabs, clearTabs,
clearLeftTabs, clearLeftTabs,
clearRightTabs, clearRightTabs,

View File

@ -1,10 +1,10 @@
import { computed, effectScope, onScopeDispose, ref, toRefs, watch } from 'vue'; import { computed, effectScope, onScopeDispose, ref, toRefs, watch } from 'vue';
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import { defineStore } from 'pinia';
import { useEventListener, usePreferredColorScheme } from '@vueuse/core'; import { useEventListener, usePreferredColorScheme } from '@vueuse/core';
import { defineStore } from 'pinia';
import { getPaletteColorByNumber } from '@sa/color'; import { getPaletteColorByNumber } from '@sa/color';
import { SetupStoreId } from '@/enum';
import { localStg } from '@/utils/storage'; import { localStg } from '@/utils/storage';
import { SetupStoreId } from '@/enum';
import { import {
addThemeVarsToGlobal, addThemeVarsToGlobal,
createThemeToken, createThemeToken,
@ -174,6 +174,7 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
darkMode, darkMode,
val => { val => {
toggleCssDarkMode(val); toggleCssDarkMode(val);
localStg.set('darkMode', val);
}, },
{ immediate: true } { immediate: true }
); );

View File

@ -1,12 +1,11 @@
import type { GlobalThemeOverrides } from 'naive-ui'; import type { GlobalThemeOverrides } from 'naive-ui';
import { defu } from 'defu'; import { defu } from 'defu';
import { addColorAlpha, getColorPalette, getPaletteColorByNumber, getRgb } from '@sa/color'; import { addColorAlpha, getColorPalette, getPaletteColorByNumber, getRgb } from '@sa/color';
import { overrideThemeSettings, themeSettings } from '@/theme/settings'; import { DARK_CLASS } from '@/constants/app';
import { themeVars } from '@/theme/vars';
import { toggleHtmlClass } from '@/utils/common'; import { toggleHtmlClass } from '@/utils/common';
import { localStg } from '@/utils/storage'; import { localStg } from '@/utils/storage';
import { overrideThemeSettings, themeSettings } from '@/theme/settings';
const DARK_CLASS = 'dark'; import { themeVars } from '@/theme/vars';
/** Init theme settings */ /** Init theme settings */
export function initThemeSettings() { export function initThemeSettings() {

View File

@ -113,7 +113,8 @@ code,
kbd, kbd,
samp, samp,
pre { pre {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; /* 1 */ font-family:
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; /* 1 */
font-size: 1em; /* 2 */ font-size: 1em; /* 2 */
} }

View File

@ -175,6 +175,12 @@ declare namespace App {
type RoutePath = import('@elegant-router/types').RoutePath; type RoutePath = import('@elegant-router/types').RoutePath;
type LastLevelRouteKey = import('@elegant-router/types').LastLevelRouteKey; type LastLevelRouteKey = import('@elegant-router/types').LastLevelRouteKey;
/** The router push options */
type RouterPushOptions = {
query?: Record<string, string>;
params?: Record<string, string>;
};
/** The global header props */ /** The global header props */
interface HeaderProps { interface HeaderProps {
/** Whether to show the logo */ /** Whether to show the logo */

View File

@ -2,6 +2,7 @@
// @ts-nocheck // @ts-nocheck
// Generated by unplugin-vue-components // Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399 // Read more: https://github.com/vuejs/core/pull/3399
// biome-ignore lint: disable
export {} export {}
/* prettier-ignore */ /* prettier-ignore */

View File

@ -20,6 +20,8 @@ declare namespace StorageType {
refreshToken: string; refreshToken: string;
/** The theme color */ /** The theme color */
themeColor: string; themeColor: string;
/** The dark mode */
darkMode: boolean;
/** The theme settings */ /** The theme settings */
themeSettings: App.Theme.ThemeSetting; themeSettings: App.Theme.ThemeSetting;
/** /**

View File

@ -8,6 +8,7 @@ declare namespace Env {
type RouterHistoryMode = 'hash' | 'history' | 'memory'; type RouterHistoryMode = 'hash' | 'history' | 'memory';
/** Interface for import.meta */ /** Interface for import.meta */
// eslint-disable-next-line @typescript-eslint/no-shadow
interface ImportMeta extends ImportMetaEnv { interface ImportMeta extends ImportMetaEnv {
/** The base url of the application */ /** The base url of the application */
readonly VITE_BASE_URL: string; readonly VITE_BASE_URL: string;
@ -105,6 +106,8 @@ declare namespace Env {
readonly VITE_STORAGE_PREFIX?: string; readonly VITE_STORAGE_PREFIX?: string;
/** Whether to automatically detect updates after configuring application packaging */ /** Whether to automatically detect updates after configuring application packaging */
readonly VITE_AUTOMATICALLY_DETECT_UPDATE?: CommonType.YesOrNo; readonly VITE_AUTOMATICALLY_DETECT_UPDATE?: CommonType.YesOrNo;
/** show proxy url log in terminal */
readonly VITE_PROXY_LOG?: CommonType.YesOrNo;
} }
} }

View File

@ -2,10 +2,10 @@
import { computed } from 'vue'; import { computed } from 'vue';
import type { Component } from 'vue'; import type { Component } from 'vue';
import { getPaletteColorByNumber, mixColor } from '@sa/color'; import { getPaletteColorByNumber, mixColor } from '@sa/color';
import { $t } from '@/locales'; import { loginModuleRecord } from '@/constants/app';
import { useAppStore } from '@/store/modules/app'; import { useAppStore } from '@/store/modules/app';
import { useThemeStore } from '@/store/modules/theme'; import { useThemeStore } from '@/store/modules/theme';
import { loginModuleRecord } from '@/constants/app'; import { $t } from '@/locales';
import PwdLogin from './modules/pwd-login.vue'; import PwdLogin from './modules/pwd-login.vue';
import CodeLogin from './modules/code-login.vue'; import CodeLogin from './modules/code-login.vue';
import Register from './modules/register.vue'; import Register from './modules/register.vue';
@ -66,6 +66,7 @@ const bgColor = computed(() => {
@switch="themeStore.toggleThemeScheme" @switch="themeStore.toggleThemeScheme"
/> />
<LangSwitch <LangSwitch
v-if="themeStore.header.multilingual.visible"
:lang="appStore.locale" :lang="appStore.locale"
:lang-options="appStore.localeOptions" :lang-options="appStore.localeOptions"
:show-tooltip="false" :show-tooltip="false"

View File

@ -1,9 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, reactive } from 'vue'; import { computed, reactive } from 'vue';
import { $t } from '@/locales';
import { useRouterPush } from '@/hooks/common/router'; import { useRouterPush } from '@/hooks/common/router';
import { useFormRules, useNaiveForm } from '@/hooks/common/form'; import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import { useCaptcha } from '@/hooks/business/captcha'; import { useCaptcha } from '@/hooks/business/captcha';
import { $t } from '@/locales';
defineOptions({ defineOptions({
name: 'CodeLogin' name: 'CodeLogin'

View File

@ -1,10 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, reactive } from 'vue'; import { computed, reactive } from 'vue';
import { $t } from '@/locales';
import { loginModuleRecord } from '@/constants/app'; import { loginModuleRecord } from '@/constants/app';
import { useAuthStore } from '@/store/modules/auth';
import { useRouterPush } from '@/hooks/common/router'; import { useRouterPush } from '@/hooks/common/router';
import { useFormRules, useNaiveForm } from '@/hooks/common/form'; import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import { useAuthStore } from '@/store/modules/auth'; import { $t } from '@/locales';
defineOptions({ defineOptions({
name: 'PwdLogin' name: 'PwdLogin'

View File

@ -1,9 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, reactive } from 'vue'; import { computed, reactive } from 'vue';
import { $t } from '@/locales';
import { useRouterPush } from '@/hooks/common/router'; import { useRouterPush } from '@/hooks/common/router';
import { useFormRules, useNaiveForm } from '@/hooks/common/form'; import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import { useCaptcha } from '@/hooks/business/captcha'; import { useCaptcha } from '@/hooks/business/captcha';
import { $t } from '@/locales';
defineOptions({ defineOptions({
name: 'Register' name: 'Register'

View File

@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, reactive } from 'vue'; import { computed, reactive } from 'vue';
import { $t } from '@/locales';
import { useRouterPush } from '@/hooks/common/router'; import { useRouterPush } from '@/hooks/common/router';
import { useFormRules, useNaiveForm } from '@/hooks/common/form'; import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import { $t } from '@/locales';
defineOptions({ defineOptions({
name: 'ResetPwd' name: 'ResetPwd'

View File

@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from 'vue';
import { $t } from '@/locales';
import { useAppStore } from '@/store/modules/app'; import { useAppStore } from '@/store/modules/app';
import { useAuthStore } from '@/store/modules/auth'; import { useAuthStore } from '@/store/modules/auth';
import { $t } from '@/locales';
defineOptions({ defineOptions({
name: 'HeaderBanner' name: 'HeaderBanner'

View File

@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { watch } from 'vue'; import { watch } from 'vue';
import { $t } from '@/locales';
import { useAppStore } from '@/store/modules/app'; import { useAppStore } from '@/store/modules/app';
import { useEcharts } from '@/hooks/common/echarts'; import { useEcharts } from '@/hooks/common/echarts';
import { $t } from '@/locales';
defineOptions({ defineOptions({
name: 'LineChart' name: 'LineChart'

View File

@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { watch } from 'vue'; import { watch } from 'vue';
import { $t } from '@/locales';
import { useAppStore } from '@/store/modules/app'; import { useAppStore } from '@/store/modules/app';
import { useEcharts } from '@/hooks/common/echarts'; import { useEcharts } from '@/hooks/common/echarts';
import { $t } from '@/locales';
defineOptions({ defineOptions({
name: 'PieChart' name: 'PieChart'

View File

@ -184,6 +184,7 @@ const basicGanttOption: VTableGantt.GanttConstructorOptions = {
}, },
markLine: [ markLine: [
{ {
content: '',
date: '2024-07-28', date: '2024-07-28',
style: { style: {
lineWidth: 1, lineWidth: 1,
@ -192,6 +193,7 @@ const basicGanttOption: VTableGantt.GanttConstructorOptions = {
} }
}, },
{ {
content: '',
date: '2024-08-17', date: '2024-08-17',
style: { style: {
lineWidth: 2, lineWidth: 2,
@ -705,6 +707,7 @@ const customGanttOption: VTableGantt.GanttConstructorOptions = {
maxDate: '2024-08-15', maxDate: '2024-08-15',
markLine: [ markLine: [
{ {
content: '',
date: '2024-07-29', date: '2024-07-29',
style: { style: {
lineWidth: 1, lineWidth: 1,
@ -713,6 +716,7 @@ const customGanttOption: VTableGantt.GanttConstructorOptions = {
} }
}, },
{ {
content: '',
date: '2024-08-17', date: '2024-08-17',
style: { style: {
lineWidth: 2, lineWidth: 2,

View File

@ -1,7 +1,7 @@
import { defineConfig } from '@unocss/vite'; import { defineConfig } from '@unocss/vite';
import transformerDirectives from '@unocss/transformer-directives'; import transformerDirectives from '@unocss/transformer-directives';
import transformerVariantGroup from '@unocss/transformer-variant-group'; import transformerVariantGroup from '@unocss/transformer-variant-group';
import presetUno from '@unocss/preset-uno'; import presetWind3 from '@unocss/preset-wind3';
import type { Theme } from '@unocss/preset-uno'; import type { Theme } from '@unocss/preset-uno';
import { presetSoybeanAdmin } from '@sa/uno-preset'; import { presetSoybeanAdmin } from '@sa/uno-preset';
import { themeVars } from './src/theme/vars'; import { themeVars } from './src/theme/vars';
@ -26,5 +26,5 @@ export default defineConfig<Theme>({
'card-wrapper': 'rd-8px shadow-sm' 'card-wrapper': 'rd-8px shadow-sm'
}, },
transformers: [transformerDirectives(), transformerVariantGroup()], transformers: [transformerDirectives(), transformerVariantGroup()],
presets: [presetUno({ dark: 'class' }), presetSoybeanAdmin()] presets: [presetWind3({ dark: 'class' }), presetSoybeanAdmin()]
}); });