merge(sj_1.0.0_beta4): 合并 sa 1.1.4
This commit is contained in:
parent
734d5bf97d
commit
d239e2f249
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -14,5 +14,6 @@
|
|||||||
"i18n-ally.localesPaths": ["src/locales/langs", "packages/work-flow/src/locales/langs"],
|
"i18n-ally.localesPaths": ["src/locales/langs", "packages/work-flow/src/locales/langs"],
|
||||||
"prettier.enable": false,
|
"prettier.enable": false,
|
||||||
"typescript.tsdk": "node_modules/typescript/lib",
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
"unocss.root": ["./"]
|
"unocss.root": ["./"],
|
||||||
|
"vue.server.hybridMode": true
|
||||||
}
|
}
|
||||||
|
13
build/plugins/html.ts
Normal file
13
build/plugins/html.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import type { Plugin } from 'vite';
|
||||||
|
|
||||||
|
export function setupHtmlPlugin(buildTime: string) {
|
||||||
|
const plugin: Plugin = {
|
||||||
|
name: 'html-plugin',
|
||||||
|
apply: 'build',
|
||||||
|
transformIndexHtml(html) {
|
||||||
|
return html.replace('<head>', `<head>\n <meta name="buildTime" content="${buildTime}">`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
}
|
@ -6,8 +6,9 @@ import progress from 'vite-plugin-progress';
|
|||||||
import { setupElegantRouter } from './router';
|
import { setupElegantRouter } from './router';
|
||||||
import { setupUnocss } from './unocss';
|
import { setupUnocss } from './unocss';
|
||||||
import { setupUnplugin } from './unplugin';
|
import { setupUnplugin } from './unplugin';
|
||||||
|
import { setupHtmlPlugin } from './html';
|
||||||
|
|
||||||
export function setupVitePlugins(viteEnv: Env.ImportMeta) {
|
export function setupVitePlugins(viteEnv: Env.ImportMeta, buildTime: string) {
|
||||||
const plugins: PluginOption = [
|
const plugins: PluginOption = [
|
||||||
vue({
|
vue({
|
||||||
script: {
|
script: {
|
||||||
@ -19,7 +20,8 @@ export function setupVitePlugins(viteEnv: Env.ImportMeta) {
|
|||||||
setupElegantRouter(),
|
setupElegantRouter(),
|
||||||
setupUnocss(viteEnv),
|
setupUnocss(viteEnv),
|
||||||
...setupUnplugin(viteEnv),
|
...setupUnplugin(viteEnv),
|
||||||
progress()
|
progress(),
|
||||||
|
setupHtmlPlugin(buildTime)
|
||||||
];
|
];
|
||||||
|
|
||||||
return plugins;
|
return plugins;
|
||||||
|
@ -7,7 +7,7 @@ export default defineConfig(
|
|||||||
'vue/multi-word-component-names': [
|
'vue/multi-word-component-names': [
|
||||||
'warn',
|
'warn',
|
||||||
{
|
{
|
||||||
ignores: ['index', 'App', '[id]', '[url]']
|
ignores: ['index', 'App', 'Register', '[id]', '[url]']
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'vue/component-name-in-template-casing': [
|
'vue/component-name-in-template-casing': [
|
||||||
|
41
package.json
41
package.json
@ -57,7 +57,7 @@
|
|||||||
"@sa/materials": "workspace:*",
|
"@sa/materials": "workspace:*",
|
||||||
"@sa/utils": "workspace:*",
|
"@sa/utils": "workspace:*",
|
||||||
"@sa/workflow": "workspace:*",
|
"@sa/workflow": "workspace:*",
|
||||||
"@vueuse/core": "10.9.0",
|
"@vueuse/core": "10.10.0",
|
||||||
"clipboard": "2.0.11",
|
"clipboard": "2.0.11",
|
||||||
"dayjs": "1.11.11",
|
"dayjs": "1.11.11",
|
||||||
"echarts": "5.5.0",
|
"echarts": "5.5.0",
|
||||||
@ -65,44 +65,45 @@
|
|||||||
"naive-ui": "2.38.2",
|
"naive-ui": "2.38.2",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"pinia": "2.1.7",
|
"pinia": "2.1.7",
|
||||||
|
"tailwind-merge": "^2.3.0",
|
||||||
"ts-md5": "1.3.1",
|
"ts-md5": "1.3.1",
|
||||||
"vue": "3.4.27",
|
"vue": "3.4.27",
|
||||||
"vue-codemirror6": "^1.3.0",
|
"vue-codemirror6": "^1.3.0",
|
||||||
"vue-draggable-plus": "0.4.1",
|
"vue-draggable-plus": "0.5.0",
|
||||||
"vue-i18n": "9.13.1",
|
"vue-i18n": "9.13.1",
|
||||||
"vue-router": "4.3.2"
|
"vue-router": "4.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@elegant-router/vue": "0.3.7",
|
"@elegant-router/vue": "0.3.7",
|
||||||
"@iconify/json": "2.2.211",
|
"@iconify/json": "2.2.216",
|
||||||
"@sa/scripts": "workspace:*",
|
"@sa/scripts": "workspace:*",
|
||||||
"@sa/uno-preset": "workspace:*",
|
"@sa/uno-preset": "workspace:*",
|
||||||
"@soybeanjs/eslint-config": "1.3.5",
|
"@soybeanjs/eslint-config": "1.3.6",
|
||||||
"@types/lodash-es": "4.17.12",
|
"@types/lodash-es": "4.17.12",
|
||||||
"@types/node": "20.12.12",
|
"@types/node": "20.14.2",
|
||||||
"@types/nprogress": "0.2.3",
|
"@types/nprogress": "0.2.3",
|
||||||
"@unocss/eslint-config": "0.60.2",
|
"@unocss/eslint-config": "0.60.4",
|
||||||
"@unocss/preset-icons": "0.60.2",
|
"@unocss/preset-icons": "0.60.4",
|
||||||
"@unocss/preset-uno": "0.60.2",
|
"@unocss/preset-uno": "0.60.4",
|
||||||
"@unocss/transformer-directives": "0.60.2",
|
"@unocss/transformer-directives": "0.60.4",
|
||||||
"@unocss/transformer-variant-group": "0.60.2",
|
"@unocss/transformer-variant-group": "0.60.4",
|
||||||
"@unocss/vite": "0.60.2",
|
"@unocss/vite": "0.60.4",
|
||||||
"@vitejs/plugin-vue": "5.0.4",
|
"@vitejs/plugin-vue": "5.0.5",
|
||||||
"@vitejs/plugin-vue-jsx": "3.1.0",
|
"@vitejs/plugin-vue-jsx": "4.0.0",
|
||||||
"eslint": "9.3.0",
|
"eslint": "9.4.0",
|
||||||
"eslint-plugin-vue": "9.26.0",
|
"eslint-plugin-vue": "9.26.0",
|
||||||
"lint-staged": "15.2.2",
|
"lint-staged": "15.2.5",
|
||||||
"sass": "1.77.2",
|
"sass": "1.77.4",
|
||||||
"simple-git-hooks": "2.11.1",
|
"simple-git-hooks": "2.11.1",
|
||||||
"tsx": "4.10.5",
|
"tsx": "4.12.0",
|
||||||
"typescript": "5.4.5",
|
"typescript": "5.4.5",
|
||||||
"unplugin-icons": "0.19.0",
|
"unplugin-icons": "0.19.0",
|
||||||
"unplugin-vue-components": "0.27.0",
|
"unplugin-vue-components": "0.27.0",
|
||||||
"vite": "5.2.11",
|
"vite": "5.2.12",
|
||||||
"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.2.0",
|
"vite-plugin-vue-devtools": "7.2.1",
|
||||||
"vue-eslint-parser": "9.4.2",
|
"vue-eslint-parser": "9.4.3",
|
||||||
"vue-tsc": "2.0.19"
|
"vue-tsc": "2.0.19"
|
||||||
},
|
},
|
||||||
"simple-git-hooks": {
|
"simple-git-hooks": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/axios",
|
"name": "@sa/axios",
|
||||||
"version": "1.1.2",
|
"version": "1.2.0",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
@ -11,8 +11,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sa/utils": "workspace:*",
|
"@sa/utils": "workspace:*",
|
||||||
"axios": "1.6.8",
|
"axios": "1.7.2",
|
||||||
"axios-retry": "4.2.0",
|
"axios-retry": "4.4.0",
|
||||||
"qs": "6.12.1"
|
"qs": "6.12.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
export const REQUEST_ID_KEY = 'X-Request-Id';
|
export const REQUEST_ID_KEY = 'X-Request-Id';
|
||||||
|
|
||||||
/** the backend error code key */
|
/** the backend error code key */
|
||||||
export const BACKEND_ERROR_CODE = 'BACKEND_ERROR';
|
export const BACKEND_ERROR_CODE = '0';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/color",
|
"name": "@sa/color",
|
||||||
"version": "1.1.2",
|
"version": "1.2.0",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/hooks",
|
"name": "@sa/hooks",
|
||||||
"version": "1.1.2",
|
"version": "1.2.0",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/materials",
|
"name": "@sa/materials",
|
||||||
"version": "1.1.2",
|
"version": "1.2.0",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/fetch",
|
"name": "@sa/fetch",
|
||||||
"version": "1.1.2",
|
"version": "1.2.0",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/scripts",
|
"name": "@sa/scripts",
|
||||||
"version": "1.1.2",
|
"version": "1.2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
"sa": "./bin.ts"
|
"sa": "./bin.ts"
|
||||||
},
|
},
|
||||||
@ -13,7 +13,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@soybeanjs/changelog": "0.3.23",
|
"@soybeanjs/changelog": "0.3.24",
|
||||||
"bumpp": "9.4.1",
|
"bumpp": "9.4.1",
|
||||||
"c12": "1.10.0",
|
"c12": "1.10.0",
|
||||||
"cac": "6.7.14",
|
"cac": "6.7.14",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/uno-preset",
|
"name": "@sa/uno-preset",
|
||||||
"version": "1.1.2",
|
"version": "1.2.0",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/utils",
|
"name": "@sa/utils",
|
||||||
"version": "1.1.2",
|
"version": "1.2.0",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
2146
pnpm-lock.yaml
2146
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -21,10 +21,10 @@ const columns = defineModel<NaiveUI.TableColumnCheck[]>('columns', {
|
|||||||
{{ $t('common.columnSetting') }}
|
{{ $t('common.columnSetting') }}
|
||||||
</NButton>
|
</NButton>
|
||||||
</template>
|
</template>
|
||||||
<VueDraggable v-model="columns">
|
<VueDraggable v-model="columns" :animation="150" filter=".none_draggable">
|
||||||
<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 cursor-move text-icon" />
|
<icon-mdi-drag class="mr-8px h-full cursor-move text-icon" />
|
||||||
<NCheckbox v-model:checked="item.checked">
|
<NCheckbox v-model:checked="item.checked" class="none_draggable flex-1">
|
||||||
{{ item.title }}
|
{{ item.title }}
|
||||||
</NCheckbox>
|
</NCheckbox>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue';
|
|
||||||
import { createReusableTemplate } from '@vueuse/core';
|
|
||||||
import type { PopoverPlacement } from 'naive-ui';
|
import type { PopoverPlacement } from 'naive-ui';
|
||||||
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'ButtonIcon',
|
name: 'ButtonIcon',
|
||||||
@ -21,60 +20,29 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
class: 'h-36px text-icon',
|
class: '',
|
||||||
icon: '',
|
icon: '',
|
||||||
tooltipContent: '',
|
tooltipContent: '',
|
||||||
tooltipPlacement: 'bottom',
|
tooltipPlacement: 'bottom',
|
||||||
zIndex: 98
|
zIndex: 98
|
||||||
});
|
});
|
||||||
|
|
||||||
interface ButtonProps {
|
const DEFAULT_CLASS = 'h-[36px] text-icon';
|
||||||
className: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const [DefineButton, Button] = createReusableTemplate<ButtonProps>();
|
|
||||||
|
|
||||||
const cls = computed(() => {
|
|
||||||
let clsStr = props.class;
|
|
||||||
|
|
||||||
if (!clsStr.includes('h-')) {
|
|
||||||
clsStr += ' h-36px';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!clsStr.includes('text-')) {
|
|
||||||
clsStr += ' text-icon';
|
|
||||||
}
|
|
||||||
|
|
||||||
return clsStr;
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<!-- define component start: Button -->
|
<NTooltip :placement="tooltipPlacement" :z-index="zIndex" :disabled="!tooltipContent">
|
||||||
<DefineButton v-slot="{ $slots, className }">
|
|
||||||
<NButton quaternary :class="className">
|
|
||||||
<div class="flex-center gap-8px">
|
|
||||||
<component :is="$slots.default" />
|
|
||||||
</div>
|
|
||||||
</NButton>
|
|
||||||
</DefineButton>
|
|
||||||
<!-- define component end: Button -->
|
|
||||||
|
|
||||||
<NTooltip v-if="tooltipContent" :placement="tooltipPlacement" :z-index="zIndex">
|
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<Button :class-name="cls" v-bind="$attrs">
|
<NButton quaternary :class="twMerge(DEFAULT_CLASS, props.class)" v-bind="$attrs">
|
||||||
|
<div class="flex-center gap-8px">
|
||||||
<slot>
|
<slot>
|
||||||
<SvgIcon :icon="icon" />
|
<SvgIcon :icon="icon" />
|
||||||
</slot>
|
</slot>
|
||||||
</Button>
|
</div>
|
||||||
|
</NButton>
|
||||||
</template>
|
</template>
|
||||||
{{ tooltipContent }}
|
{{ tooltipContent }}
|
||||||
</NTooltip>
|
</NTooltip>
|
||||||
<Button v-else :class-name="cls" v-bind="$attrs">
|
|
||||||
<slot>
|
|
||||||
<SvgIcon :icon="icon" />
|
|
||||||
</slot>
|
|
||||||
</Button>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -34,9 +34,9 @@ function search() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleClose() {
|
function handleClose() {
|
||||||
visible.value = false;
|
|
||||||
// handle with setTimeout to prevent user from seeing some operations
|
// handle with setTimeout to prevent user from seeing some operations
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
visible.value = false;
|
||||||
resultOptions.value = [];
|
resultOptions.value = [];
|
||||||
keyword.value = '';
|
keyword.value = '';
|
||||||
}, 200);
|
}, 200);
|
||||||
@ -112,7 +112,7 @@ registerShortcut();
|
|||||||
|
|
||||||
<div class="mt-20px">
|
<div class="mt-20px">
|
||||||
<NEmpty v-if="resultOptions.length === 0" :description="$t('common.noData')" />
|
<NEmpty v-if="resultOptions.length === 0" :description="$t('common.noData')" />
|
||||||
<SearchResult v-else v-model:path="activePath" :options="resultOptions" @enter.prevent="handleEnter" />
|
<SearchResult v-else v-model:path="activePath" :options="resultOptions" @enter="handleEnter" />
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<SearchFooter v-if="!isMobile" />
|
<SearchFooter v-if="!isMobile" />
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
const local: App.I18n.Schema = {
|
const local: App.I18n.Schema = {
|
||||||
system: {
|
system: {
|
||||||
title: 'Snail Job',
|
title: 'Snail Job',
|
||||||
desc: 'A flexible, reliable, and fast platform for distributed task retry and distributed task scheduling.'
|
desc: 'A flexible, reliable, and fast platform for distributed task retry and distributed task scheduling.',
|
||||||
|
updateTitle: 'System Version Update Notification',
|
||||||
|
updateContent: 'A new version of the system has been detected. Do you want to refresh the page immediately?',
|
||||||
|
updateConfirm: 'Refresh immediately',
|
||||||
|
updateCancel: 'Later'
|
||||||
},
|
},
|
||||||
common: {
|
common: {
|
||||||
action: 'Action',
|
action: 'Action',
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
const local: App.I18n.Schema = {
|
const local: App.I18n.Schema = {
|
||||||
system: {
|
system: {
|
||||||
title: 'Snail Job',
|
title: 'Snail Job',
|
||||||
desc: '灵活,可靠和快速的分布式任务重试和分布式任务调度平台'
|
desc: '灵活,可靠和快速的分布式任务重试和分布式任务调度平台',
|
||||||
|
updateTitle: '系统版本更新通知',
|
||||||
|
updateContent: '检测到系统有新版本发布,是否立即刷新页面?',
|
||||||
|
updateConfirm: '立即刷新',
|
||||||
|
updateCancel: '稍后再说'
|
||||||
},
|
},
|
||||||
common: {
|
common: {
|
||||||
action: '操作',
|
action: '操作',
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { createApp } from 'vue';
|
import { createApp } from 'vue';
|
||||||
import './plugins/assets';
|
import './plugins/assets';
|
||||||
import { setupDayjs, setupIconifyOffline, setupLoading, setupNProgress } from './plugins';
|
import { setupAppVersionNotification, setupDayjs, setupIconifyOffline, setupLoading, setupNProgress } from './plugins';
|
||||||
import { setupStore } from './store';
|
import { setupStore } from './store';
|
||||||
import { setupRouter } from './router';
|
import { setupRouter } from './router';
|
||||||
import { setupI18n } from './locales';
|
import { setupI18n } from './locales';
|
||||||
@ -23,6 +23,8 @@ async function setupApp() {
|
|||||||
|
|
||||||
setupI18n(app);
|
setupI18n(app);
|
||||||
|
|
||||||
|
setupAppVersionNotification();
|
||||||
|
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
53
src/plugins/app.ts
Normal file
53
src/plugins/app.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { h } from 'vue';
|
||||||
|
import { NButton } from 'naive-ui';
|
||||||
|
import { $t } from '../locales';
|
||||||
|
|
||||||
|
export function setupAppVersionNotification() {
|
||||||
|
document.addEventListener('visibilitychange', async () => {
|
||||||
|
const buildTime = await getHtmlBuildTime();
|
||||||
|
|
||||||
|
if (buildTime !== BUILD_TIME && document.visibilityState === 'visible') {
|
||||||
|
const n = window.$notification?.create({
|
||||||
|
title: $t('system.updateTitle'),
|
||||||
|
content: $t('system.updateContent'),
|
||||||
|
action() {
|
||||||
|
return h('div', { style: { display: 'flex', justifyContent: 'end', gap: '12px', width: '325px' } }, [
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
onClick() {
|
||||||
|
n?.destroy();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
$t('system.updateCancel')
|
||||||
|
),
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
type: 'primary',
|
||||||
|
onClick() {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
$t('system.updateConfirm')
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getHtmlBuildTime() {
|
||||||
|
const baseURL = import.meta.env.VITE_BASE_URL;
|
||||||
|
|
||||||
|
const res = await fetch(`${baseURL}index.html`);
|
||||||
|
|
||||||
|
const html = await res.text();
|
||||||
|
|
||||||
|
const match = html.match(/<meta name="buildTime" content="(.*)">/);
|
||||||
|
|
||||||
|
const buildTime = match?.[1] || '';
|
||||||
|
|
||||||
|
return buildTime;
|
||||||
|
}
|
@ -2,3 +2,4 @@ export * from './loading';
|
|||||||
export * from './nprogress';
|
export * from './nprogress';
|
||||||
export * from './iconify';
|
export * from './iconify';
|
||||||
export * from './dayjs';
|
export * from './dayjs';
|
||||||
|
export * from './app';
|
||||||
|
@ -48,7 +48,7 @@ export function createRouteGuard(router: Router) {
|
|||||||
next({ name: rootRoute });
|
next({ name: rootRoute });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// if is is constant route, then it is allowed to access directly
|
// if it is constant route, then it is allowed to access directly
|
||||||
{
|
{
|
||||||
condition: !needLogin,
|
condition: !needLogin,
|
||||||
callback: () => {
|
callback: () => {
|
||||||
@ -97,6 +97,7 @@ export function createRouteGuard(router: Router) {
|
|||||||
* @param to to route
|
* @param to to route
|
||||||
*/
|
*/
|
||||||
async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw | null> {
|
async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw | null> {
|
||||||
|
const authStore = useAuthStore();
|
||||||
const routeStore = useRouteStore();
|
const routeStore = useRouteStore();
|
||||||
|
|
||||||
const notFoundRoute: RouteKey = 'not-found';
|
const notFoundRoute: RouteKey = 'not-found';
|
||||||
@ -130,6 +131,15 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
|
|||||||
// the auth route is initialized
|
// the auth route is initialized
|
||||||
// it is not the "not-found" route, then it is allowed to access
|
// it is not the "not-found" route, then it is allowed to access
|
||||||
if (routeStore.isInitAuthRoute && !isNotFoundRoute) {
|
if (routeStore.isInitAuthRoute && !isNotFoundRoute) {
|
||||||
|
// update user info
|
||||||
|
await authStore.updateUserInfo();
|
||||||
|
const { data, error } = await fetchVersion();
|
||||||
|
if (!error && data) {
|
||||||
|
localStg.set('version', data!);
|
||||||
|
} else {
|
||||||
|
localStg.remove('version');
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// it is captured by the "not-found" route, then check whether the route exists
|
// it is captured by the "not-found" route, then check whether the route exists
|
||||||
@ -165,19 +175,6 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
|
|||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLogin) {
|
|
||||||
if (to.path !== '/pwd-login') {
|
|
||||||
const authStore = useAuthStore();
|
|
||||||
await authStore.getInfo();
|
|
||||||
const { data, error } = await fetchVersion();
|
|
||||||
if (!error && data) {
|
|
||||||
localStg.set('version', data!);
|
|
||||||
} else {
|
|
||||||
localStg.remove('version');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize the auth route
|
// initialize the auth route
|
||||||
await routeStore.initAuthRoute();
|
await routeStore.initAuthRoute();
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
|
|||||||
content: $t('request.logoutWithModalMsg'),
|
content: $t('request.logoutWithModalMsg'),
|
||||||
positiveText: $t('common.confirm'),
|
positiveText: $t('common.confirm'),
|
||||||
maskClosable: false,
|
maskClosable: false,
|
||||||
|
closeOnEsc: false,
|
||||||
onPositiveClick() {
|
onPositiveClick() {
|
||||||
request.state.isLogout = false;
|
request.state.isLogout = false;
|
||||||
logoutAndCleanup();
|
logoutAndCleanup();
|
||||||
|
@ -36,9 +36,6 @@ export function showErrorMsg(state: RequestInstanceState, message: string) {
|
|||||||
state.errMsgStack = [];
|
state.errMsgStack = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const isExist = state.errMsgStack.includes(message);
|
|
||||||
|
|
||||||
if (!isExist) {
|
|
||||||
state.errMsgStack.push(message);
|
state.errMsgStack.push(message);
|
||||||
|
|
||||||
window.$message?.error(message, {
|
window.$message?.error(message, {
|
||||||
@ -51,4 +48,3 @@ export function showErrorMsg(state: RequestInstanceState, message: string) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -125,7 +125,7 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
|||||||
// update tabs by locale
|
// update tabs by locale
|
||||||
tabStore.updateTabsByLocale();
|
tabStore.updateTabsByLocale();
|
||||||
|
|
||||||
// sey dayjs locale
|
// set dayjs locale
|
||||||
setDayjsLocale(locale.value);
|
setDayjsLocale(locale.value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -9,7 +9,7 @@ import { localStg } from '@/utils/storage';
|
|||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
import { roleTypeRecord } from '@/constants/business';
|
import { roleTypeRecord } from '@/constants/business';
|
||||||
import { useRouteStore } from '../route';
|
import { useRouteStore } from '../route';
|
||||||
import { clearAuthStorage, getToken, getUserInfo } from './shared';
|
import { clearAuthStorage, getToken } from './shared';
|
||||||
|
|
||||||
export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@ -19,7 +19,17 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
|||||||
|
|
||||||
const token = ref(getToken());
|
const token = ref(getToken());
|
||||||
|
|
||||||
const userInfo: Api.Auth.UserInfo = reactive(getUserInfo());
|
const userInfo: Api.Auth.UserInfo = reactive({
|
||||||
|
id: '',
|
||||||
|
userId: '',
|
||||||
|
mode: '',
|
||||||
|
role: 1,
|
||||||
|
username: '',
|
||||||
|
userName: '',
|
||||||
|
roles: [],
|
||||||
|
buttons: [],
|
||||||
|
namespaceIds: []
|
||||||
|
});
|
||||||
|
|
||||||
/** is super role in static route */
|
/** is super role in static route */
|
||||||
const isStaticSuper = computed(() => {
|
const isStaticSuper = computed(() => {
|
||||||
@ -98,22 +108,32 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
|||||||
localStg.set('userNamespace', userNamespace);
|
localStg.set('userNamespace', userNamespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. get user info and update store
|
||||||
|
const pass = await updateUserInfo();
|
||||||
|
|
||||||
|
if (pass) {
|
||||||
|
token.value = loginToken.token;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateUserInfo() {
|
||||||
const { data: info, error } = await fetchGetUserInfo();
|
const { data: info, error } = await fetchGetUserInfo();
|
||||||
|
|
||||||
if (!error) {
|
if (!error) {
|
||||||
info!.userId = info?.id;
|
// update store
|
||||||
info!.userName = info?.username;
|
info!.userName = info?.username;
|
||||||
info!.roles = [roleTypeRecord[info.role]];
|
info!.roles = [roleTypeRecord[info.role]];
|
||||||
// 2. store user info
|
|
||||||
localStg.set('userInfo', info);
|
localStg.set('userInfo', info);
|
||||||
|
|
||||||
// 3. update store
|
|
||||||
token.value = loginToken.token;
|
|
||||||
Object.assign(userInfo, info);
|
Object.assign(userInfo, info);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await resetStore();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,21 +144,6 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
|||||||
localStg.set('namespaceId', namespaceId);
|
localStg.set('namespaceId', namespaceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getInfo() {
|
|
||||||
const { data: info, error } = await fetchGetUserInfo();
|
|
||||||
|
|
||||||
if (!error) {
|
|
||||||
info!.userName = info?.username;
|
|
||||||
info!.roles = [roleTypeRecord[info.role]];
|
|
||||||
localStg.set('userInfo', info);
|
|
||||||
Object.assign(userInfo, info);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
resetStore();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
token,
|
token,
|
||||||
userInfo,
|
userInfo,
|
||||||
@ -147,7 +152,7 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
|||||||
loginLoading,
|
loginLoading,
|
||||||
resetStore,
|
resetStore,
|
||||||
login,
|
login,
|
||||||
getInfo,
|
updateUserInfo,
|
||||||
setNamespaceId
|
setNamespaceId
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -97,13 +97,19 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
|||||||
/** Cache routes */
|
/** Cache routes */
|
||||||
const cacheRoutes = ref<RouteKey[]>([]);
|
const cacheRoutes = ref<RouteKey[]>([]);
|
||||||
|
|
||||||
|
/** All cache routes */
|
||||||
|
const allCacheRoutes = shallowRef<RouteKey[]>([]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get cache routes
|
* Get cache routes
|
||||||
*
|
*
|
||||||
* @param routes Vue routes
|
* @param routes Vue routes
|
||||||
*/
|
*/
|
||||||
function getCacheRoutes(routes: RouteRecordRaw[]) {
|
function getCacheRoutes(routes: RouteRecordRaw[]) {
|
||||||
cacheRoutes.value = getCacheRouteNames(routes);
|
const alls = getCacheRouteNames(routes);
|
||||||
|
|
||||||
|
cacheRoutes.value = alls;
|
||||||
|
allCacheRoutes.value = [...alls];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,12 +136,23 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
|||||||
cacheRoutes.value.splice(index, 1);
|
cacheRoutes.value.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is cached route
|
||||||
|
*
|
||||||
|
* @param routeKey
|
||||||
|
*/
|
||||||
|
function isCachedRoute(routeKey: RouteKey) {
|
||||||
|
return allCacheRoutes.value.includes(routeKey);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Re cache routes by route key
|
* Re cache routes by route key
|
||||||
*
|
*
|
||||||
* @param routeKey
|
* @param routeKey
|
||||||
*/
|
*/
|
||||||
async function reCacheRoutesByKey(routeKey: RouteKey) {
|
async function reCacheRoutesByKey(routeKey: RouteKey) {
|
||||||
|
if (!isCachedRoute(routeKey)) return;
|
||||||
|
|
||||||
removeCacheRoutes(routeKey);
|
removeCacheRoutes(routeKey);
|
||||||
|
|
||||||
await appStore.reloadPage();
|
await appStore.reloadPage();
|
||||||
|
4
src/typings/app.d.ts
vendored
4
src/typings/app.d.ts
vendored
@ -252,6 +252,10 @@ declare namespace App {
|
|||||||
system: {
|
system: {
|
||||||
title: string;
|
title: string;
|
||||||
desc: string;
|
desc: string;
|
||||||
|
updateTitle: string;
|
||||||
|
updateContent: string;
|
||||||
|
updateConfirm: string;
|
||||||
|
updateCancel: string;
|
||||||
};
|
};
|
||||||
common: {
|
common: {
|
||||||
action: string;
|
action: string;
|
||||||
|
7
src/typings/router.d.ts
vendored
7
src/typings/router.d.ts
vendored
@ -27,7 +27,7 @@ declare module 'vue-router' {
|
|||||||
/**
|
/**
|
||||||
* Is constant route
|
* Is constant route
|
||||||
*
|
*
|
||||||
* Does not need to login, and the route is defined in the front-end
|
* when it is set to true, there will be no login verification and no permission verification to access the route
|
||||||
*/
|
*/
|
||||||
constant?: boolean | null;
|
constant?: boolean | null;
|
||||||
/**
|
/**
|
||||||
@ -57,7 +57,10 @@ declare module 'vue-router' {
|
|||||||
* the route is "user_detail", if it is set to "user_list", the menu "user_list" will be activated
|
* the route is "user_detail", if it is set to "user_list", the menu "user_list" will be activated
|
||||||
*/
|
*/
|
||||||
activeMenu?: import('@elegant-router/types').RouteKey | null;
|
activeMenu?: import('@elegant-router/types').RouteKey | null;
|
||||||
/** By default, the same route path will use one tab, if set to true, it will use multiple tabs */
|
/**
|
||||||
|
* By default, the same route path will use one tab, even with different query, if set true, the route with
|
||||||
|
* different query will use different tabs
|
||||||
|
*/
|
||||||
multiTab?: boolean | null;
|
multiTab?: boolean | null;
|
||||||
/** If set, the route will be fixed in tabs, and the value is the order of fixed tabs */
|
/** If set, the route will be fixed in tabs, and the value is the order of fixed tabs */
|
||||||
fixedIndexInTab?: number | null;
|
fixedIndexInTab?: number | null;
|
||||||
|
@ -25,7 +25,7 @@ export default defineConfig(configEnv => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
plugins: setupVitePlugins(viteEnv),
|
plugins: setupVitePlugins(viteEnv, buildTime),
|
||||||
define: {
|
define: {
|
||||||
BUILD_TIME: JSON.stringify(buildTime)
|
BUILD_TIME: JSON.stringify(buildTime)
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user