web code format
This commit is contained in:
parent
1f5bded672
commit
a9fe6e4d5a
@ -1,16 +1,20 @@
|
|||||||
## 快速开始
|
## 快速开始
|
||||||
|
|
||||||
进入前端目录
|
进入前端目录
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd web
|
cd web
|
||||||
```
|
```
|
||||||
|
|
||||||
安装依赖(建议使用pnpm: https://pnpm.io/zh/installation)
|
安装依赖(建议使用pnpm: https://pnpm.io/zh/installation)
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm i -g pnpm # 已安装可忽略
|
npm i -g pnpm # 已安装可忽略
|
||||||
pnpm i # 或者 npm i
|
pnpm i # 或者 npm i
|
||||||
```
|
```
|
||||||
|
|
||||||
启动
|
启动
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pnpm dev
|
pnpm dev
|
||||||
```
|
```
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export function createVitePlugins(viteEnv, isBuild) {
|
|||||||
open: true,
|
open: true,
|
||||||
gzipSize: true,
|
gzipSize: true,
|
||||||
brotliSize: true,
|
brotliSize: true,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ const i18n = createI18n({
|
|||||||
globalInjection: true,
|
globalInjection: true,
|
||||||
locale: currentLocale || 'en',
|
locale: currentLocale || 'en',
|
||||||
fallbackLocale: 'en',
|
fallbackLocale: 'en',
|
||||||
messages: messages
|
messages: messages,
|
||||||
})
|
})
|
||||||
|
|
||||||
export default i18n
|
export default i18n
|
||||||
|
|||||||
@ -34,16 +34,16 @@
|
|||||||
"label_email": "邮箱",
|
"label_email": "邮箱",
|
||||||
"label_old_password": "旧密码",
|
"label_old_password": "旧密码",
|
||||||
"label_new_password": "新密码",
|
"label_new_password": "新密码",
|
||||||
"label_confirm_password": "确认密码",
|
"label_confirm_password": "确认密码",
|
||||||
"placeholder_username": "请填写姓名",
|
"placeholder_username": "请填写姓名",
|
||||||
"placeholder_email": "请填写邮箱",
|
"placeholder_email": "请填写邮箱",
|
||||||
"placeholder_old_password": "请输入旧密码",
|
"placeholder_old_password": "请输入旧密码",
|
||||||
"placeholder_new_password": "请输入新密码",
|
"placeholder_new_password": "请输入新密码",
|
||||||
"placeholder_confirm_password": "请再次输入新密码",
|
"placeholder_confirm_password": "请再次输入新密码",
|
||||||
"message_username_required": "请输入昵称",
|
"message_username_required": "请输入昵称",
|
||||||
"message_old_password_required": "请输入旧密码",
|
"message_old_password_required": "请输入旧密码",
|
||||||
"message_new_password_required": "请输入新密码",
|
"message_new_password_required": "请输入新密码",
|
||||||
"message_password_confirmation_required": "请再次输入密码",
|
"message_password_confirmation_required": "请再次输入密码",
|
||||||
"message_password_confirmation_diff": "两次密码输入不一致"
|
"message_password_confirmation_diff": "两次密码输入不一致"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
@ -59,4 +59,4 @@
|
|||||||
"update": "修改"
|
"update": "修改"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,7 +43,7 @@
|
|||||||
"message_username_required": "Please enter username",
|
"message_username_required": "Please enter username",
|
||||||
"message_old_password_required": "Please enter the old password",
|
"message_old_password_required": "Please enter the old password",
|
||||||
"message_new_password_required": "Please enter a new password",
|
"message_new_password_required": "Please enter a new password",
|
||||||
"message_password_confirmation_required": "Please enter confirm password",
|
"message_password_confirmation_required": "Please enter confirm password",
|
||||||
"message_password_confirmation_diff": "Two password inputs are inconsistent"
|
"message_password_confirmation_diff": "Two password inputs are inconsistent"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
@ -59,4 +59,4 @@
|
|||||||
"update": "Update"
|
"update": "Update"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,5 +3,5 @@ import * as cn from './cn.json'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
en,
|
en,
|
||||||
cn
|
cn,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="cn">
|
<html lang="cn">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
|
|||||||
@ -8,7 +8,8 @@
|
|||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"lint": "eslint --ext .js,.vue .",
|
"lint": "eslint --ext .js,.vue .",
|
||||||
"lint:fix": "eslint --fix --ext .js,.vue .",
|
"lint:fix": "eslint --fix --ext .js,.vue .",
|
||||||
"lint:staged": "lint-staged"
|
"lint:staged": "lint-staged",
|
||||||
|
"prettier": "npx prettier --write ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iconify/json": "^2.2.101",
|
"@iconify/json": "^2.2.101",
|
||||||
|
|||||||
3438
web/pnpm-lock.yaml
generated
3438
web/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,3 @@
|
|||||||
<template>
|
<template>
|
||||||
<footer f-c-c flex-col text-14 color="#6a6a6a">
|
<footer f-c-c flex-col text-14 color="#6a6a6a"></footer>
|
||||||
</footer>
|
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -22,13 +22,13 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { defineComponent, h } from 'vue'
|
import { defineComponent, h } from 'vue'
|
||||||
import {
|
import {
|
||||||
zhCN,
|
zhCN,
|
||||||
dateZhCN,
|
dateZhCN,
|
||||||
darkTheme,
|
darkTheme,
|
||||||
useLoadingBar,
|
useLoadingBar,
|
||||||
useDialog,
|
useDialog,
|
||||||
useMessage,
|
useMessage,
|
||||||
useNotification,
|
useNotification,
|
||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
import { useCssVar } from '@vueuse/core'
|
import { useCssVar } from '@vueuse/core'
|
||||||
import { kebabCase } from 'lodash-es'
|
import { kebabCase } from 'lodash-es'
|
||||||
|
|||||||
@ -53,7 +53,7 @@ const isEmpty = computed(() => props.empty && !props.loading && network.value)
|
|||||||
const showPlaceholder = computed(() => props.loading || isEmpty.value || !network.value)
|
const showPlaceholder = computed(() => props.loading || isEmpty.value || !network.value)
|
||||||
|
|
||||||
const networkErrorDesc = computed(() =>
|
const networkErrorDesc = computed(() =>
|
||||||
props.showNetworkReload ? `${NETWORK_ERROR_MSG}, 点击重试` : NETWORK_ERROR_MSG
|
props.showNetworkReload ? `${NETWORK_ERROR_MSG}, 点击重试` : NETWORK_ERROR_MSG,
|
||||||
)
|
)
|
||||||
|
|
||||||
function handleReload() {
|
function handleReload() {
|
||||||
@ -71,7 +71,7 @@ const stopHandle = watch(
|
|||||||
if (!newValue) {
|
if (!newValue) {
|
||||||
network.value = window.navigator.onLine
|
network.value = window.navigator.onLine
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
|||||||
@ -28,7 +28,7 @@ watchDebounced(
|
|||||||
filterIcons()
|
filterIcons()
|
||||||
emit('update:value', choosed.value)
|
emit('update:value', choosed.value)
|
||||||
},
|
},
|
||||||
{ debounce: 200 }
|
{ debounce: 200 },
|
||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,24 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<n-dropdown :options="options" @select="handleChangeLocale">
|
<n-dropdown :options="options" @select="handleChangeLocale">
|
||||||
<n-icon mr-20 size="18" style="cursor: pointer">
|
<n-icon mr-20 size="18" style="cursor: pointer">
|
||||||
<icon-mdi:globe/>
|
<icon-mdi:globe />
|
||||||
</n-icon>
|
</n-icon>
|
||||||
</n-dropdown>
|
</n-dropdown>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {useI18n} from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import {useAppStore} from "@/store";
|
import { useAppStore } from '@/store'
|
||||||
|
|
||||||
const store = useAppStore()
|
const store = useAppStore()
|
||||||
const { availableLocales, t } = useI18n()
|
const { availableLocales, t } = useI18n()
|
||||||
|
|
||||||
const options = computed(() => {
|
const options = computed(() => {
|
||||||
let select = []
|
let select = []
|
||||||
availableLocales.forEach(locale => {
|
availableLocales.forEach((locale) => {
|
||||||
select.push({
|
select.push({
|
||||||
label: t('lang', 1, {'locale': locale}),
|
label: t('lang', 1, { locale: locale }),
|
||||||
key: locale
|
key: locale,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return select
|
return select
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import { renderIcon } from '@/utils'
|
|||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
const {t} = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
|
|||||||
@ -19,5 +19,5 @@ import FullScreen from './components/FullScreen.vue'
|
|||||||
import UserAvatar from './components/UserAvatar.vue'
|
import UserAvatar from './components/UserAvatar.vue'
|
||||||
import GithubSite from './components/GithubSite.vue'
|
import GithubSite from './components/GithubSite.vue'
|
||||||
import ThemeMode from './components/ThemeMode.vue'
|
import ThemeMode from './components/ThemeMode.vue'
|
||||||
import Languages from './components/Languages.vue';
|
import Languages from './components/Languages.vue'
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -48,7 +48,7 @@ watch(
|
|||||||
const title = route.meta?.title
|
const title = route.meta?.title
|
||||||
tagsStore.addTag({ name, path, title })
|
tagsStore.addTag({ name, path, title })
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@ -60,7 +60,7 @@ watch(
|
|||||||
const { offsetLeft: x, offsetWidth: width } = activeTabElement
|
const { offsetLeft: x, offsetWidth: width } = activeTabElement
|
||||||
scrollXRef.value?.handleScroll(x + width, width)
|
scrollXRef.value?.handleScroll(x + width, width)
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleTagClick = (path) => {
|
const handleTagClick = (path) => {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import i18n from '~/i18n'
|
import i18n from '~/i18n'
|
||||||
const {t} = i18n.global
|
const { t } = i18n.global
|
||||||
|
|
||||||
const Layout = () => import('@/layout/index.vue')
|
const Layout = () => import('@/layout/index.vue')
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { sStorage } from '@/utils'
|
|||||||
import i18n from '~/i18n'
|
import i18n from '~/i18n'
|
||||||
|
|
||||||
const currentLocale = sStorage.get('locale')
|
const currentLocale = sStorage.get('locale')
|
||||||
const {locale} = i18n.global
|
const { locale } = i18n.global
|
||||||
|
|
||||||
const isDark = useDark()
|
const isDark = useDark()
|
||||||
export const useAppStore = defineStore('app', {
|
export const useAppStore = defineStore('app', {
|
||||||
@ -16,7 +16,7 @@ export const useAppStore = defineStore('app', {
|
|||||||
/** keepAlive路由的key,重新赋值可重置keepAlive */
|
/** keepAlive路由的key,重新赋值可重置keepAlive */
|
||||||
aliveKeys: {},
|
aliveKeys: {},
|
||||||
isDark,
|
isDark,
|
||||||
locale: currentLocale || 'en'
|
locale: currentLocale || 'en',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
@ -55,6 +55,6 @@ export const useAppStore = defineStore('app', {
|
|||||||
this.locale = newLocale
|
this.locale = newLocale
|
||||||
locale.value = newLocale
|
locale.value = newLocale
|
||||||
sStorage.set('locale', newLocale)
|
sStorage.set('locale', newLocale)
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,24 +1,22 @@
|
|||||||
export function useResize(el, cb) {
|
export function useResize(el, cb) {
|
||||||
const observer = new ResizeObserver((entries) => {
|
const observer = new ResizeObserver((entries) => {
|
||||||
cb(entries[0].contentRect);
|
cb(entries[0].contentRect)
|
||||||
});
|
})
|
||||||
observer.observe(el);
|
observer.observe(el)
|
||||||
return observer;
|
return observer
|
||||||
}
|
}
|
||||||
|
|
||||||
const install = (app) => {
|
const install = (app) => {
|
||||||
let observer;
|
let observer
|
||||||
|
|
||||||
app.directive('resize', {
|
app.directive('resize', {
|
||||||
mounted(el, binding) {
|
mounted(el, binding) {
|
||||||
observer = useResize(el, binding.value);
|
observer = useResize(el, binding.value)
|
||||||
},
|
},
|
||||||
beforeUnmount() {
|
beforeUnmount() {
|
||||||
observer?.disconnect();
|
observer?.disconnect()
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
useResize.install = install;
|
useResize.install = install
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,9 @@
|
|||||||
<icon-custom-unauthorized text-400px text-primary></icon-custom-unauthorized>
|
<icon-custom-unauthorized text-400px text-primary></icon-custom-unauthorized>
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<n-button type="primary" @click="replace('/')">{{ $t('views.errors.text_back_to_home') }}</n-button>
|
<n-button type="primary" @click="replace('/')">{{
|
||||||
|
$t('views.errors.text_back_to_home')
|
||||||
|
}}</n-button>
|
||||||
</template>
|
</template>
|
||||||
</n-result>
|
</n-result>
|
||||||
</AppPage>
|
</AppPage>
|
||||||
|
|||||||
@ -5,7 +5,9 @@
|
|||||||
<icon-custom-forbidden text-400px text-primary></icon-custom-forbidden>
|
<icon-custom-forbidden text-400px text-primary></icon-custom-forbidden>
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<n-button type="primary" @click="replace('/')">{{ $t('views.errors.text_back_to_home') }}</n-button>
|
<n-button type="primary" @click="replace('/')">{{
|
||||||
|
$t('views.errors.text_back_to_home')
|
||||||
|
}}</n-button>
|
||||||
</template>
|
</template>
|
||||||
</n-result>
|
</n-result>
|
||||||
</AppPage>
|
</AppPage>
|
||||||
|
|||||||
@ -5,7 +5,9 @@
|
|||||||
<icon-custom-not-found text-400px text-primary></icon-custom-not-found>
|
<icon-custom-not-found text-400px text-primary></icon-custom-not-found>
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<n-button type="primary" @click="replace('/')">{{ $t('views.errors.text_back_to_home') }}</n-button>
|
<n-button type="primary" @click="replace('/')">{{
|
||||||
|
$t('views.errors.text_back_to_home')
|
||||||
|
}}</n-button>
|
||||||
</template>
|
</template>
|
||||||
</n-result>
|
</n-result>
|
||||||
</AppPage>
|
</AppPage>
|
||||||
|
|||||||
@ -5,7 +5,9 @@
|
|||||||
<icon-custom-server-error text-400px text-primary></icon-custom-server-error>
|
<icon-custom-server-error text-400px text-primary></icon-custom-server-error>
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<n-button type="primary" @click="replace('/')">{{ $t('views.errors.text_back_to_home') }}</n-button>
|
<n-button type="primary" @click="replace('/')">{{
|
||||||
|
$t('views.errors.text_back_to_home')
|
||||||
|
}}</n-button>
|
||||||
</template>
|
</template>
|
||||||
</n-result>
|
</n-result>
|
||||||
</AppPage>
|
</AppPage>
|
||||||
|
|||||||
@ -57,11 +57,11 @@ import { lStorage, setToken } from '@/utils'
|
|||||||
import bgImg from '@/assets/images/login_bg.webp'
|
import bgImg from '@/assets/images/login_bg.webp'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import { addDynamicRoutes } from '@/router'
|
import { addDynamicRoutes } from '@/router'
|
||||||
import {useI18n} from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { query } = useRoute()
|
const { query } = useRoute()
|
||||||
const {t} = useI18n({ useScope: "global" })
|
const { t } = useI18n({ useScope: 'global' })
|
||||||
|
|
||||||
const loginInfo = ref({
|
const loginInfo = ref({
|
||||||
username: '',
|
username: '',
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { NButton, NForm, NFormItem, NInput, NTabPane, NTabs, NImage } from 'naive-ui'
|
import { NButton, NForm, NFormItem, NInput, NTabPane, NTabs, NImage } from 'naive-ui'
|
||||||
import {useI18n} from "vue-i18n";
|
import { useI18n } from 'vue-i18n'
|
||||||
import CommonPage from '@/components/page/CommonPage.vue'
|
import CommonPage from '@/components/page/CommonPage.vue'
|
||||||
import { useUserStore } from '@/store'
|
import { useUserStore } from '@/store'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import { is } from '~/src/utils'
|
import { is } from '~/src/utils'
|
||||||
|
|
||||||
const {t} = useI18n()
|
const { t } = useI18n()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
|
|
||||||
@ -137,12 +137,22 @@ function validatePasswordSame(rule, value) {
|
|||||||
<NImage width="100" :src="infoForm.avatar"></NImage>
|
<NImage width="100" :src="infoForm.avatar"></NImage>
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
<NFormItem :label="$t('views.profile.label_username')" path="username">
|
<NFormItem :label="$t('views.profile.label_username')" path="username">
|
||||||
<NInput v-model:value="infoForm.username" type="text" :placeholder="$t('views.profile.placeholder_username')" />
|
<NInput
|
||||||
|
v-model:value="infoForm.username"
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('views.profile.placeholder_username')"
|
||||||
|
/>
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
<NFormItem :label="$t('views.profile.label_email')" path="email">
|
<NFormItem :label="$t('views.profile.label_email')" path="email">
|
||||||
<NInput v-model:value="infoForm.email" type="text" :placeholder="$t('views.profile.placeholder_email')" />
|
<NInput
|
||||||
|
v-model:value="infoForm.email"
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('views.profile.placeholder_email')"
|
||||||
|
/>
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
<NButton type="primary" :loading="isLoading" @click="updateProfile"> {{$t("common.buttons.update")}} </NButton>
|
<NButton type="primary" :loading="isLoading" @click="updateProfile">
|
||||||
|
{{ $t('common.buttons.update') }}
|
||||||
|
</NButton>
|
||||||
</NForm>
|
</NForm>
|
||||||
</div>
|
</div>
|
||||||
</NTabPane>
|
</NTabPane>
|
||||||
@ -182,7 +192,9 @@ function validatePasswordSame(rule, value) {
|
|||||||
:placeholder="$t('views.profile.placeholder_confirm_password')"
|
:placeholder="$t('views.profile.placeholder_confirm_password')"
|
||||||
/>
|
/>
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
<NButton type="primary" :loading="isLoading" @click="updatePassword"> {{$t("common.buttons.update")}} </NButton>
|
<NButton type="primary" :loading="isLoading" @click="updatePassword">
|
||||||
|
{{ $t('common.buttons.update') }}
|
||||||
|
</NButton>
|
||||||
</NForm>
|
</NForm>
|
||||||
</NTabPane>
|
</NTabPane>
|
||||||
</NTabs>
|
</NTabs>
|
||||||
|
|||||||
@ -141,9 +141,9 @@ const columns = [
|
|||||||
{
|
{
|
||||||
default: () => '编辑',
|
default: () => '编辑',
|
||||||
icon: renderIcon('material-symbols:edit', { size: 16 }),
|
icon: renderIcon('material-symbols:edit', { size: 16 }),
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
[[vPermission, 'post/api/v1/api/update']]
|
[[vPermission, 'post/api/v1/api/update']],
|
||||||
),
|
),
|
||||||
h(
|
h(
|
||||||
NPopconfirm,
|
NPopconfirm,
|
||||||
@ -163,12 +163,12 @@ const columns = [
|
|||||||
{
|
{
|
||||||
default: () => '删除',
|
default: () => '删除',
|
||||||
icon: renderIcon('material-symbols:delete-outline', { size: 16 }),
|
icon: renderIcon('material-symbols:delete-outline', { size: 16 }),
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
[[vPermission, 'delete/api/v1/api/delete']]
|
[[vPermission, 'delete/api/v1/api/delete']],
|
||||||
),
|
),
|
||||||
default: () => h('div', {}, '确定删除该API吗?'),
|
default: () => h('div', {}, '确定删除该API吗?'),
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -135,9 +135,9 @@ const columns = [
|
|||||||
handleAdd()
|
handleAdd()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ default: () => '子菜单', icon: renderIcon('material-symbols:add', { size: 16 }) }
|
{ default: () => '子菜单', icon: renderIcon('material-symbols:add', { size: 16 }) },
|
||||||
),
|
),
|
||||||
[[vPermission, 'post/api/v1/menu/create']]
|
[[vPermission, 'post/api/v1/menu/create']],
|
||||||
),
|
),
|
||||||
withDirectives(
|
withDirectives(
|
||||||
h(
|
h(
|
||||||
@ -154,9 +154,9 @@ const columns = [
|
|||||||
{
|
{
|
||||||
default: () => '编辑',
|
default: () => '编辑',
|
||||||
icon: renderIcon('material-symbols:edit-outline', { size: 16 }),
|
icon: renderIcon('material-symbols:edit-outline', { size: 16 }),
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
[[vPermission, 'post/api/v1/menu/update']]
|
[[vPermission, 'post/api/v1/menu/update']],
|
||||||
),
|
),
|
||||||
h(
|
h(
|
||||||
NPopconfirm,
|
NPopconfirm,
|
||||||
@ -177,12 +177,12 @@ const columns = [
|
|||||||
{
|
{
|
||||||
default: () => '删除',
|
default: () => '删除',
|
||||||
icon: renderIcon('material-symbols:delete-outline', { size: 16 }),
|
icon: renderIcon('material-symbols:delete-outline', { size: 16 }),
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
[[vPermission, 'delete/api/v1/menu/delete']]
|
[[vPermission, 'delete/api/v1/menu/delete']],
|
||||||
),
|
),
|
||||||
default: () => h('div', {}, '确定删除该菜单吗?'),
|
default: () => h('div', {}, '确定删除该菜单吗?'),
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -144,9 +144,9 @@ const columns = [
|
|||||||
{
|
{
|
||||||
default: () => '编辑',
|
default: () => '编辑',
|
||||||
icon: renderIcon('material-symbols:edit-outline', { size: 16 }),
|
icon: renderIcon('material-symbols:edit-outline', { size: 16 }),
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
[[vPermission, 'post/api/v1/role/update']]
|
[[vPermission, 'post/api/v1/role/update']],
|
||||||
),
|
),
|
||||||
h(
|
h(
|
||||||
NPopconfirm,
|
NPopconfirm,
|
||||||
@ -167,12 +167,12 @@ const columns = [
|
|||||||
{
|
{
|
||||||
default: () => '删除',
|
default: () => '删除',
|
||||||
icon: renderIcon('material-symbols:delete-outline', { size: 16 }),
|
icon: renderIcon('material-symbols:delete-outline', { size: 16 }),
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
[[vPermission, 'delete/api/v1/role/delete']]
|
[[vPermission, 'delete/api/v1/role/delete']],
|
||||||
),
|
),
|
||||||
default: () => h('div', {}, '确定删除该角色吗?'),
|
default: () => h('div', {}, '确定删除该角色吗?'),
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
withDirectives(
|
withDirectives(
|
||||||
h(
|
h(
|
||||||
@ -195,9 +195,9 @@ const columns = [
|
|||||||
{
|
{
|
||||||
default: () => '设置权限',
|
default: () => '设置权限',
|
||||||
icon: renderIcon('material-symbols:edit-outline', { size: 16 }),
|
icon: renderIcon('material-symbols:edit-outline', { size: 16 }),
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
[[vPermission, 'get/api/v1/role/authorized']]
|
[[vPermission, 'get/api/v1/role/authorized']],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -99,7 +99,7 @@ const columns = [
|
|||||||
const group = []
|
const group = []
|
||||||
for (let i = 0; i < roles.length; i++)
|
for (let i = 0; i < roles.length; i++)
|
||||||
group.push(
|
group.push(
|
||||||
h(NTag, { type: 'info', style: { margin: '2px 3px' } }, { default: () => roles[i].name })
|
h(NTag, { type: 'info', style: { margin: '2px 3px' } }, { default: () => roles[i].name }),
|
||||||
)
|
)
|
||||||
return h('span', group)
|
return h('span', group)
|
||||||
},
|
},
|
||||||
@ -113,7 +113,7 @@ const columns = [
|
|||||||
return h(
|
return h(
|
||||||
NTag,
|
NTag,
|
||||||
{ type: 'info', style: { margin: '2px 3px' } },
|
{ type: 'info', style: { margin: '2px 3px' } },
|
||||||
{ default: () => (row.is_superuser ? '是' : '否') }
|
{ default: () => (row.is_superuser ? '是' : '否') },
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -130,7 +130,7 @@ const columns = [
|
|||||||
{
|
{
|
||||||
default: () => (row.last_login !== null ? formatDate(row.last_login) : null),
|
default: () => (row.last_login !== null ? formatDate(row.last_login) : null),
|
||||||
icon: renderIcon('mdi:update', { size: 16 }),
|
icon: renderIcon('mdi:update', { size: 16 }),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -175,9 +175,9 @@ const columns = [
|
|||||||
{
|
{
|
||||||
default: () => '编辑',
|
default: () => '编辑',
|
||||||
icon: renderIcon('material-symbols:edit', { size: 16 }),
|
icon: renderIcon('material-symbols:edit', { size: 16 }),
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
[[vPermission, 'post/api/v1/user/update']]
|
[[vPermission, 'post/api/v1/user/update']],
|
||||||
),
|
),
|
||||||
h(
|
h(
|
||||||
NPopconfirm,
|
NPopconfirm,
|
||||||
@ -197,12 +197,12 @@ const columns = [
|
|||||||
{
|
{
|
||||||
default: () => '删除',
|
default: () => '删除',
|
||||||
icon: renderIcon('material-symbols:delete-outline', { size: 16 }),
|
icon: renderIcon('material-symbols:delete-outline', { size: 16 }),
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
[[vPermission, 'delete/api/v1/user/delete']]
|
[[vPermission, 'delete/api/v1/user/delete']],
|
||||||
),
|
),
|
||||||
default: () => h('div', {}, '确定删除该用户吗?'),
|
default: () => h('div', {}, '确定删除该用户吗?'),
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -6,7 +6,9 @@
|
|||||||
<div flex items-center>
|
<div flex items-center>
|
||||||
<img rounded-full width="60" :src="userStore.avatar" />
|
<img rounded-full width="60" :src="userStore.avatar" />
|
||||||
<div ml-10>
|
<div ml-10>
|
||||||
<p text-20 font-semibold> {{ $t('views.workbench.text_hello', {username: userStore.name}) }}</p>
|
<p text-20 font-semibold>
|
||||||
|
{{ $t('views.workbench.text_hello', { username: userStore.name }) }}
|
||||||
|
</p>
|
||||||
<p mt-5 text-14 op-60>{{ $t('views.workbench.text_welcome') }}</p>
|
<p mt-5 text-14 op-60>{{ $t('views.workbench.text_welcome') }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -16,9 +18,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</n-card>
|
</n-card>
|
||||||
|
|
||||||
<n-card :title="$t('views.workbench.label_project')" size="small" :segmented="true" mt-15 rounded-10>
|
<n-card
|
||||||
|
:title="$t('views.workbench.label_project')"
|
||||||
|
size="small"
|
||||||
|
:segmented="true"
|
||||||
|
mt-15
|
||||||
|
rounded-10
|
||||||
|
>
|
||||||
<template #header-extra>
|
<template #header-extra>
|
||||||
<n-button text type="primary">{{$t('views.workbench.label_more')}}</n-button>
|
<n-button text type="primary">{{ $t('views.workbench.label_more') }}</n-button>
|
||||||
</template>
|
</template>
|
||||||
<div flex flex-wrap justify-between>
|
<div flex flex-wrap justify-between>
|
||||||
<n-card
|
<n-card
|
||||||
@ -29,7 +37,7 @@
|
|||||||
title="Vue FastAPI Admin"
|
title="Vue FastAPI Admin"
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
<p op-60>{{dummyText}}</p>
|
<p op-60>{{ dummyText }}</p>
|
||||||
</n-card>
|
</n-card>
|
||||||
</div>
|
</div>
|
||||||
</n-card>
|
</n-card>
|
||||||
@ -41,8 +49,8 @@
|
|||||||
import { useUserStore } from '@/store'
|
import { useUserStore } from '@/store'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
const dummyText = "一个基于 Vue3.0、FastAPI、Naive UI 的轻量级后台管理模板"
|
const dummyText = '一个基于 Vue3.0、FastAPI、Naive UI 的轻量级后台管理模板'
|
||||||
const {t} = useI18n({ useScope: "global" })
|
const { t } = useI18n({ useScope: 'global' })
|
||||||
|
|
||||||
const statisticData = computed(() => [
|
const statisticData = computed(() => [
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user