feat: 优化路由加载
parent
43487136fb
commit
943ec54aed
4
.env
4
.env
|
|
@ -29,4 +29,6 @@ VITE_PROXY = https://appnify.app.juetan.cn/
|
|||
# API文档 说明:需返回符合 OPENAPI 规范的json内容
|
||||
VITE_OPENAPI = http://127.0.0.1:3030/openapi.json
|
||||
# 文件后缀 说明:设为dev时会优先加载index.dev.vue文件,否则回退至index.vue文件
|
||||
VITE_EXTENSION = dev
|
||||
VITE_EXTENSION = dev
|
||||
# 是否以离线模式启动,跳过登录
|
||||
VITE_OFFLINE = true
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import { Button, ButtonInstance, FormInstance, Message, Modal } from '@arco-design/web-vue';
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { InjectionKey, PropType, Ref } from 'vue';
|
||||
import { getModel, setModel } from '../utils/useFormModel';
|
||||
import { AnForm, AnFormInstance, AnFormSubmit } from './Form';
|
||||
import { AnFormItemProps } from './FormItem';
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { getModel, setModel } from '../utils/useFormModel';
|
||||
|
||||
export interface AnFormModalContext {
|
||||
visible: Ref<boolean>;
|
||||
|
|
@ -210,6 +210,8 @@ export const AnFormModal = defineComponent({
|
|||
<Modal
|
||||
titleAlign="start"
|
||||
closable={false}
|
||||
maskAnimationName=""
|
||||
modalAnimationName=""
|
||||
{...this.modalProps}
|
||||
v-model:visible={this.visible}
|
||||
class="an-form-modal"
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ function useTableButtonColumn(column: TableButtonColumn & TableColumnData) {
|
|||
}
|
||||
return (
|
||||
<>
|
||||
{index !== 0 && <Divider direction="vertical" margin={2} />}
|
||||
{index !== 0 && <Divider direction="vertical" margin={4} />}
|
||||
<Link {...item.buttonProps} disabled={item.disable?.(props)} onClick={() => item.onClick?.(props)}>
|
||||
{{
|
||||
default: () => item.text,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
</div>
|
||||
<slot name="content">
|
||||
<a-scrollbar outer-class="h-full overflow-hidden" class="h-full overflow-auto" type="track">
|
||||
<div class="m-4 p-4 bg-white rounded overflow-hidden">
|
||||
<div class="m-4 bg-white rounded overflow-hidden" :class="{ 'p-4': contentPadding }">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</a-scrollbar>
|
||||
|
|
@ -19,7 +19,14 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import BreadCrumb from "./bread-crumb.vue";
|
||||
import BreadCrumb from './bread-crumb.vue';
|
||||
|
||||
defineProps({
|
||||
contentPadding: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
<template>
|
||||
<a-modal v-model:visible="show" :fullscreen="true" :footer="false" class="ani-modal">
|
||||
<a-modal
|
||||
v-model:visible="show"
|
||||
mask-animation-name=""
|
||||
modal-animation-name=""
|
||||
:fullscreen="true"
|
||||
:footer="false"
|
||||
class="ani-modal"
|
||||
>
|
||||
<div class="w-full h-full bg-slate-100 grid grid-rows-[auto_1fr] select-none">
|
||||
<div class="h-13 bg-white border-b border-slate-200 z-10">
|
||||
<EditorHeader
|
||||
|
|
@ -41,17 +48,17 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { delConfirm, sleep } from '@/utils';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { Block, ContextMenuItem, EditorKey, useEditor } from '../core';
|
||||
import ContextMenu from './ContextMenu.vue';
|
||||
import EditorSetting from './EditorConfig.vue';
|
||||
import EditorHeader from './EditorHeader.vue';
|
||||
import EditorLeft from './EditorLeft.vue';
|
||||
import EditorMain from './EditorMain.vue';
|
||||
import EditorRight from './EditorRight.vue';
|
||||
import EditorPreview from './EditorPreview.vue';
|
||||
import EditorSetting from './EditorConfig.vue';
|
||||
import ContextMenu from './ContextMenu.vue';
|
||||
import { delConfirm, sleep } from '@/utils';
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import EditorRight from './EditorRight.vue';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
|
|
@ -85,7 +92,7 @@ const blockMenuItems: ContextMenuItem[] = [
|
|||
await delConfirm({
|
||||
content: '确定删除该组件吗?',
|
||||
okText: '确定删除',
|
||||
})
|
||||
});
|
||||
if (blockMenu.block) {
|
||||
rmBlock(blockMenu.block);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
<template>
|
||||
<div class="h-full flex items-center justify-between pl-2 pr-4">
|
||||
<div class="text-base group">
|
||||
<div class="text-base flex items-center group">
|
||||
<a-link @click="emit('exit')">
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-left"></i>
|
||||
</template>
|
||||
返回
|
||||
</a-link>
|
||||
<a-divider :direction="'vertical'" :margin="4"></a-divider>
|
||||
<a-tag :color="container.id ? 'blue' : 'green'" class="mr-2 ml-1">
|
||||
{{ container.id ? '修改' : '新增' }}
|
||||
</a-tag>
|
||||
<a-divider :direction="'vertical'" :margin="8"></a-divider>
|
||||
<ani-texter v-model="container.title"></ani-texter>
|
||||
<!-- <a-tag :color="container.id ? 'blue' : 'green'" class="mr-2 ml-1">
|
||||
{{ container.id ? '修改' : '新增' }}
|
||||
</a-tag> -->
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<a-button @click="emit('preview')">
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
<template>
|
||||
<span v-if="!descEditing">
|
||||
<span v-if="!descEditing" class="inline-block leading-[32px] h-8">
|
||||
{{ modelValue }}
|
||||
<i
|
||||
class="!hidden !group-hover:inline-block icon-park-outline-edit text-gray-400 hover:text-gray-700 ml-1 cursor-pointer"
|
||||
@click="onDescEdit"
|
||||
></i>
|
||||
<a-button type="text" size="small" shape="round" class="!hidden !group-hover:inline-block !text-gray-500" @click="onDescEdit">
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-edit"></i>
|
||||
</template>
|
||||
</a-button>
|
||||
</span>
|
||||
<span v-else class="inline-flex items-center">
|
||||
<a-input size="small" v-model="descContent" class="!w-96" v-bind="inputProps"></a-input>
|
||||
|
|
@ -22,8 +23,8 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from "vue";
|
||||
import { Input } from "@arco-design/web-vue";
|
||||
import { PropType } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
|
|
|
|||
|
|
@ -25,29 +25,15 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useRouter } from "vue-router";
|
||||
import Image404 from "./image-404.svg?raw";
|
||||
import { useRouter } from 'vue-router';
|
||||
import Image404 from './image-404.svg?raw';
|
||||
|
||||
defineOptions({ name: "AllUncatchedPage" });
|
||||
defineOptions({ name: 'AllUncatchedPage' });
|
||||
|
||||
const router = useRouter();
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.slide-in-bottom {
|
||||
animation: slide-in-bottom 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
|
||||
}
|
||||
@keyframes slide-in-bottom {
|
||||
0% {
|
||||
transform: translateY(100px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
||||
<route lang="json">
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script lang="tsx">
|
||||
import { MenuItem } from "@/router";
|
||||
import { useMenuStore } from "@/store/menu";
|
||||
import { MenuItem } from '@/router';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
|
||||
export default defineComponent({
|
||||
name: "LayoutMenu",
|
||||
name: 'LayoutMenu',
|
||||
setup() {
|
||||
const selectedKeys = ref<string[]>([]);
|
||||
const route = useRoute();
|
||||
|
|
@ -13,21 +13,21 @@ export default defineComponent({
|
|||
watch(
|
||||
() => route.path,
|
||||
() => {
|
||||
selectedKeys.value = route.matched.map((i) => i.path);
|
||||
selectedKeys.value = route.matched.map(i => i.path);
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
function goto(route: MenuItem) {
|
||||
if (route.external) {
|
||||
window.open(route.path, "_blank");
|
||||
window.open(route.path, '_blank');
|
||||
return;
|
||||
}
|
||||
router.push(route.path);
|
||||
}
|
||||
|
||||
function renderItem(routes: MenuItem[]) {
|
||||
return routes.map((route) => {
|
||||
return routes.map(route => {
|
||||
const icon = route.icon ? () => <i class={route.icon} /> : null;
|
||||
const node: any = route.children?.length ? (
|
||||
<>
|
||||
|
|
@ -38,8 +38,13 @@ export default defineComponent({
|
|||
</>
|
||||
) : (
|
||||
<a-menu-item key={route.path} v-slots={{ icon }} onClick={() => goto(route)}>
|
||||
{route.title}
|
||||
{false && <span class="text-xs text-slate-400 ml-2">({route.sort})</span>}
|
||||
<div class="flex items-center justify-between gap-2 pr-4">
|
||||
<div>{route.title}</div>
|
||||
<div class="text-xs text-gray-400">
|
||||
{/* <a-badge count={8}>8</a-badge> */}
|
||||
{ route.only === 'dev' ? '仅开发' : null }
|
||||
</div>
|
||||
</div>
|
||||
</a-menu-item>
|
||||
);
|
||||
return node;
|
||||
|
|
@ -47,7 +52,7 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
return () => (
|
||||
<a-menu style={{ width: "100%" }} selectedKeys={selectedKeys.value} autoOpenSelected={true} levelIndent={0}>
|
||||
<a-menu style={{ width: '100%' }} selectedKeys={selectedKeys.value} autoOpenSelected={true} levelIndent={0}>
|
||||
{renderItem(menuStore.menus)}
|
||||
</a-menu>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
<a-divider :margin="4"></a-divider>
|
||||
<a-doption @click="logout">
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-logout"></i>
|
||||
<i class="icon-park-outline-power"></i>
|
||||
</template>
|
||||
退出
|
||||
</a-doption>
|
||||
|
|
@ -75,7 +75,7 @@ const logout = async () => {
|
|||
const { component: PasswordModal, open } = useFormModal({
|
||||
title: '修改密码',
|
||||
trigger: false,
|
||||
width: 452,
|
||||
width: 500,
|
||||
items: [
|
||||
{
|
||||
field: 'password',
|
||||
|
|
@ -84,6 +84,7 @@ const { component: PasswordModal, open } = useFormModal({
|
|||
setterProps: {
|
||||
placeholder: '请输入原密码',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'password1',
|
||||
|
|
@ -92,14 +93,16 @@ const { component: PasswordModal, open } = useFormModal({
|
|||
setterProps: {
|
||||
placeholder: '请输入新密码',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'password2',
|
||||
label: '确认密码',
|
||||
label: '确认新密码',
|
||||
setter: 'input',
|
||||
setterProps: {
|
||||
placeholder: '请再次输入新密码',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,12 +4,18 @@
|
|||
class="h-13 overflow-hidden flex justify-between items-center gap-4 px-2 pr-4 border-b border-slate-200 bg-white dark:bg-slate-800 dark:border-slate-700"
|
||||
>
|
||||
<div class="h-13 flex items-center">
|
||||
<!-- <a-button size="small" @click="isCollapsed = !isCollapsed">
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-hamburger-button text-base"></i>
|
||||
</template>
|
||||
</a-button> -->
|
||||
<router-link to="/" class="px-2 flex items-center gap-2 text-slate-700">
|
||||
<img src="/favicon.ico" alt="" width="24" height="24" class="" />
|
||||
<h1 class="relative text-[22px] leading-[22px] dark:text-white m-0 p-0 font-normal">
|
||||
<h1 class="relative text-[18px] leading-[22px] dark:text-white m-0 p-0 font-normal">
|
||||
{{ appStore.title }}
|
||||
<span class="absolute -right-10 -top-1 font-normal text-xs text-gray-400"> v0.0.1 </span>
|
||||
</h1>
|
||||
<!-- <span class="text-gray-400">{{ appStore.subtitle }}</span> -->
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
|
|
@ -41,7 +47,7 @@
|
|||
<a-layout-sider
|
||||
class="h-full overflow-hidden dark:bg-slate-800 border-r border-slate-200 dark:border-slate-700"
|
||||
:width="224"
|
||||
:collapsed-width="52"
|
||||
:collapsed-width="49"
|
||||
:collapsible="true"
|
||||
:collapsed="isCollapsed"
|
||||
:hide-trigger="false"
|
||||
|
|
@ -112,6 +118,13 @@ const buttons = [
|
|||
window.open('https://github.com/appnify/starter-vue', '_blank');
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'icon-park-outline-info',
|
||||
tooltip: '关于',
|
||||
onClick: () => {
|
||||
window.open('https://github.com/appnify/starter-vue', '_blank');
|
||||
},
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ const updateFileCategories = async () => {
|
|||
loading.value = true;
|
||||
const res = await api.fileCategory.getFileCategorys({ size: 0 });
|
||||
list.value = res.data.data ?? [];
|
||||
list.value.length && emit('change', list.value[0]);
|
||||
list.value.length && emit('change', {});
|
||||
} catch {
|
||||
// nothing to do
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -14,15 +14,15 @@
|
|||
<a-modal v-model:visible="show" :footer="false"></a-modal>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a-modal v-model:visible="show" title="预览" title-align="start" :closable="false" :width="420">
|
||||
<a-modal v-model:visible="show" title="预览" title-align="start" mask-animation-name="" modal-animation-name="" :closable="false" :width="420">
|
||||
抱歉,此文件类型暂不支持预览!
|
||||
</a-modal>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from 'vue';
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { PropType } from 'vue';
|
||||
|
||||
type FileType = 'text' | 'audio' | 'image' | 'video' | 'unknown';
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@
|
|||
title="上传文件"
|
||||
title-align="start"
|
||||
v-model:visible="visible"
|
||||
:width="940"
|
||||
mask-animation-name=""
|
||||
modal-animation-name=""
|
||||
:width="960"
|
||||
:mask-closable="false"
|
||||
:on-before-cancel="onBeforeCancel"
|
||||
@close="onClose"
|
||||
|
|
@ -27,7 +29,12 @@
|
|||
@error="onUploadError"
|
||||
>
|
||||
<template #upload-button>
|
||||
<a-button type="primary"> 选择文件 </a-button>
|
||||
<a-button type="primary">
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-upload-one"></i>
|
||||
</template>
|
||||
选择
|
||||
</a-button>
|
||||
</template>
|
||||
</a-upload>
|
||||
<div class="flex-1 flex items-center text-gray-400">
|
||||
|
|
@ -38,7 +45,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="h-[424px] border-t border-b border-zinc-100 mt-3">
|
||||
<div class="h-[424px] border-t border-b border-zinc-100 mt-4">
|
||||
<ul v-if="fileList.length" class="overflow-hidden p-0 m-0">
|
||||
<a-scrollbar outer-class="h-full overflow-hidden" class="h-full overflow-auto pr-[20px] divide-y">
|
||||
<li v-for="item in fileList" :key="item.uid" class="flex items-center gap-4 py-3">
|
||||
|
|
@ -99,7 +106,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<template #footer>
|
||||
<div class="flex justify-between gap-2 items-center">
|
||||
<div class="text-gray-400">已上传 {{ stat.doneCount }}/{{ fileList.length }} 项</div>
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ import { useCreateColumn, useTable, useTableDelete, useUpdateColumn } from '@/co
|
|||
import { Message } from '@arco-design/web-vue';
|
||||
import numeral from 'numeral';
|
||||
import AnGroup from './components/AnGroup.vue';
|
||||
import AnUpload from './components/AnUpload.vue';
|
||||
import AnPreview from './components/AnPreview.vue';
|
||||
import AnUpload from './components/AnUpload.vue';
|
||||
import { getIcon } from './components/util';
|
||||
|
||||
const current = ref<FileCategory>();
|
||||
|
|
@ -111,10 +111,12 @@ const {
|
|||
onClick: props => {
|
||||
window.open(props.record.path, '_blank');
|
||||
},
|
||||
icon: 'icon-park-outline-download',
|
||||
},
|
||||
{
|
||||
type: 'modify',
|
||||
text: '修改',
|
||||
icon: 'icon-park-outline-edit',
|
||||
},
|
||||
{
|
||||
type: 'delete',
|
||||
|
|
@ -138,6 +140,41 @@ const {
|
|||
categoryId: undefined,
|
||||
},
|
||||
items: [
|
||||
{
|
||||
field: 'type',
|
||||
label: '类型',
|
||||
setter: 'select',
|
||||
options: [
|
||||
{
|
||||
label: '视频',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '音频',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '图片',
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
label: '文本',
|
||||
value: 4,
|
||||
},
|
||||
{
|
||||
label: '其他',
|
||||
value: 5,
|
||||
},
|
||||
],
|
||||
setterProps: {
|
||||
style: {
|
||||
width: '100px',
|
||||
},
|
||||
triggerProps: {
|
||||
autoFitPopupMinWidth: true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'name',
|
||||
label: '素材名称',
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
{
|
||||
"only": "dev",
|
||||
"meta": {
|
||||
"sort": 20010,
|
||||
"sort": 120010,
|
||||
"title": "开发相关",
|
||||
"icon": "icon-park-outline-home"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
{
|
||||
"only": "dev",
|
||||
"meta": {
|
||||
"sort": 20010,
|
||||
"sort": 120010,
|
||||
"title": "接口文档",
|
||||
"icon": "icon-park-outline-api"
|
||||
}
|
||||
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
<script setup lang="tsx">
|
||||
import { api } from '@/api';
|
||||
import { TableColumnRender, useCreateColumn, useTable, useUpdateColumn } from '@/components/AnTable';
|
||||
import { useFormModal } from '@/components/AnForm';
|
||||
import { TableColumnRender, useCreateColumn, useTable, useUpdateColumn } from '@/components/AnTable';
|
||||
|
||||
defineOptions({ name: 'SystemUserPage' });
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ const usernameRender: TableColumnRender = ({ record }) => (
|
|||
</a-avatar>
|
||||
<div class="w-full flex-1 overflow-hidden">
|
||||
<div>
|
||||
<span>{record.nickname}</span>
|
||||
<span class="cursor-pointer hover:text-brand-500">{record.nickname}</span>
|
||||
<span class="text-gray-400 text-xs truncate ml-2">@{record.username}</span>
|
||||
</div>
|
||||
<div class="w-full text-gray-400 space-x-4 text-xs">
|
||||
|
|
@ -71,6 +71,7 @@ const { component: UserTable } = useTable({
|
|||
title: '操作',
|
||||
type: 'button',
|
||||
width: 200,
|
||||
align: 'right',
|
||||
buttons: [
|
||||
{
|
||||
text: '重置密码',
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
<template>
|
||||
<BreadPage>
|
||||
<template #content>
|
||||
<section class="my-page m-5 py-4 pr-4 h-full bg-white">
|
||||
<a-tabs direction="vertical">
|
||||
<BreadPage :content-padding="false">
|
||||
<section class="my-page bg-white">
|
||||
<a-tabs size="large">
|
||||
<a-tab-pane key="1" title="基本设置">
|
||||
<template #title>
|
||||
<i class="icon-park-outline-config"></i>
|
||||
基本设置
|
||||
</template>
|
||||
<a-form :model="user" layout="vertical">
|
||||
<a-form-item label="个人头像">
|
||||
<a-form
|
||||
:model="user"
|
||||
:label-col-props="{ span: 3 }"
|
||||
label-align="left"
|
||||
class="px-6 divide-y divide-gray-100"
|
||||
>
|
||||
<a-form-item label="用户头像">
|
||||
<a-avatar :size="64">
|
||||
<img src="https://github.com/juetan.png" alt="" />
|
||||
<template #trigger-icon>
|
||||
|
|
@ -23,12 +23,13 @@
|
|||
v-model="user.nickname"
|
||||
placeholder="请输入"
|
||||
class="!w-[432px]"
|
||||
allow-clear
|
||||
:max-length="24"
|
||||
:show-word-limit="true"
|
||||
></a-input>
|
||||
<template #help> 用作系统内显示的名称,可在后台修改 </template>
|
||||
</a-form-item>
|
||||
<a-form-item label="个人描述">
|
||||
<a-form-item label="用户描述">
|
||||
<a-textarea
|
||||
v-model="user.description"
|
||||
placeholder="请输入"
|
||||
|
|
@ -47,15 +48,42 @@
|
|||
<a-form-item label="出生日期">
|
||||
<a-date-picker v-model="user.birth"></a-date-picker>
|
||||
</a-form-item>
|
||||
<a-button type="primary">保存修改</a-button>
|
||||
<a-form-item>
|
||||
<a-button type="primary">保存修改</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="5" title="消息推送">
|
||||
<template #title>
|
||||
<i class="icon-park-outline-message"></i>
|
||||
消息通知
|
||||
</template>
|
||||
<a-form :model="user" layout="vertical">
|
||||
<a-tab-pane key="5" title="消息推送">
|
||||
<a-form :model="user" :label-col-props="{ span: 3 }" label-align="left" class="px-6 divide-y divide-gray-100">
|
||||
<a-form-item label="站点LOGO">
|
||||
<a-avatar :size="64">
|
||||
<img :src="appStore.logo" alt="" />
|
||||
<template #trigger-icon>
|
||||
<i class="icon-park-outline-edit"></i>
|
||||
</template>
|
||||
</a-avatar>
|
||||
<template #help> 支持 5MB 以内大小, png 或 jpg 格式的图片 </template>
|
||||
</a-form-item>
|
||||
<a-form-item label="站点名称">
|
||||
<a-input
|
||||
v-model="appStore.title"
|
||||
placeholder="请输入"
|
||||
class="!w-[432px]"
|
||||
allow-clear
|
||||
:max-length="24"
|
||||
:show-word-limit="true"
|
||||
></a-input>
|
||||
<template #help> 用作系统内显示的名称,可在后台修改 </template>
|
||||
</a-form-item>
|
||||
<a-form-item label="站点描述">
|
||||
<a-textarea
|
||||
v-model="appStore.subtitle"
|
||||
placeholder="请输入"
|
||||
class="!w-[432px] h-24"
|
||||
:max-length="140"
|
||||
:show-word-limit="true"
|
||||
></a-textarea>
|
||||
</a-form-item>
|
||||
<a-form-item label="消息推送">
|
||||
<div>
|
||||
<a-checkbox-group direction="vertical" v-model="user.msg">
|
||||
|
|
@ -67,60 +95,41 @@
|
|||
</div>
|
||||
<template elp> 用作系统内显示的名称,可在后台修改 </template>
|
||||
</a-form-item>
|
||||
<a-form-item label="邮箱账号">
|
||||
<a-input v-model="user.email" placeholder="请输入" class="!w-[432px]"></a-input>
|
||||
<a-form-item label="默认主题">
|
||||
<div>
|
||||
<a-radio-group v-model="user.theme" direction="vertical">
|
||||
<a-radio value="dark">
|
||||
黑曜深空
|
||||
<div class="text-gray-400 mt-1">浅绿色主题,包含深林、绿叶、河流等内容</div>
|
||||
</a-radio>
|
||||
<a-radio value="light">
|
||||
天空之城
|
||||
<div class="text-gray-400 mt-1">浅绿色主题,包含深林、绿叶、河流等内容</div>
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="SMTP地址">
|
||||
<a-input v-model="user.smtpIp" allow-clear placeholder="请输入" class="!w-[314px]"></a-input>
|
||||
<span class="inline-block px-2">:</span>
|
||||
<a-input-number v-model="user.smtpPort" :min="0" :max="65535" class="w-24!"></a-input-number>
|
||||
<template #help> 推荐使用主流邮箱, 例如: gmail.com, qq.com, 163.com等后缀 </template>
|
||||
</a-form-item>
|
||||
<a-form-item label="SMTP账号">
|
||||
<a-input v-model="user.smtpUser" placeholder="请输入" class="!w-[432px]"></a-input>
|
||||
<template #help> 例如: gmail.com, qq.com, 163.com等后缀 </template>
|
||||
</a-form-item>
|
||||
<a-form-item label="SMTP密钥">
|
||||
<a-input v-model="user.smtpPass" placeholder="请输入" class="!w-[432px]"></a-input>
|
||||
<template #help> 测试 </template>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button type="primary"> 保存修改 </a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="8" title="账号密码">
|
||||
<template #title>
|
||||
<i class="icon-park-outline-lock"></i>
|
||||
账号密码
|
||||
</template>
|
||||
<a-form :model="user" layout="vertical">
|
||||
<a-form-item label="原密码">
|
||||
<a-input placeholder="请输入原密码"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="新密码">
|
||||
<a-input placeholder="请输入新密码"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="确认新密码">
|
||||
<a-input placeholder="请再次输入新密码"></a-input>
|
||||
</a-form-item>
|
||||
<a-button type="primary">修改密码</a-button>
|
||||
</a-form>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" title="主题偏好">
|
||||
<template #title>
|
||||
<i class="icon-park-outline-theme"></i>
|
||||
主题设置
|
||||
</template>
|
||||
<div class="flex-1">
|
||||
<a-form :model="user" layout="vertical">
|
||||
<a-form-item label="主题">
|
||||
<div>
|
||||
<a-radio-group v-model="user.theme" direction="vertical">
|
||||
<a-radio value="dark">
|
||||
黑曜深空
|
||||
<div class="text-gray-400 mt-1">浅绿色主题,包含深林、绿叶、河流等内容</div>
|
||||
</a-radio>
|
||||
<a-radio value="light">
|
||||
天空之城
|
||||
<div class="text-gray-400 mt-1">浅绿色主题,包含深林、绿叶、河流等内容</div>
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3" title="额外功能">
|
||||
<template #title>
|
||||
<i class="icon-park-outline-shield"></i>
|
||||
基本设置
|
||||
</template>
|
||||
<div class="flex-1 grid">
|
||||
<div class="flex-1 grid px-6">
|
||||
<div class="mb-3">功能列表</div>
|
||||
<div v-for="i in 3" class="border-t py-4 flex justify-between items-center gap-4">
|
||||
<div class="flex gap-3 items-center">
|
||||
|
|
@ -180,13 +189,15 @@
|
|||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</section>
|
||||
</template>
|
||||
</BreadPage>
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import { useAppStore } from '@/store';
|
||||
import { reactive } from 'vue';
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
||||
const user = reactive({
|
||||
nickname: '绝弹',
|
||||
description: '选择在公开个人资料中显示私有项目的贡献,但不显示任何项目,仓库或组织信息',
|
||||
|
|
@ -195,11 +206,21 @@ const user = reactive({
|
|||
msg: [2],
|
||||
gender: 1,
|
||||
birth: '1988-12-18',
|
||||
smtpPort: 25,
|
||||
smtpIp: '10.10.10.30',
|
||||
smtpUser: '952222@163.com',
|
||||
smtpPass: 'xxxxx',
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.my-page {
|
||||
.arco-form-item-label {
|
||||
color: var(--color-text-3);
|
||||
}
|
||||
.arco-tabs-nav-type-line .arco-tabs-tab {
|
||||
height: 52px;
|
||||
}
|
||||
.arco-form-item.arco-form-item-error,
|
||||
.arco-form-item.arco-form-item-has-help {
|
||||
margin-bottom: 20px;
|
||||
|
|
@ -220,6 +241,9 @@ const user = reactive({
|
|||
.arco-radio-icon-hover {
|
||||
margin-top: 4px;
|
||||
}
|
||||
.arco-form-item:not(:first-child) {
|
||||
padding: 20px 0 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
@ -228,8 +252,7 @@ const user = reactive({
|
|||
"meta": {
|
||||
"sort": 30401,
|
||||
"title": "个人设置",
|
||||
"icon": "icon-park-outline-config",
|
||||
"auth": ["1"]
|
||||
"icon": "icon-park-outline-config"
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { api } from '@/api';
|
||||
import { env } from '@/config/env';
|
||||
import { store, useUserStore } from '@/store';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
import { treeEach, treeFilter, treeFind } from '@/utils/listToTree';
|
||||
|
|
@ -7,7 +8,6 @@ import { Router } from 'vue-router';
|
|||
import { menus } from '../menus';
|
||||
import { APP_HOME_NAME } from '../routes/base';
|
||||
import { APP_ROUTE_NAME, routes } from '../routes/page';
|
||||
import { env } from '@/config/env';
|
||||
|
||||
const WHITE_LIST = ['/:all(.*)*'];
|
||||
const UNSIGNIN_LIST = ['/login'];
|
||||
|
|
@ -27,7 +27,6 @@ export function useAuthGuard(router: Router) {
|
|||
};
|
||||
|
||||
router.beforeEach(async function (to, from) {
|
||||
console.log(to);
|
||||
const userStore = useUserStore(store);
|
||||
const menuStore = useMenuStore(store);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ export interface MenuItem {
|
|||
icon?: string;
|
||||
external?: boolean;
|
||||
name?: string;
|
||||
only?: undefined | 'none' | 'dev';
|
||||
keepAlive: boolean;
|
||||
children?: MenuItem[];
|
||||
}
|
||||
|
|
@ -25,13 +26,13 @@ function routesToItems(routes: RouteRecordRaw[]): MenuItem[] {
|
|||
const items: MenuItem[] = [];
|
||||
|
||||
for (const route of routes) {
|
||||
const { meta = {}, parentMeta, path } = route as any;
|
||||
const { title, sort, icon, keepAlive = false, name } = meta;
|
||||
const { meta = {}, parentMeta, only, path } = route as any;
|
||||
const { title, sort, icon, keepAlive = false, name } = meta;
|
||||
let id = path;
|
||||
let paths = route.path.split('/');
|
||||
let parentId = paths.slice(0, -1).join('/');
|
||||
if (parentMeta) {
|
||||
const { title, icon, sort } = parentMeta;
|
||||
const { title, icon, sort, only } = parentMeta;
|
||||
id = `${path}/index`;
|
||||
parentId = path;
|
||||
items.push({
|
||||
|
|
@ -39,6 +40,7 @@ function routesToItems(routes: RouteRecordRaw[]): MenuItem[] {
|
|||
icon,
|
||||
sort,
|
||||
path,
|
||||
only,
|
||||
id: path,
|
||||
keepAlive: false,
|
||||
parentId: paths.slice(0, -1).join('/'),
|
||||
|
|
@ -49,7 +51,7 @@ function routesToItems(routes: RouteRecordRaw[]): MenuItem[] {
|
|||
parentId = p;
|
||||
}
|
||||
}
|
||||
items.push({ id, title, parentId, path, icon, sort, keepAlive, name });
|
||||
items.push({ id, title, parentId, path, icon, sort, only, keepAlive, name });
|
||||
}
|
||||
|
||||
return items;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import generatedRoutes from 'virtual:generated-pages';
|
||||
import { RouteRecordRaw } from 'vue-router';
|
||||
import { routes as vroutes } from 'vue-router/auto/routes';
|
||||
|
||||
console.log({vroutes, generatedRoutes});
|
||||
|
||||
export const TOP_ROUTE_PREF = '_';
|
||||
export const APP_ROUTE_NAME = '_layout';
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ export const useAppStore = defineStore({
|
|||
state: (): AppStore => ({
|
||||
isDarkMode: false,
|
||||
title: env.title,
|
||||
logo: "/favicon.ico",
|
||||
subtitle: env.subtitle,
|
||||
pageLoding: false,
|
||||
pageTags: [],
|
||||
|
|
@ -74,6 +75,7 @@ export const useAppStore = defineStore({
|
|||
});
|
||||
|
||||
interface AppStore {
|
||||
logo: string;
|
||||
/**
|
||||
* 是否为暗模式
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ body {
|
|||
margin-right: 0;
|
||||
}
|
||||
|
||||
.ani-form-modal .arco-modal-body {
|
||||
.an-form-modal .arco-modal-body {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ declare module '@vue/runtime-core' {
|
|||
ADoption: typeof import('@arco-design/web-vue')['Doption']
|
||||
ADrawer: typeof import('@arco-design/web-vue')['Drawer']
|
||||
ADropdown: typeof import('@arco-design/web-vue')['Dropdown']
|
||||
ADropdownButton: typeof import('@arco-design/web-vue')['DropdownButton']
|
||||
AEmpty: typeof import('@arco-design/web-vue')['Empty']
|
||||
AForm: typeof import('@arco-design/web-vue')['Form']
|
||||
AFormItem: typeof import('@arco-design/web-vue')['FormItem']
|
||||
|
|
@ -43,7 +42,6 @@ declare module '@vue/runtime-core' {
|
|||
AnEmpty: typeof import('./../components/AnEmpty/AnEmpty.vue')['default']
|
||||
AnForbidden: typeof import('./../components/AnForbidden/AnForbidden.vue')['default']
|
||||
AnToast: typeof import('./../components/AnToast/AnToast.vue')['default']
|
||||
AOption: typeof import('@arco-design/web-vue')['Option']
|
||||
APagination: typeof import('@arco-design/web-vue')['Pagination']
|
||||
APopover: typeof import('@arco-design/web-vue')['Popover']
|
||||
AProgress: typeof import('@arco-design/web-vue')['Progress']
|
||||
|
|
@ -73,7 +71,6 @@ declare module '@vue/runtime-core' {
|
|||
EditorLeft: typeof import('./../components/editor/components/EditorLeft.vue')['default']
|
||||
EditorMain: typeof import('./../components/editor/components/EditorMain.vue')['default']
|
||||
EditorMainBlock: typeof import('./../components/editor/components/EditorMainBlock.vue')['default']
|
||||
EditorMainConfig: typeof import('./../components/editor/components/EditorMainConfig.vue')['default']
|
||||
EditorMainHeader: typeof import('./../components/editor/components/EditorMainHeader.vue')['default']
|
||||
EditorPreview: typeof import('./../components/editor/components/EditorPreview.vue')['default']
|
||||
EditorRight: typeof import('./../components/editor/components/EditorRight.vue')['default']
|
||||
|
|
@ -84,13 +81,6 @@ declare module '@vue/runtime-core' {
|
|||
InputTexter: typeof import('./../components/editor/components/InputTexter.vue')['default']
|
||||
Marquee: typeof import('./../components/editor/blocks/text/marquee.vue')['default']
|
||||
Option: typeof import('./../components/editor/blocks/date/option.vue')['default']
|
||||
PanelHeader: typeof import('./../components/editor/components/PanelHeader.vue')['default']
|
||||
PanelLeft: typeof import('./../components/editor/components/PanelLeft.vue')['default']
|
||||
PanelMain: typeof import('./../components/editor/components/PanelMain.vue')['default']
|
||||
PanelMainBlock: typeof import('./../components/editor/components/PanelMainBlock.vue')['default']
|
||||
PanelMainConfig: typeof import('./../components/editor/components/PanelMainConfig.vue')['default']
|
||||
PanelMainHeader: typeof import('./../components/editor/components/PanelMainHeader.vue')['default']
|
||||
PanelRight: typeof import('./../components/editor/components/PanelRight.vue')['default']
|
||||
Render: typeof import('./../components/editor/blocks/date/render.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
|
|
|
|||
|
|
@ -42,25 +42,24 @@ declare module 'vue-router/auto/routes' {
|
|||
'/_layout/': RouteRecordInfo<'/_layout/', '/_layout', Record<never, never>, Record<never, never>>,
|
||||
'/_login/': RouteRecordInfo<'/_login/', '/_login', Record<never, never>, Record<never, never>>,
|
||||
'/[..._all]/': RouteRecordInfo<'/[..._all]/', '/:_all(.*)', { _all: ParamValue<true> }, { _all: ParamValue<false> }>,
|
||||
'/dev/openapi': RouteRecordInfo<'/dev/openapi', '/dev/openapi', Record<never, never>, Record<never, never>>,
|
||||
'/home/demo': RouteRecordInfo<'/home/demo', '/home/demo', Record<never, never>, Record<never, never>>,
|
||||
'/home/home': RouteRecordInfo<'/home/home', '/home/home', Record<never, never>, Record<never, never>>,
|
||||
'/home/test': RouteRecordInfo<'/home/test', '/home/test', Record<never, never>, Record<never, never>>,
|
||||
'/my/': RouteRecordInfo<'/my/', '/my', Record<never, never>, Record<never, never>>,
|
||||
'/my/dev': RouteRecordInfo<'/my/dev', '/my/dev', Record<never, never>, Record<never, never>>,
|
||||
'/my/editor': RouteRecordInfo<'/my/editor', '/my/editor', Record<never, never>, Record<never, never>>,
|
||||
'/post/': RouteRecordInfo<'/post/', '/post', Record<never, never>, Record<never, never>>,
|
||||
'/post/category/': RouteRecordInfo<'/post/category/', '/post/category', Record<never, never>, Record<never, never>>,
|
||||
'/post/comment/': RouteRecordInfo<'/post/comment/', '/post/comment', Record<never, never>, Record<never, never>>,
|
||||
'/post/media/': RouteRecordInfo<'/post/media/', '/post/media', Record<never, never>, Record<never, never>>,
|
||||
'/post/post/': RouteRecordInfo<'/post/post/', '/post/post', Record<never, never>, Record<never, never>>,
|
||||
'/content/': RouteRecordInfo<'/content/', '/content', Record<never, never>, Record<never, never>>,
|
||||
'/content/category/': RouteRecordInfo<'/content/category/', '/content/category', Record<never, never>, Record<never, never>>,
|
||||
'/content/comment/': RouteRecordInfo<'/content/comment/', '/content/comment', Record<never, never>, Record<never, never>>,
|
||||
'/content/material/': RouteRecordInfo<'/content/material/', '/content/material', Record<never, never>, Record<never, never>>,
|
||||
'/content/post/': RouteRecordInfo<'/content/post/', '/content/post', Record<never, never>, Record<never, never>>,
|
||||
'/dev/': RouteRecordInfo<'/dev/', '/dev', Record<never, never>, Record<never, never>>,
|
||||
'/dev/editor/': RouteRecordInfo<'/dev/editor/', '/dev/editor', Record<never, never>, Record<never, never>>,
|
||||
'/dev/openapi/': RouteRecordInfo<'/dev/openapi/', '/dev/openapi', Record<never, never>, Record<never, never>>,
|
||||
'/home/': RouteRecordInfo<'/home/', '/home', Record<never, never>, Record<never, never>>,
|
||||
'/log/': RouteRecordInfo<'/log/', '/log', Record<never, never>, Record<never, never>>,
|
||||
'/log/login/': RouteRecordInfo<'/log/login/', '/log/login', Record<never, never>, Record<never, never>>,
|
||||
'/log/operation/': RouteRecordInfo<'/log/operation/', '/log/operation', Record<never, never>, Record<never, never>>,
|
||||
'/system/': RouteRecordInfo<'/system/', '/system', Record<never, never>, Record<never, never>>,
|
||||
'/system/login-log/': RouteRecordInfo<'/system/login-log/', '/system/login-log', Record<never, never>, Record<never, never>>,
|
||||
'/system/dict/': RouteRecordInfo<'/system/dict/', '/system/dict', Record<never, never>, Record<never, never>>,
|
||||
'/system/menu/': RouteRecordInfo<'/system/menu/', '/system/menu', Record<never, never>, Record<never, never>>,
|
||||
'/system/operation-log/': RouteRecordInfo<'/system/operation-log/', '/system/operation-log', Record<never, never>, Record<never, never>>,
|
||||
'/system/permission/': RouteRecordInfo<'/system/permission/', '/system/permission', Record<never, never>, Record<never, never>>,
|
||||
'/system/role/': RouteRecordInfo<'/system/role/', '/system/role', Record<never, never>, Record<never, never>>,
|
||||
'/system/user/': RouteRecordInfo<'/system/user/', '/system/user', Record<never, never>, Record<never, never>>,
|
||||
'/user/': RouteRecordInfo<'/user/', '/user', Record<never, never>, Record<never, never>>,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import { merge } from 'lodash-es';
|
|||
export type DelOptions = string | Partial<Omit<ModalConfig, 'onOk' | 'onCancel'>>;
|
||||
|
||||
export const delOptions: ModalConfig = {
|
||||
maskAnimationName: '',
|
||||
modalAnimationName: '',
|
||||
title: '提示',
|
||||
titleAlign: 'start',
|
||||
width: 432,
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
import Vue from "@vitejs/plugin-vue";
|
||||
import VueJsx from "@vitejs/plugin-vue-jsx";
|
||||
import { resolve } from "path";
|
||||
import { visualizer } from "rollup-plugin-visualizer";
|
||||
import { presetIcons, presetUno } from "unocss";
|
||||
import Unocss from "unocss/vite";
|
||||
import AutoImport from "unplugin-auto-import/vite";
|
||||
import { ArcoResolver } from "unplugin-vue-components/resolvers";
|
||||
import AutoComponent from "unplugin-vue-components/vite";
|
||||
import { defineConfig, loadEnv } from "vite";
|
||||
import Page from "vite-plugin-pages";
|
||||
import { arcoToUnoColor } from "./scripts/vite/color";
|
||||
import iconFile from "./scripts/vite/file.json";
|
||||
import iconFmt from "./scripts/vite/fmt.json";
|
||||
import plugin from "./scripts/vite/plugin";
|
||||
import Vue from '@vitejs/plugin-vue';
|
||||
import VueJsx from '@vitejs/plugin-vue-jsx';
|
||||
import { resolve } from 'path';
|
||||
import { visualizer } from 'rollup-plugin-visualizer';
|
||||
import { presetIcons, presetUno } from 'unocss';
|
||||
import Unocss from 'unocss/vite';
|
||||
import AutoImport from 'unplugin-auto-import/vite';
|
||||
import { ArcoResolver } from 'unplugin-vue-components/resolvers';
|
||||
import AutoComponent from 'unplugin-vue-components/vite';
|
||||
import router from 'unplugin-vue-router/vite';
|
||||
import { defineConfig, loadEnv } from 'vite';
|
||||
import Page from 'vite-plugin-pages';
|
||||
import { arcoToUnoColor } from './scripts/vite/color';
|
||||
import iconFile from './scripts/vite/file.json';
|
||||
import iconFmt from './scripts/vite/fmt.json';
|
||||
import plugin from './scripts/vite/plugin';
|
||||
|
||||
/**
|
||||
* vite 配置
|
||||
|
|
@ -20,12 +21,21 @@ import plugin from "./scripts/vite/plugin";
|
|||
*/
|
||||
export default defineConfig(({ mode }) => {
|
||||
const env = loadEnv(mode, process.cwd());
|
||||
const base = env.VITE_BASE ?? "/";
|
||||
const host = env.VITE_HOST ?? "0.0.0.0";
|
||||
const base = env.VITE_BASE ?? '/';
|
||||
const host = env.VITE_HOST ?? '0.0.0.0';
|
||||
const port = Number(env.VITE_PORT ?? 3020);
|
||||
return {
|
||||
base,
|
||||
plugins: [
|
||||
/**
|
||||
* 提供路由自动生成
|
||||
* @see https://github.com/posva/unplugin-vue-router
|
||||
*/
|
||||
router({
|
||||
dts: 'src/types/auto-router.d.ts',
|
||||
exclude: ['**/components/*'],
|
||||
}),
|
||||
|
||||
/**
|
||||
* 提供 Vue 3 单文件组件支持
|
||||
* @see https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue
|
||||
|
|
@ -47,9 +57,9 @@ export default defineConfig(({ mode }) => {
|
|||
* @see https://github.com/antfu/unplugin-auto-import#readme
|
||||
*/
|
||||
AutoImport({
|
||||
imports: ["vue", "vue-router"],
|
||||
dts: 'src/types/auto-import.d.ts',
|
||||
imports: ['vue', 'vue-router'],
|
||||
resolvers: [ArcoResolver()],
|
||||
dts: "./src/types/auto-import.d.ts",
|
||||
}),
|
||||
|
||||
/**
|
||||
|
|
@ -57,8 +67,8 @@ export default defineConfig(({ mode }) => {
|
|||
* @see https://github.com/antfu/unplugin-vue-components
|
||||
*/
|
||||
AutoComponent({
|
||||
dts: 'src/types/auto-component.d.ts',
|
||||
resolvers: [ArcoResolver({ sideEffect: false })],
|
||||
dts: "./src/types/auto-component.d.ts",
|
||||
}),
|
||||
|
||||
/**
|
||||
|
|
@ -66,13 +76,13 @@ export default defineConfig(({ mode }) => {
|
|||
* @see https://github.com/hannoeru/vite-plugin-pages
|
||||
*/
|
||||
Page({
|
||||
exclude: ["**/components/*", "**/*.*.*"],
|
||||
importMode: "async",
|
||||
exclude: ['**/components/*', '**/*.*.*'],
|
||||
importMode: 'async',
|
||||
onRoutesGenerated(routes) {
|
||||
// if (env.DEV) {
|
||||
// return routes;
|
||||
// }
|
||||
return routes.filter((route) => route.only !== "dev");
|
||||
if (mode === 'development') {
|
||||
return routes.filter(route => route.only !== 'none');
|
||||
}
|
||||
return routes.filter(route => !['none', 'dev'].includes(route.only));
|
||||
},
|
||||
}),
|
||||
|
||||
|
|
@ -83,17 +93,17 @@ export default defineConfig(({ mode }) => {
|
|||
Unocss({
|
||||
theme: {
|
||||
colors: {
|
||||
brand: arcoToUnoColor("primary"),
|
||||
brand: arcoToUnoColor('primary'),
|
||||
},
|
||||
},
|
||||
include: ["src/**/*.{vue,ts,tsx,css,scss,sass,less,styl}"],
|
||||
include: ['src/**/*.{vue,ts,tsx,css,scss,sass,less,styl}'],
|
||||
presets: [
|
||||
presetUno(),
|
||||
presetIcons({
|
||||
prefix: "",
|
||||
prefix: '',
|
||||
collections: {
|
||||
"icon-file": iconFile,
|
||||
"icon-fmt": iconFmt,
|
||||
'icon-file': iconFile,
|
||||
'icon-fmt': iconFmt,
|
||||
},
|
||||
}),
|
||||
],
|
||||
|
|
@ -105,7 +115,7 @@ export default defineConfig(({ mode }) => {
|
|||
*/
|
||||
visualizer({
|
||||
title: `构建统计 | ${env.VITE_SUBTITLE}`,
|
||||
filename: ".gitea/stat.html",
|
||||
filename: '.gitea/stat.html',
|
||||
}),
|
||||
|
||||
/**
|
||||
|
|
@ -117,8 +127,8 @@ export default defineConfig(({ mode }) => {
|
|||
resolve: {
|
||||
alias: [
|
||||
{
|
||||
find: "@",
|
||||
replacement: "/src",
|
||||
find: '@',
|
||||
replacement: '/src',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -126,10 +136,10 @@ export default defineConfig(({ mode }) => {
|
|||
host,
|
||||
port,
|
||||
proxy: {
|
||||
"/api": {
|
||||
'/api': {
|
||||
target: env.VITE_PROXY,
|
||||
},
|
||||
"/upload": {
|
||||
'/upload': {
|
||||
target: env.VITE_PROXY,
|
||||
},
|
||||
},
|
||||
|
|
@ -139,8 +149,8 @@ export default defineConfig(({ mode }) => {
|
|||
less: {
|
||||
javascriptEnabled: true,
|
||||
modifyVars: {
|
||||
hack: `true; @import (reference) "${resolve("src/styles/css-arco.less")}";`,
|
||||
arcoblue: "#66f",
|
||||
hack: `true; @import (reference) "${resolve('src/styles/css-arco.less')}";`,
|
||||
arcoblue: '#66f',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue