提交 4ff6b73c 编写于 作者: V vben

perf: optimize settingDrawer code

上级 5832ee66
......@@ -4,6 +4,10 @@
- 表单项的`componentsProps`支持函数类型
### ⚡ Performance Improvements
- 优化 settingDrawer 代码
### 🐛 Bug Fixes
- 修复多个富文本编辑器只显示一个
......
......@@ -30,8 +30,7 @@
.app-loading {
width: 100%;
height: 100%;
/* background: #f0f2f5; */
background: #f0f2f5;
}
.app-loading .app-loading-wrap {
......
......@@ -11,7 +11,7 @@ const demoList = (() => {
address: '@city()',
name: '@cname()',
'no|100000-10000000': 100000,
'status|1': ['正常', '启用', '停用'],
'status|1': ['normal', 'enable', 'disable'],
});
}
return result;
......
import { defHttp } from '/@/utils/http/axios';
enum Api {
// 该地址不存在
// The address does not exist
Error = '/error',
}
/**
* @description: 触发ajax错误
* @description: Trigger ajax error
*/
export function fireErrorApi() {
return defHttp.request({
......
import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel';
/**
* @description: 请求列表接口参数
* @description: Request list interface parameters
*/
export type DemoParams = BasicPageParams;
......@@ -15,6 +15,6 @@ export interface DemoListItem {
}
/**
* @description: 请求列表返回值
* @description: Request list return value
*/
export type DemoListGetResultModel = BasicFetchResult<DemoListItem>;
......@@ -6,7 +6,7 @@ enum Api {
}
/**
* @description: 获取示例列表值
* @description: Get sample list value
*/
export function demoListApi(params: DemoParams) {
return defHttp.request<DemoListGetResultModel>({
......
......@@ -89,7 +89,6 @@ export type ComponentType =
| 'InputNumber'
| 'InputCountDown'
| 'Select'
| 'DictSelect'
| 'SelectOptGroup'
| 'SelectOption'
| 'TreeSelect'
......
......@@ -52,7 +52,8 @@ export default defineComponent({
toRef(props, 'items'),
toRef(props, 'flatItems'),
toRef(props, 'isAppMenu'),
toRef(props, 'mode')
toRef(props, 'mode'),
toRef(props, 'accordion')
);
const getOpenKeys = computed(() => {
......
......@@ -58,6 +58,10 @@ export const basicProps = {
type: Boolean as PropType<boolean>,
default: false,
},
accordion: {
type: Boolean as PropType<boolean>,
default: true,
},
beforeClickFn: {
type: Function as PropType<Fn>,
default: null,
......
......@@ -6,21 +6,31 @@ import type { Ref } from 'vue';
import { unref } from 'vue';
import { menuStore } from '/@/store/modules/menu';
import { getAllParentPath } from '/@/utils/helper/menuHelper';
import { es6Unique } from '/@/utils';
export function useOpenKeys(
menuState: MenuState,
menus: Ref<MenuType[]>,
flatMenusRef: Ref<MenuType[]>,
isAppMenu: Ref<boolean>,
mode: Ref<MenuModeEnum>
mode: Ref<MenuModeEnum>,
accordion: Ref<boolean>
) {
/**
* @description:设置展开
*/
function setOpenKeys(menu: MenuType) {
const flatMenus = unref(flatMenusRef);
menuState.openKeys = getAllParentPath(flatMenus, menu.path);
if (!unref(accordion)) {
menuState.openKeys = es6Unique([
...menuState.openKeys,
...getAllParentPath(flatMenus, menu.path),
]);
} else {
menuState.openKeys = getAllParentPath(flatMenus, menu.path);
}
}
/**
* @description: 重置值
*/
......@@ -30,7 +40,7 @@ export function useOpenKeys(
}
function handleOpenChange(openKeys: string[]) {
if (unref(mode) === MenuModeEnum.HORIZONTAL) {
if (unref(mode) === MenuModeEnum.HORIZONTAL || !unref(accordion)) {
menuState.openKeys = openKeys;
} else {
const rootSubMenuKeys: string[] = [];
......
......@@ -2,11 +2,8 @@ import { defineComponent } from 'vue';
import { Layout } from 'ant-design-vue';
import { RouterView } from 'vue-router';
// hooks
import { ContentEnum } from '/@/enums/appEnum';
import { appStore } from '/@/store/modules/app';
// import PageLayout from '/@/layouts/page/index';
export default defineComponent({
name: 'DefaultLayoutContent',
setup() {
......@@ -17,7 +14,6 @@ export default defineComponent({
return (
<Layout.Content class={`layout-content ${wrapClass} `}>
{() => <RouterView />}
{/* <PageLayout class={`layout-content ${wrapClass} `} /> */}
</Layout.Content>
);
};
......
......@@ -55,27 +55,25 @@ export default defineComponent({
},
},
setup(props) {
// Menu array
const menusRef = ref<Menu[]>([]);
// flat menu array
const flatMenusRef = ref<Menu[]>([]);
const { currentRoute, push } = useRouter();
// const { addTab } = useTabs();
// get app config
const getProjectConfigRef = computed(() => {
return appStore.getProjectConfig;
});
// get is Horizontal
const getIsHorizontalRef = computed(() => {
return unref(getProjectConfigRef).menuSetting.mode === MenuModeEnum.HORIZONTAL;
});
const [throttleHandleSplitLeftMenu] = useThrottle(handleSplitLeftMenu, 50);
// watch(
// () => menuStore.getCurrentTopSplitMenuPathState,
// async (parentPath: string) => {
// throttleHandleSplitLeftMenu(parentPath);
// }
// );
// Route change split menu
watch(
[() => unref(currentRoute).path, () => props.splitType],
async ([path, splitType]: [string, MenuSplitTyeEnum]) => {
......@@ -88,23 +86,26 @@ export default defineComponent({
}
);
// Menu changes
watch(
[() => permissionStore.getLastBuildMenuTimeState, permissionStore.getBackMenuListState],
[() => permissionStore.getLastBuildMenuTimeState, () => permissionStore.getBackMenuListState],
() => {
genMenus();
}
);
// split Menu changes
watch([() => appStore.getProjectConfig.menuSetting.split], () => {
if (props.splitType !== MenuSplitTyeEnum.LEFT && !unref(getIsHorizontalRef)) return;
genMenus();
});
// Handle left menu split
async function handleSplitLeftMenu(parentPath: string) {
const isSplitMenu = unref(getProjectConfigRef).menuSetting.split;
if (!isSplitMenu) return;
const { splitType } = props;
// 菜单分割模式-left
// spilt mode left
if (splitType === MenuSplitTyeEnum.LEFT) {
const children = await getChildrenMenus(parentPath);
if (!children) {
......@@ -128,11 +129,11 @@ export default defineComponent({
}
}
// get menus
async function genMenus() {
const isSplitMenu = unref(getProjectConfigRef).menuSetting.split;
// 普通模式
// normal mode
const { splitType } = props;
if (splitType === MenuSplitTyeEnum.NONE || !isSplitMenu) {
flatMenusRef.value = await getFlatMenus();
......@@ -140,7 +141,7 @@ export default defineComponent({
return;
}
// 菜单分割模式-top
// split-top
if (splitType === MenuSplitTyeEnum.TOP) {
const parentPath = await getCurrentParentPath(unref(currentRoute).path);
menuStore.commitCurrentTopSplitMenuPathState(parentPath);
......@@ -156,12 +157,11 @@ export default defineComponent({
const { path } = menu;
if (path) {
const { splitType } = props;
// 菜单分割模式-top
// split mode top
if (splitType === MenuSplitTyeEnum.TOP) {
menuStore.commitCurrentTopSplitMenuPathState(path);
}
push(path);
// addTab(path as PageEnum, true);
}
}
......@@ -205,6 +205,7 @@ export default defineComponent({
collapsed,
collapsedShowTitle,
collapsedShowSearch,
accordion,
},
} = unref(getProjectConfigRef);
......@@ -227,6 +228,7 @@ export default defineComponent({
onClickSearchInput={handleClickSearchInput}
appendClass={props.splitType === MenuSplitTyeEnum.TOP}
isTop={props.isTop}
accordion={accordion}
>
{{
header: () =>
......
......@@ -4,9 +4,6 @@ import { Layout } from 'ant-design-vue';
import LayoutTrigger from './LayoutTrigger';
import { menuStore } from '/@/store/modules/menu';
// import darkMiniIMg from '/@/assets/images/sidebar/dark-mini.png';
// import lightMiniImg from '/@/assets/images/sidebar/light-mini.png';
// import lightImg from '/@/assets/images/sidebar/light.png';
import { appStore } from '/@/store/modules/app';
import { MenuModeEnum, MenuSplitTyeEnum, TriggerEnum } from '/@/enums/menuEnum';
import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum';
......@@ -44,7 +41,7 @@ export default defineComponent({
initRef.value = true;
}
// 菜单区域拖拽 - 鼠标移动
// Menu area drag and drop-mouse movement
function handleMouseMove(ele: any, wrap: any, clientX: number) {
document.onmousemove = function (innerE) {
let iT = ele.left + ((innerE || event).clientX - clientX);
......@@ -98,7 +95,6 @@ export default defineComponent({
const side = unref(sideRef);
const wrap = (side || {}).$el;
// const eleWidth = 6;
ele &&
(ele.onmousedown = (e: any) => {
menuStore.commitDragStartState(true);
......
......@@ -19,12 +19,11 @@ import './index.less';
export default defineComponent({
name: 'DefaultLayout',
setup() {
// ! 在这里才注册全局组件
// ! 可以减少首屏代码体积
// default layout是在登录后才加载的。所以不会打包到首屏去
// ! Only register global components here
// ! Can reduce the size of the first screen code
// default layout It is loaded after login. So it won’t be packaged to the first screen
registerGlobComp();
// 获取项目配置
const { getFullContent } = useFullContent();
const getProjectConfigRef = computed(() => {
......@@ -56,8 +55,6 @@ export default defineComponent({
return split || (show && mode !== MenuModeEnum.HORIZONTAL && !unref(getFullContent));
});
// Get project configuration
// const { getFullContent } = useFullContent(currentRoute);
function getTarget(): any {
const {
headerSetting: { fixed },
......
......@@ -2,14 +2,7 @@ import { defineComponent, computed, unref, ref } from 'vue';
import { BasicDrawer } from '/@/components/Drawer/index';
import { Divider, Switch, Tooltip, InputNumber, Select } from 'ant-design-vue';
import Button from '/@/components/Button/index.vue';
import {
MenuModeEnum,
MenuTypeEnum,
MenuThemeEnum,
TopMenuAlignEnum,
TriggerEnum,
} from '/@/enums/menuEnum';
import { ContentEnum, RouterTransitionEnum } from '/@/enums/appEnum';
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
import { CopyOutlined, RedoOutlined, CheckOutlined } from '@ant-design/icons-vue';
import { appStore } from '/@/store/modules/app';
import { userStore } from '/@/store/modules/user';
......@@ -24,70 +17,15 @@ import mixImg from '/@/assets/images/layout/menu-mix.svg';
import sidebarImg from '/@/assets/images/layout/menu-sidebar.svg';
import menuTopImg from '/@/assets/images/layout/menu-top.svg';
import { updateColorWeak, updateGrayMode } from '/@/setup/theme';
const themeOptions = [
{
value: MenuThemeEnum.LIGHT,
label: '亮色',
},
{
value: MenuThemeEnum.DARK,
label: '暗色',
},
];
const contentModeOptions = [
{
value: ContentEnum.FULL,
label: '流式',
},
{
value: ContentEnum.FIXED,
label: '定宽',
},
];
const topMenuAlignOptions = [
{
value: TopMenuAlignEnum.CENTER,
label: '居中',
},
{
value: TopMenuAlignEnum.START,
label: '居左',
},
{
value: TopMenuAlignEnum.END,
label: '居右',
},
];
const menuTriggerOptions = [
{
value: TriggerEnum.NONE,
label: '不显示',
},
{
value: TriggerEnum.FOOTER,
label: '底部',
},
{
value: TriggerEnum.HEADER,
label: '顶部',
},
];
const routerTransitionOptions = [
RouterTransitionEnum.ZOOM_FADE,
RouterTransitionEnum.FADE,
RouterTransitionEnum.ZOOM_OUT,
RouterTransitionEnum.FADE_SIDE,
RouterTransitionEnum.FADE_BOTTOM,
].map((item) => {
return {
label: item,
value: item,
key: item,
};
});
import { baseHandler } from './handler';
import {
HandlerEnum,
themeOptions,
contentModeOptions,
topMenuAlignOptions,
menuTriggerOptions,
routerTransitionOptions,
} from './const';
interface SwitchOptions {
config?: DeepPartial<ProjectConfig>;
......@@ -139,6 +77,25 @@ export default defineComponent({
});
}
function handleResetSetting() {
try {
appStore.commitProjectConfigState(defaultSetting);
const { colorWeak, grayMode } = defaultSetting;
// updateTheme(themeColor);
updateColorWeak(colorWeak);
updateGrayMode(grayMode);
createMessage.success('重置成功!');
} catch (error) {
createMessage.error(error);
}
}
function handleClearAndRedo() {
localStorage.clear();
userStore.resumeAllState();
location.reload();
}
function renderSidebar() {
const {
headerSetting: { theme: headerTheme },
......@@ -175,7 +132,7 @@ export default defineComponent({
{{
default: () => (
<div
onClick={baseHandler.bind(null, 'layout', {
onClick={baseHandler.bind(null, HandlerEnum.CHANGE_LAYOUT, {
mode: mode,
type: ItemType,
split: unref(getIsHorizontalRef) ? false : undefined,
......@@ -192,14 +149,14 @@ export default defineComponent({
</div>,
renderSwitchItem('分割菜单', {
handler: (e) => {
baseHandler('splitMenu', e);
baseHandler(HandlerEnum.MENU_SPLIT, e);
},
def: split,
disabled: !unref(getShowMenuRef) || type !== MenuTypeEnum.MIX,
}),
renderSelectItem('顶栏主题', {
handler: (e) => {
baseHandler('headerMenu', e);
baseHandler(HandlerEnum.HEADER_THEME, e);
},
def: headerTheme,
options: themeOptions,
......@@ -207,7 +164,7 @@ export default defineComponent({
}),
renderSelectItem('菜单主题', {
handler: (e) => {
baseHandler('menuTheme', e);
baseHandler(HandlerEnum.MENU_THEME, e);
},
def: menuTheme,
options: themeOptions,
......@@ -230,48 +187,49 @@ export default defineComponent({
topMenuAlign,
collapsedShowTitle,
trigger,
accordion,
} = {},
} = appStore.getProjectConfig;
return [
renderSwitchItem('侧边菜单拖拽', {
handler: (e) => {
baseHandler('hasDrag', e);
baseHandler(HandlerEnum.MENU_HAS_DRAG, e);
},
def: hasDrag,
disabled: !unref(getShowMenuRef),
}),
renderSwitchItem('侧边菜单搜索', {
handler: (e) => {
baseHandler('showSearch', e);
baseHandler(HandlerEnum.MENU_SHOW_SEARCH, e);
},
def: showSearch,
disabled: !unref(getShowMenuRef),
}),
renderSwitchItem('侧边菜单手风琴模式', {
handler: (e) => {
baseHandler(HandlerEnum.MENU_ACCORDION, e);
},
def: accordion,
disabled: !unref(getShowMenuRef),
}),
renderSwitchItem('折叠菜单', {
handler: (e) => {
baseHandler('collapsed', e);
baseHandler(HandlerEnum.MENU_COLLAPSED, e);
},
def: collapsed,
disabled: !unref(getShowMenuRef),
}),
renderSwitchItem('折叠菜单显示名称', {
handler: (e) => {
baseHandler('collapsedShowTitle', e);
baseHandler(HandlerEnum.MENU_COLLAPSED_SHOW_TITLE, e);
},
def: collapsedShowTitle,
disabled: !unref(getShowMenuRef) || !collapsed,
}),
renderSwitchItem('固定header', {
handler: (e) => {
baseHandler('headerFixed', e);
},
def: fixed,
disabled: !unref(getShowHeaderRef),
}),
renderSelectItem('顶部菜单布局', {
handler: (e) => {
baseHandler('topMenuAlign', e);
baseHandler(HandlerEnum.MENU_TOP_ALIGN, e);
},
def: topMenuAlign,
options: topMenuAlignOptions,
......@@ -279,14 +237,21 @@ export default defineComponent({
}),
renderSelectItem('菜单折叠按钮', {
handler: (e) => {
baseHandler('menuTrigger', e);
baseHandler(HandlerEnum.MENU_TRIGGER, e);
},
def: trigger,
options: menuTriggerOptions,
}),
renderSwitchItem('固定header', {
handler: (e) => {
baseHandler(HandlerEnum.HEADER_FIXED, e);
},
def: fixed,
disabled: !unref(getShowHeaderRef),
}),
renderSelectItem('内容区域宽度', {
handler: (e) => {
baseHandler('contentMode', e);
baseHandler(HandlerEnum.CONTENT_MODE, e);
},
def: contentMode,
options: contentModeOptions,
......@@ -297,8 +262,8 @@ export default defineComponent({
style="width:120px"
size="small"
min={0}
onChange={(e) => {
baseHandler('lockTime', e);
onChange={(e: any) => {
baseHandler(HandlerEnum.LOCK_TIME, e);
}}
defaultValue={appStore.getProjectConfig.lockTime}
formatter={(value: string) => {
......@@ -321,7 +286,7 @@ export default defineComponent({
defaultValue={menuWidth}
formatter={(value: string) => `${parseInt(value)}px`}
onChange={(e: any) => {
baseHandler('menuWidth', e);
baseHandler(HandlerEnum.MENU_WIDTH, e);
}}
/>
</div>,
......@@ -334,19 +299,19 @@ export default defineComponent({
<>
{renderSwitchItem('页面切换loading', {
handler: (e) => {
baseHandler('openPageLoading', e);
baseHandler(HandlerEnum.OPEN_PAGE_LOADING, e);
},
def: openPageLoading,
})}
{renderSwitchItem('切换动画', {
handler: (e) => {
baseHandler('openRouterTransition', e);
baseHandler(HandlerEnum.OPEN_ROUTE_TRANSITION, e);
},
def: openRouterTransition,
})}
{renderSelectItem('路由动画', {
handler: (e) => {
baseHandler('routerTransition', e);
baseHandler(HandlerEnum.ROUTER_TRANSITION, e);
},
def: routerTransition,
options: routerTransitionOptions,
......@@ -370,289 +335,77 @@ export default defineComponent({
return [
renderSwitchItem('面包屑', {
handler: (e) => {
baseHandler('showBreadCrumb', e);
baseHandler(HandlerEnum.SHOW_BREADCRUMB, e);
},
def: showBreadCrumb,
disabled: !unref(getShowHeaderRef),
}),
renderSwitchItem('面包屑图标', {
handler: (e) => {
baseHandler('showBreadCrumbIcon', e);
baseHandler(HandlerEnum.SHOW_BREADCRUMB_ICON, e);
},
def: showBreadCrumbIcon,
disabled: !unref(getShowHeaderRef),
}),
renderSwitchItem('标签页', {
handler: (e) => {
baseHandler('showMultiple', e);
baseHandler(HandlerEnum.TABS_SHOW, e);
},
def: showMultiple,
}),
renderSwitchItem('标签页快捷按钮', {
handler: (e) => {
baseHandler('showQuick', e);
baseHandler(HandlerEnum.TABS_SHOW_QUICK, e);
},
def: showQuick,
disabled: !unref(getShowTabsRef),
}),
renderSwitchItem('标签页图标', {
handler: (e) => {
baseHandler('showTabIcon', e);
baseHandler(HandlerEnum.TABS_SHOW_ICON, e);
},
def: showTabIcon,
disabled: !unref(getShowTabsRef),
}),
renderSwitchItem('左侧菜单', {
handler: (e) => {
baseHandler('showSidebar', e);
baseHandler(HandlerEnum.MENU_SHOW_SIDEBAR, e);
},
def: showMenu,
disabled: unref(getIsHorizontalRef),
}),
renderSwitchItem('顶栏', {
handler: (e) => {
baseHandler('showHeader', e);
baseHandler(HandlerEnum.HEADER_SHOW, e);
},
def: showHeader,
}),
renderSwitchItem('Logo', {
handler: (e) => {
baseHandler('showLogo', e);
baseHandler(HandlerEnum.SHOW_LOGO, e);
},
def: showLogo,
}),
renderSwitchItem('全屏内容', {
handler: (e) => {
baseHandler('fullContent', e);
baseHandler(HandlerEnum.FULL_CONTENT, e);
},
def: fullContent,
}),
renderSwitchItem('灰色模式', {
handler: (e) => {
baseHandler('grayMode', e);
baseHandler(HandlerEnum.GRAY_MODE, e);
},
def: grayMode,
}),
renderSwitchItem('色弱模式', {
handler: (e) => {
baseHandler('colorWeak', e);
baseHandler(HandlerEnum.COLOR_WEAK, e);
},
def: colorWeak,
}),
];
}
function baseHandler(event: string, value: any) {
let config: DeepPartial<ProjectConfig> = {};
if (event === 'layout') {
const { mode, type, split } = value;
const splitOpt = split === undefined ? { split } : {};
let headerSetting = {};
if (type === MenuTypeEnum.TOP_MENU) {
headerSetting = {
theme: MenuThemeEnum.DARK,
};
}
config = {
menuSetting: {
mode,
type,
collapsed: false,
show: true,
...splitOpt,
},
headerSetting,
};
}
if (event === 'hasDrag') {
config = {
menuSetting: {
hasDrag: value,
},
};
}
if (event === 'menuTrigger') {
config = {
menuSetting: {
trigger: value,
},
};
}
if (event === 'openPageLoading') {
config = {
openPageLoading: value,
};
}
if (event === 'topMenuAlign') {
config = {
menuSetting: {
topMenuAlign: value,
},
};
}
if (event === 'showBreadCrumb') {
config = {
showBreadCrumb: value,
};
}
if (event === 'showBreadCrumbIcon') {
config = {
showBreadCrumbIcon: value,
};
}
if (event === 'collapsed') {
config = {
menuSetting: {
collapsed: value,
},
};
}
if (event === 'menuWidth') {
config = {
menuSetting: {
menuWidth: value,
},
};
}
if (event === 'collapsedShowTitle') {
config = {
menuSetting: {
collapsedShowTitle: value,
},
};
}
if (event === 'lockTime') {
config = {
lockTime: value,
};
}
if (event === 'showQuick') {
config = {
multiTabsSetting: {
showQuick: value,
},
};
}
if (event === 'showTabIcon') {
config = {
multiTabsSetting: {
showIcon: value,
},
};
}
if (event === 'contentMode') {
config = {
contentMode: value,
};
}
if (event === 'menuTheme') {
config = {
menuSetting: {
theme: value,
},
};
}
if (event === 'splitMenu') {
config = {
menuSetting: {
split: value,
},
};
}
if (event === 'showMultiple') {
config = {
multiTabsSetting: {
show: value,
},
};
}
if (event === 'headerMenu') {
config = {
headerSetting: {
theme: value,
},
};
}
if (event === 'grayMode') {
config = {
grayMode: value,
};
updateGrayMode(value);
}
if (event === 'colorWeak') {
config = {
colorWeak: value,
};
updateColorWeak(value);
}
if (event === 'showLogo') {
config = {
showLogo: value,
};
}
if (event === 'showSearch') {
config = {
menuSetting: {
showSearch: value,
},
};
}
if (event === 'showSidebar') {
config = {
menuSetting: {
show: value,
},
};
}
if (event === 'openRouterTransition') {
config = {
openRouterTransition: value,
};
}
if (event === 'routerTransition') {
config = {
routerTransition: value,
};
}
if (event === 'headerFixed') {
config = {
headerSetting: {
fixed: value,
},
};
}
if (event === 'fullContent') {
config = {
fullContent: value,
};
}
if (event === 'showHeader') {
config = {
headerSetting: {
show: value,
},
};
}
appStore.commitProjectConfigState(config);
}
function handleResetSetting() {
try {
appStore.commitProjectConfigState(defaultSetting);
const { colorWeak, grayMode } = defaultSetting;
// updateTheme(themeColor);
updateColorWeak(colorWeak);
updateGrayMode(grayMode);
createMessage.success('重置成功!');
} catch (error) {
createMessage.error(error);
}
}
function handleClearAndRedo() {
localStorage.clear();
userStore.resumeAllState();
location.reload();
}
function renderSelectItem(text: string, config?: SelectConfig) {
const { handler, def, disabled = false, options } = config || {};
......@@ -693,6 +446,7 @@ export default defineComponent({
</div>
);
}
return () => (
<BasicDrawer {...attrs} title="项目配置" width={300} wrapClassName="setting-drawer">
{{
......
import { ContentEnum, RouterTransitionEnum } from '/@/enums/appEnum';
import { MenuThemeEnum, TopMenuAlignEnum, TriggerEnum } from '/@/enums/menuEnum';
export enum HandlerEnum {
CHANGE_LAYOUT,
// menu
MENU_HAS_DRAG,
MENU_ACCORDION,
MENU_TRIGGER,
MENU_TOP_ALIGN,
MENU_COLLAPSED,
MENU_COLLAPSED_SHOW_TITLE,
MENU_WIDTH,
MENU_SHOW_SIDEBAR,
MENU_THEME,
MENU_SPLIT,
MENU_SHOW_SEARCH,
// header
HEADER_SHOW,
HEADER_THEME,
HEADER_FIXED,
TABS_SHOW_QUICK,
TABS_SHOW,
TABS_SHOW_ICON,
OPEN_PAGE_LOADING,
OPEN_ROUTE_TRANSITION,
ROUTER_TRANSITION,
LOCK_TIME,
FULL_CONTENT,
CONTENT_MODE,
SHOW_BREADCRUMB,
SHOW_BREADCRUMB_ICON,
GRAY_MODE,
COLOR_WEAK,
SHOW_LOGO,
}
export const themeOptions = [
{
value: MenuThemeEnum.LIGHT,
label: '亮色',
},
{
value: MenuThemeEnum.DARK,
label: '暗色',
},
];
export const contentModeOptions = [
{
value: ContentEnum.FULL,
label: '流式',
},
{
value: ContentEnum.FIXED,
label: '定宽',
},
];
export const topMenuAlignOptions = [
{
value: TopMenuAlignEnum.CENTER,
label: '居中',
},
{
value: TopMenuAlignEnum.START,
label: '居左',
},
{
value: TopMenuAlignEnum.END,
label: '居右',
},
];
export const menuTriggerOptions = [
{
value: TriggerEnum.NONE,
label: '不显示',
},
{
value: TriggerEnum.FOOTER,
label: '底部',
},
{
value: TriggerEnum.HEADER,
label: '顶部',
},
];
export const routerTransitionOptions = [
RouterTransitionEnum.ZOOM_FADE,
RouterTransitionEnum.FADE,
RouterTransitionEnum.ZOOM_OUT,
RouterTransitionEnum.FADE_SIDE,
RouterTransitionEnum.FADE_BOTTOM,
].map((item) => {
return {
label: item,
value: item,
};
});
import { HandlerEnum } from './const';
import { MenuThemeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
import { updateColorWeak, updateGrayMode } from '/@/setup/theme';
import { appStore } from '/@/store/modules/app';
import { ProjectConfig } from '/@/types/config';
export function baseHandler(event: HandlerEnum, value: any) {
const config = handler(event, value);
appStore.commitProjectConfigState(config);
}
export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConfig> {
switch (event) {
case HandlerEnum.CHANGE_LAYOUT:
const { mode, type, split } = value;
const splitOpt = split === undefined ? { split } : {};
let headerSetting = {};
if (type === MenuTypeEnum.TOP_MENU) {
headerSetting = {
theme: MenuThemeEnum.DARK,
};
}
return {
menuSetting: {
mode,
type,
collapsed: false,
show: true,
...splitOpt,
},
headerSetting,
};
case HandlerEnum.MENU_HAS_DRAG:
return {
menuSetting: {
hasDrag: value,
},
};
case HandlerEnum.MENU_ACCORDION:
return {
menuSetting: {
accordion: value,
},
};
case HandlerEnum.MENU_TRIGGER:
return {
menuSetting: {
trigger: value,
},
};
case HandlerEnum.MENU_TOP_ALIGN:
return {
menuSetting: {
topMenuAlign: value,
},
};
case HandlerEnum.MENU_COLLAPSED:
return {
menuSetting: {
collapsed: value,
},
};
case HandlerEnum.MENU_WIDTH:
return {
menuSetting: {
menuWidth: value,
},
};
case HandlerEnum.MENU_COLLAPSED_SHOW_TITLE:
return {
menuSetting: {
collapsedShowTitle: value,
},
};
case HandlerEnum.MENU_SHOW_SIDEBAR:
return {
menuSetting: {
show: value,
},
};
case HandlerEnum.MENU_THEME:
return {
menuSetting: {
theme: value,
},
};
case HandlerEnum.MENU_SPLIT:
return {
menuSetting: {
split: value,
},
};
case HandlerEnum.MENU_SHOW_SEARCH:
return {
menuSetting: {
showSearch: value,
},
};
case HandlerEnum.OPEN_PAGE_LOADING:
return {
openPageLoading: value,
};
case HandlerEnum.OPEN_ROUTE_TRANSITION:
return {
openRouterTransition: value,
};
case HandlerEnum.ROUTER_TRANSITION:
return {
routerTransition: value,
};
case HandlerEnum.LOCK_TIME:
return {
lockTime: value,
};
case HandlerEnum.FULL_CONTENT:
return {
fullContent: value,
};
case HandlerEnum.CONTENT_MODE:
return {
contentMode: value,
};
case HandlerEnum.SHOW_BREADCRUMB:
return {
showBreadCrumb: value,
};
case HandlerEnum.SHOW_BREADCRUMB_ICON:
return {
showBreadCrumbIcon: value,
};
case HandlerEnum.GRAY_MODE:
updateGrayMode(value);
return {
grayMode: value,
};
case HandlerEnum.COLOR_WEAK:
updateColorWeak(value);
return {
colorWeak: value,
};
case HandlerEnum.SHOW_LOGO:
return {
showLogo: value,
};
case HandlerEnum.TABS_SHOW_QUICK:
return {
multiTabsSetting: {
showQuick: value,
},
};
case HandlerEnum.TABS_SHOW_QUICK:
return {
multiTabsSetting: {
showIcon: value,
},
};
case HandlerEnum.TABS_SHOW:
return {
multiTabsSetting: {
show: value,
},
};
case HandlerEnum.HEADER_THEME:
return {
headerSetting: {
theme: value,
},
};
case HandlerEnum.HEADER_FIXED:
return {
headerSetting: {
fixed: value,
},
};
case HandlerEnum.HEADER_SHOW:
return {
headerSetting: {
show: value,
},
};
default:
return {};
}
}
......@@ -74,6 +74,8 @@ const setting: ProjectConfig = {
collapsedShowSearch: false,
// 折叠触发器的位置
trigger: TriggerEnum.HEADER,
// 开启手风琴模式,只显示一个菜单
accordion: true,
},
// 消息配置
messageSetting: {
......
......@@ -24,6 +24,7 @@ export interface MenuSetting {
topMenuAlign: 'start' | 'center' | 'end';
collapsedShowSearch: boolean;
trigger: TriggerEnum;
accordion: boolean;
}
export interface MultiTabsSetting {
......
......@@ -30,12 +30,16 @@ declare type Indexable<T = any> = {
declare type Hash<T> = Indexable<T>;
// declare type DeepPartial<T> = {
// [P in keyof T]?: T[P] extends (infer U)[]
// ? RecursivePartial<U>[]
// : T[P] extends object
// ? RecursivePartial<T[P]>
// : T[P];
// };
declare type DeepPartial<T> = {
[P in keyof T]?: T[P] extends (infer U)[]
? RecursivePartial<U>[]
: T[P] extends object
? RecursivePartial<T[P]>
: T[P];
[P in keyof T]?: DeepPartial<T[P]>;
};
declare type SelectOptions = {
......
......@@ -42,7 +42,7 @@ export function useThemeMode(mode: ThemeModeEnum) {
};
}
// 初始化项目配置
// Initial project configuration
export function useInitAppConfigStore() {
let projCfg: ProjectConfig = getLocal(PROJ_CFG_KEY) as ProjectConfig;
if (!projCfg) {
......@@ -78,12 +78,12 @@ export function useConfigProvider() {
};
}
// 初始化网络监听
// Initialize network monitoring
export function useListenerNetWork() {
const { listenNetWork } = appStore.getProjectConfig;
if (!listenNetWork) return;
const { replace } = useRouter();
// 检测网络状态
// Check network status
useNetWork({
onLineFn: () => {
replace(PageEnum.BASE_HOME);
......
<template>
<div class="analysis p-4">
<Row class="pl-2">
<a-row class="pl-2">
<template v-for="item in growCardList" :key="item.title">
<ACol :sm="24" :md="12" :lg="6">
<GrowCard :info="item" />
</ACol>
</template>
</Row>
</a-row>
<Row>
<ACol :md="24" :lg="17" class="my-3">
<a-row>
<a-col :md="24" :lg="17" class="my-3">
<CollapseContainer class="mr-3" title="产品成交额" :canExpan="false">
<AnalysisLine />
</CollapseContainer>
<Row class="mt-3">
<ACol :md="24" :lg="12" class="product-total">
<a-row class="mt-3">
<a-col :md="24" :lg="12" class="product-total">
<CollapseContainer class="mr-3" title="产品成交额" :canExpan="false">
<AnalysisPie />
</CollapseContainer>
</ACol>
<ACol :md="24" :lg="12">
</a-col>
<a-col :md="24" :lg="12">
<CollapseContainer class="mr-3" title="用户来源" :canExpan="false">
<AnalysisBar />
</CollapseContainer>
</ACol>
</Row>
</ACol>
<ACol :md="24" :lg="7">
</a-col>
</a-row>
</a-col>
<a-col :md="24" :lg="7">
<CollapseContainer class="mt-3" title="项目进度" :canExpan="false">
<template v-for="item in taskList" :key="item.title">
<TaskCard :info="item" />
</template>
</CollapseContainer>
</ACol>
</Row>
<Row>
</a-col>
</a-row>
<a-row>
<FlowAnalysis />
</Row>
</a-row>
</div>
</template>
<script lang="ts">
......@@ -48,14 +48,11 @@
import AnalysisBar from './components/AnalysisBar.vue';
import TaskCard from './components/TaskCard.vue';
import FlowAnalysis from './components/FlowAnalysis';
import { Row, Col } from 'ant-design-vue';
import { CollapseContainer } from '/@/components/Container/index';
import { growCardList, taskList } from './data';
export default defineComponent({
components: {
Row,
ACol: Col,
GrowCard,
CollapseContainer,
TrendLine,
......
<template>
<Row class="workbench p-4" :gutter="12">
<Col :md="24" :lg="17">
<a-row class="workbench p-4" :gutter="12">
<a-col :md="24" :lg="17">
<ProdTotal class="mb-3" />
<TodoList class="mb-3" />
<NewsList class="mb-3" />
</Col>
<Col :md="24" :lg="7">
</a-col>
<a-col :md="24" :lg="7">
<img src="/@/assets/images/dashboard/wokb/wokb.png" class="workbench__wokb-img mb-3" />
<ShortCuts class="mb-3" />
<Week class="mb-3" />
</Col>
</Row>
</a-col>
</a-row>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Row, Col } from 'ant-design-vue';
import ProdTotal from './components/ProdTotal.vue';
import TodoList from './components/TodoList.vue';
import Week from './components/Week.vue';
......@@ -22,7 +21,7 @@
import ShortCuts from './components/ShortCuts.vue';
export default defineComponent({
components: { Row, Col, ProdTotal, TodoList, Week, ShortCuts, NewsList },
components: { ProdTotal, TodoList, Week, ShortCuts, NewsList },
setup() {
return {};
},
......
......@@ -168,7 +168,7 @@
display: none;
height: 100%;
background: url(../../../assets/images/login/login-in.png) no-repeat;
background-position: 50% 30%;
background-position: 30% 30%;
background-size: 80% 80%;
.respond-to(xlarge, { display: block;});
......@@ -194,9 +194,9 @@
align-items: center;
.respond-to(large, {
width: 600px;
right: calc(50% - 300px);
right: calc(50% - 270px);
});
.respond-to(xlarge, { width: 600px; right:0});
.respond-to(xlarge, { width: 540px; right:0});
}
&__content {
......
......@@ -34,7 +34,7 @@ const viteConfig: UserConfig = {
* @default 'index.html'
*/
// TODO build error
// entry: './public/index.html',
// entry: 'public/index.html',
/**
* port
* @default '3000'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册