'admin-22.12.10:同步vue-next-admin-template分支v2.4.2版本内容'

This commit is contained in:
lyt 2022-12-10 11:06:38 +08:00
parent e0f40f6f5e
commit cef2754806
35 changed files with 1428 additions and 1923 deletions

View File

@ -1,6 +1,12 @@
# <a href="https://gitee.com/lyt-top/vue-next-admin" target="_blank">vue-next-admin-template-js不带国际化 更新日志</a>
🎉🎉🔥 `vue-next-admin-template-js` 基于 vue-next-admin-template v2.4.1 版本) vue3.x 、vite、Element plus 等适配手机、平板、pc 的后台开源免费模板库vue2.x 请切换 vue-prev-admin 分支)
🎉🎉🔥 `vue-next-admin-template-js` 基于 vue-next-admin-template v2.4.2 版本) vue3.x 、vite、Element plus 等适配手机、平板、pc 的后台开源免费模板库vue2.x 请切换 vue-prev-admin 分支)
## 2.4.2
`2022.12.10`
- 🎉 同步 vue-next-admin-template 基础版本(不带国际化) 分支 v2.4.2 版本内容,具体查看 master 分支 CHANGELOG.md
## 2.4.1

View File

@ -20,7 +20,7 @@
<p>&nbsp;</p>
</div>
#### 🌈 介绍 基础版 js不带国际化基于 vue-next-admin-template V2.4.1setup 语法糖)
#### 🌈 介绍 基础版 js不带国际化基于 vue-next-admin-template V2.4.2setup 语法糖)
基于 vue3.x + CompositionAPI setup 语法糖 + typescript + vite + element plus + vue-router-next + pinia 技术适配手机、平板、pc 的后台开源免费模板,希望减少工作量,帮助大家实现快速开发。
@ -43,13 +43,15 @@
| Edge | Firefox | Chrome | Safari |
| --------- | ------------ | ----------- | ----------- |
| Edge ≥ 79 | Firefox ≥ 78 | Chrome ≥ 76 | Safari ≥ 12 |
| Edge ≥ 88 | Firefox ≥ 78 | Chrome ≥ 87 | Safari ≥ 13 |
> 由于 Vue3 不再支持 IE11故而 ElementPlus 也不支持 IE11 及之前版本。
#### ⚡ 使用说明
建议使用 cnpm因为 yarn 有时会报错。<a href="http://nodejs.cn/" target="_blank">node 版本 > 14xx.xx.x</a>
建议使用 cnpm因为 yarn 有时会报错。<a href="http://nodejs.cn/" target="_blank">node 版本 > 14.18+/16+</a>
> Vite 不再支持 Node 12 / 13 / 15因为上述版本已经进入了 EOL 阶段。现在你必须使用 Node 14.18+ / 16+ 版本。
```bash
# 克隆项目

1415
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "vue-next-admin-template-js",
"version": "2.4.1",
"version": "2.4.2",
"description": "vue3 vite next admin template js setup",
"author": "lyt_20201208",
"license": "MIT",
@ -11,29 +11,30 @@
},
"dependencies": {
"@element-plus/icons-vue": "^2.0.10",
"axios": "^1.2.0",
"echarts": "^5.4.0",
"element-plus": "^2.2.25",
"axios": "^1.2.1",
"echarts": "^5.4.1",
"element-plus": "^2.2.26",
"js-cookie": "^3.0.1",
"mitt": "^3.0.0",
"nprogress": "^0.2.0",
"pinia": "^2.0.27",
"pinia": "^2.0.28",
"qrcodejs2-fixes": "^0.0.2",
"screenfull": "^6.0.2",
"sortablejs": "^1.15.0",
"vue": "^3.2.45",
"vue-clipboard3": "^2.0.0",
"qs": "^6.11.0",
"vue-router": "^4.1.6"
},
"devDependencies": {
"@vitejs/plugin-vue": "^3.2.0",
"@vitejs/plugin-vue": "^4.0.0",
"@vue/compiler-sfc": "^3.2.45",
"eslint": "^8.28.0",
"eslint": "^8.29.0",
"eslint-plugin-vue": "^9.8.0",
"prettier": "^2.8.0",
"sass": "^1.56.1",
"prettier": "^2.8.1",
"sass": "^1.56.2",
"unplugin-auto-import": "^0.12.0",
"vite": "^3.2.4",
"vite": "^4.0.0",
"vite-plugin-vue-setup-extend": "^0.4.0",
"vue-eslint-parser": "^9.1.0"
},
@ -46,7 +47,7 @@
"url": "https://gitee.com/lyt-top/vue-next-admin/issues"
},
"engines": {
"node": ">=14.0.0",
"node": ">=16.0.0",
"npm": ">= 7.0.0"
},
"keywords": [

View File

@ -1,17 +1,27 @@
import request from '/@/utils/request';
/**
* 不建议写成 request.post(xxx)因为这样 post 无法 params data 同时传参
*
* 登录api接口集合
* @method signIn 用户登录
* @method signOut 用户退出登录
*/
export function useLoginApi() {
return {
signIn: (params) => {
return request.post('/user/signIn', params);
signIn: (data) => {
return request({
url: '/user/signIn',
method: 'post',
data,
});
},
signOut: (params) => {
return request.post('/user/signOut', params);
signOut: (data) => {
return request({
url: '/user/signOut',
method: 'post',
data,
});
},
};
}

View File

@ -3,6 +3,8 @@ import request from '/@/utils/request';
/**
* 以下为模拟接口地址gitee 的不通就换自己的真实接口地址
*
* 不建议写成 request.post(xxx)因为这样 post 无法 params data 同时传参
*
* 后端控制菜单模拟json路径在 https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu
* 后端控制路由isRequestRoutes true则开启后端控制路由
* @method getAdminMenu 获取后端动态路由菜单(admin)
@ -11,10 +13,18 @@ import request from '/@/utils/request';
export function useMenuApi() {
return {
getAdminMenu: (params) => {
return request.get('/gitee/lyt-top/vue-next-admin-images/raw/master/menu/adminMenu.json', params);
return request({
url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/adminMenu.json',
method: 'get',
params,
});
},
getTestMenu: (params) => {
return request.get('/gitee/lyt-top/vue-next-admin-images/raw/master/menu/testMenu.json', params);
return request({
url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/testMenu.json',
method: 'get',
params,
});
},
};
}

View File

@ -1,67 +1,48 @@
<template>
<div class="icon-selector w100 h100">
<el-input
v-model="state.fontIconSearch"
:placeholder="state.fontIconPlaceholder"
:clearable="clearable"
:disabled="disabled"
:size="size"
ref="inputWidthRef"
@clear="onClearFontIcon"
@focus="onIconFocus"
@blur="onIconBlur"
>
<template #prepend>
<SvgIcon
:name="state.fontIconPrefix === '' ? prepend : state.fontIconPrefix"
class="font14"
v-if="state.fontIconPrefix === '' ? prepend?.indexOf('ele-') > -1 : state.fontIconPrefix?.indexOf('ele-') > -1"
/>
<i v-else :class="state.fontIconPrefix === '' ? prepend : state.fontIconPrefix" class="font14"></i>
</template>
</el-input>
<el-popover
placement="bottom"
:width="state.fontIconWidth"
trigger="click"
transition="el-zoom-in-top"
popper-class="icon-selector-popper"
@show="onPopoverShow"
trigger="click"
:virtual-ref="inputWidthRef"
virtual-triggering
>
<template #reference>
<el-input
v-model="state.fontIconSearch"
:placeholder="state.fontIconPlaceholder"
:clearable="clearable"
:disabled="disabled"
:size="size"
ref="inputWidthRef"
@clear="onClearFontIcon"
@focus="onIconFocus"
@blur="onIconBlur"
>
<template #prepend>
<SvgIcon
:name="state.fontIconPrefix === '' ? prepend : state.fontIconPrefix"
class="font14"
v-if="state.fontIconPrefix === '' ? prepend?.indexOf('ele-') > -1 : state.fontIconPrefix?.indexOf('ele-') > -1"
/>
<i v-else :class="state.fontIconPrefix === '' ? prepend : state.fontIconPrefix" class="font14"></i>
</template>
</el-input>
</template>
<template #default>
<div class="icon-selector-warp">
<div class="icon-selector-warp-title flex">
<div class="flex-auto">{{ title }}</div>
<div class="icon-selector-warp-title-tab" v-if="type === 'all'">
<span :class="{ 'span-active': state.fontIconType === 'ali' }" @click="onIconChange('ali')" class="ml10" title="iconfont 图标">
ali
</span>
<span :class="{ 'span-active': state.fontIconType === 'ele' }" @click="onIconChange('ele')" class="ml10" title="elementPlus 图标">
ele
</span>
<span :class="{ 'span-active': state.fontIconType === 'awe' }" @click="onIconChange('awe')" class="ml10" title="fontawesome 图标">
awe
</span>
</div>
</div>
<div class="icon-selector-warp-row">
<el-scrollbar ref="selectorScrollbarRef">
<el-row :gutter="10" v-if="fontIconSheetsFilterList.length > 0">
<el-col :xs="6" :sm="4" :md="4" :lg="4" :xl="4" @click="onColClick(v)" v-for="(v, k) in fontIconSheetsFilterList" :key="k">
<div class="icon-selector-warp-item" :class="{ 'icon-selector-active': state.fontIconPrefix === v }">
<div class="flex-margin">
<div class="icon-selector-warp-item-value">
<SvgIcon :name="v" />
</div>
</div>
</div>
</el-col>
</el-row>
<el-empty :image-size="100" v-if="fontIconSheetsFilterList.length <= 0" :description="emptyDescription"></el-empty>
</el-scrollbar>
</div>
<div class="icon-selector-warp-title">{{ title }}</div>
<el-tabs v-model="state.fontIconTabActive" @tab-click="onIconClick">
<el-tab-pane lazy label="ali" name="ali">
<IconList :list="fontIconSheetsFilterList" :empty="emptyDescription" :prefix="state.fontIconPrefix" @get-icon="onColClick" />
</el-tab-pane>
<el-tab-pane lazy label="ele" name="ele">
<IconList :list="fontIconSheetsFilterList" :empty="emptyDescription" :prefix="state.fontIconPrefix" @get-icon="onColClick" />
</el-tab-pane>
<el-tab-pane lazy label="awe" name="awe">
<IconList :list="fontIconSheetsFilterList" :empty="emptyDescription" :prefix="state.fontIconPrefix" @get-icon="onColClick" />
</el-tab-pane>
</el-tabs>
</div>
</template>
</el-popover>
@ -76,29 +57,24 @@ import '/@/theme/iconSelector.scss';
const props = defineProps({
//
prepend: {
type,
type: String,
default: () => 'ele-Pointer',
},
//
placeholder: {
type,
type: String,
default: () => '请输入内容搜索图标或者选择图标',
},
//
size: {
type,
type: String,
default: () => 'default',
},
//
title: {
type,
type: String,
default: () => '请选择图标',
},
// icon
type: {
type,
default: () => 'ele',
},
//
disabled: {
type: Boolean,
@ -111,30 +87,34 @@ const props = defineProps({
},
//
emptyDescription: {
type,
type: String,
default: () => '无相关图标',
},
// modelValue
// https://v3.cn.vuejs.org/guide/migration/v-model.html#%E8%BF%81%E7%A7%BB%E7%AD%96%E7%95%A5
// https://v3.cn.vuejs.org/guide/component-custom-events.html#%E5%A4%9A%E4%B8%AA-v-model-%E7%BB%91%E5%AE%9A
modelValue,
modelValue: String,
});
// /
const emit = defineEmits(['update:modelValue', 'get', 'clear']);
//
const IconList = defineAsyncComponent(() => import('/@/components/iconSelector/list.vue'));
//
const inputWidthRef = ref();
const selectorScrollbarRef = ref();
const state = reactive({
fontIconPrefix: '',
fontIconWidth: 0,
fontIconSearch: '',
fontIconTabsIndex: 0,
fontIconSheetsList: [],
fontIconPlaceholder: '',
fontIconType: 'ali',
fontIconShow: true,
fontIconTabActive: 'ali',
fontIconList: {
ali: [],
ele: [],
awe: [],
},
});
// input modelValue input placeholder
@ -145,32 +125,91 @@ const onIconFocus = () => {
};
// input input
const onIconBlur = () => {
const list = fontIconTabNameList();
setTimeout(() => {
const icon = state.fontIconSheetsList.filter((icon) => icon === state.fontIconSearch);
const icon = list.filter((icon) => icon === state.fontIconSearch);
if (icon.length <= 0) state.fontIconSearch = '';
}, 300);
};
//
const fontIconSheetsFilterList = computed(() => {
const list = fontIconTabNameList();
if (!state.fontIconSearch) return list;
let search = state.fontIconSearch.trim().toLowerCase();
return list.filter((item) => {
if (item.toLowerCase().indexOf(search) !== -1) return item;
});
});
// tab name
const fontIconTabNameList = () => {
let iconList = [];
if (state.fontIconTabActive === 'ali') iconList = state.fontIconList.ali;
else if (state.fontIconTabActive === 'ele') iconList = state.fontIconList.ele;
else if (state.fontIconTabActive === 'awe') iconList = state.fontIconList.awe;
return iconList;
};
// icon
const initModeValueEcho = () => {
if (props.modelValue === '') return (state.fontIconPlaceholder = props.placeholder);
state.fontIconPlaceholder = props.modelValue;
state.fontIconPrefix = props.modelValue;
};
// icon type all alieleawe
const initFontIconTypeEcho = () => {
if (props.modelValue.indexOf('iconfont') > -1) onIconChange('ali');
else if (props.modelValue.indexOf('ele-') > -1) onIconChange('ele');
else if (props.modelValue.indexOf('fa') > -1) onIconChange('awe');
else onIconChange('ali');
// icon tab
const initFontIconName = () => {
let name = 'ali';
if (props.modelValue.indexOf('iconfont') > -1) name = 'ali';
else if (props.modelValue.indexOf('ele-') > -1) name = 'ele';
else if (props.modelValue.indexOf('fa') > -1) name = 'awe';
// tab
state.fontIconTabActive = name;
return name;
};
//
const initFontIconData = async (name) => {
if (name === 'ali') {
// 使 `iconfont xxx`
if (state.fontIconList.ali.length > 0) return;
await initIconfont.ali().then((res) => {
state.fontIconList.ali = res.map((i) => `iconfont ${i}`);
});
} else if (name === 'ele') {
// element plus
if (state.fontIconList.ele.length > 0) return;
await initIconfont.ele().then((res) => {
state.fontIconList.ele = res;
});
} else if (name === 'awe') {
// fontawesome使 `fa xxx`
if (state.fontIconList.awe.length > 0) return;
await initIconfont.awe().then((res) => {
state.fontIconList.awe = res.map((i) => `fa ${i}`);
});
}
// input placeholder
// https://cn.vuejs.org/v2/guide/components-props.html?#%E5%8D%95%E5%90%91%E6%95%B0%E6%8D%AE%E6%B5%81
state.fontIconPlaceholder = props.placeholder;
//
initModeValueEcho();
};
//
const onIconClick = (pane) => {
initFontIconData(pane.paneName);
inputWidthRef.value.focus();
};
// icon
const onColClick = (v) => {
state.fontIconPlaceholder = v;
state.fontIconPrefix = v;
emit('get', state.fontIconPrefix);
emit('update:modelValue', state.fontIconPrefix);
inputWidthRef.value.focus();
};
// icon
const onClearFontIcon = () => {
state.fontIconPrefix = '';
emit('clear', state.fontIconPrefix);
emit('update:modelValue', state.fontIconPrefix);
};
//
const fontIconSheetsFilterList = computed(() => {
if (!state.fontIconSearch) return state.fontIconSheetsList;
let search = state.fontIconSearch.trim().toLowerCase();
return state.fontIconSheetsList.filter((item) => {
if (item.toLowerCase().indexOf(search) !== -1) return item;
});
});
// input
const getInputWidth = () => {
nextTick(() => {
@ -183,56 +222,9 @@ const initResize = () => {
getInputWidth();
});
};
//
const initFontIconData = async (type) => {
state.fontIconSheetsList = [];
if (type === 'ali') {
await initIconfont.ali().then((res) => {
// 使 `iconfont xxx`
state.fontIconSheetsList = res.map((i) => `iconfont ${i}`);
});
} else if (type === 'ele') {
await initIconfont.ele().then((res) => {
state.fontIconSheetsList = res;
});
} else if (type === 'awe') {
await initIconfont.awe().then((res) => {
// fontawesome使 `fa xxx`
state.fontIconSheetsList = res.map((i) => `fa ${i}`);
});
}
// input placeholder
// https://cn.vuejs.org/v2/guide/components-props.html?#%E5%8D%95%E5%90%91%E6%95%B0%E6%8D%AE%E6%B5%81
state.fontIconPlaceholder = props.placeholder;
//
initModeValueEcho();
};
//
const onIconChange = (type) => {
state.fontIconType = type;
initFontIconData(type);
};
// icon
const onColClick = (v) => {
state.fontIconPlaceholder = v;
state.fontIconPrefix = v;
emit('get', state.fontIconPrefix);
emit('update:modelValue', state.fontIconPrefix);
};
// icon
const onClearFontIcon = () => {
state.fontIconPrefix = '';
emit('clear', state.fontIconPrefix);
emit('update:modelValue', state.fontIconPrefix);
};
// Popover
const onPopoverShow = () => {
initModeValueEcho();
initFontIconTypeEcho();
};
//
onMounted(() => {
initModeValueEcho();
initFontIconData(initFontIconName());
initResize();
getInputWidth();
});
@ -241,6 +233,7 @@ watch(
() => props.modelValue,
() => {
initModeValueEcho();
initFontIconName();
}
);
</script>

View File

@ -0,0 +1,84 @@
<template>
<div class="icon-selector-warp-row">
<el-scrollbar ref="selectorScrollbarRef">
<el-row :gutter="10" v-if="props.list.length > 0">
<el-col :xs="6" :sm="4" :md="4" :lg="4" :xl="4" v-for="(v, k) in list" :key="k" @click="onColClick(v)">
<div class="icon-selector-warp-item" :class="{ 'icon-selector-active': prefix === v }">
<SvgIcon :name="v" />
</div>
</el-col>
</el-row>
<el-empty :image-size="100" v-if="list.length <= 0" :description="empty"></el-empty>
</el-scrollbar>
</div>
</template>
<script setup name="iconSelectorList">
//
const props = defineProps({
//
list: {
type: Array,
default: () => [],
},
//
empty: {
type: String,
default: () => '无相关图标',
},
//
prefix: {
type: String,
default: () => '',
},
});
// /
const emit = defineEmits(['get-icon']);
// icon
const onColClick = (v) => {
emit('get-icon', v);
};
</script>
<style scoped lang="scss">
.icon-selector-warp-row {
height: 230px;
overflow: hidden;
.el-row {
padding: 15px;
}
.el-scrollbar__bar.is-horizontal {
display: none;
}
.icon-selector-warp-item {
display: flex;
justify-content: center;
align-items: center;
border: 1px solid var(--el-border-color);
border-radius: 5px;
margin-bottom: 10px;
height: 30px;
i {
font-size: 20px;
color: var(--el-text-color-regular);
}
&:hover {
cursor: pointer;
background-color: var(--el-color-primary-light-9);
border: 1px solid var(--el-color-primary-light-5);
i {
color: var(--el-color-primary);
}
}
}
.icon-selector-active {
background-color: var(--el-color-primary-light-9);
border: 1px solid var(--el-color-primary-light-5);
i {
color: var(--el-color-primary);
}
}
}
</style>

View File

@ -241,7 +241,7 @@ const refreshCurrentTagsView = async (fullPath) => {
};
// 3 tagsViewisAffix
const closeCurrentTagsView = (path) => {
state.tagsViewList.map((v, k, arrs) => {
state.tagsViewList.map((v, k, arr) => {
if (!v.meta?.isAffix) {
if (getThemeConfig.value.isShareTagsView ? v.path === path : v.url === path) {
storesKeepALiveNames.delCachedView(v);

View File

@ -78,9 +78,13 @@ onMounted(() => {
getIframeListRoutes();
// https://gitee.com/lyt-top/vue-next-admin/issues/I58U75
// https://gitee.com/lyt-top/vue-next-admin/issues/I59RXK
// https://gitee.com/lyt-top/vue-next-admin/pulls/40
nextTick(() => {
setTimeout(() => {
if (themeConfig.value.isCacheTagsView) cachedViews.value = Session.get('tagsViewList')?.map((item) => item.name);
if (themeConfig.value.isCacheTagsView) {
let tagsViewArr = Session.get('tagsViewList') || [];
cachedViews.value = tagsViewArr.filter((item) => item.meta?.isKeepAlive).map((item) => item.name);
}
}, 0);
});
});

View File

@ -16,6 +16,11 @@
</div>
<div class="upgrade-content">
{{ getThemeConfig.globalTitle }} 新版本来啦马上更新尝鲜吧不用担心更新很快的哦
<div class="mt5">
<el-link type="primary" class="font12" href="https://gitee.com/lyt-top/vue-next-admin/blob/master/CHANGELOG.md" target="_black">
CHANGELOG.md
</el-link>
</div>
<div class="upgrade-content-desc mt5">提示更新会还原默认配置</div>
</div>
<div class="upgrade-btn">
@ -35,7 +40,7 @@ import { Local } from '/@/utils/storage';
const storesThemeConfig = useThemeConfig();
const { themeConfig } = storeToRefs(storesThemeConfig);
const state = reactive({
isUpgrade: true,
isUpgrade: false,
version: __VERSION__,
isLoading: false,
btnTxt: '',
@ -59,8 +64,15 @@ const onUpgrade = () => {
Local.set('version', state.version);
}, 2000);
};
//
const delayShow = () => {
setTimeout(() => {
state.isUpgrade = true;
}, 2000);
};
//
onMounted(() => {
delayShow();
setTimeout(() => {
state.btnTxt = '马上更新';
}, 200);
@ -86,7 +98,7 @@ onMounted(() => {
&::after {
content: '';
position: absolute;
background-color: var(--el-color-primary);
background-color: var(--el-color-primary-light-1);
width: 130%;
height: 130px;
border-bottom-left-radius: 100%;
@ -101,7 +113,8 @@ onMounted(() => {
letter-spacing: 3px;
}
.upgrade-title-warp-version {
background-color: var(--next-color-white);
color: var(--next-color-white);
background-color: var(--el-color-primary-light-4);
font-size: 12px;
position: absolute;
display: flex;

View File

@ -42,6 +42,9 @@ export async function initBackEndControlRoutes() {
await useUserInfo().setUserInfos();
// 获取路由菜单数据
const res = await getBackEndControlRoutes();
// 无登录权限时,添加判断
// https://gitee.com/lyt-top/vue-next-admin/issues/I64HVO
if (res.data.length <= 0) return Promise.resolve(true);
// 存储接口原始路由未处理component根据需求选择使用
useRequestOldRoutes().setRequestOldRoutes(JSON.parse(JSON.stringify(res.data)));
// 处理路由component替换 dynamicRoutes/@/router/route第一个顶级 children 的路由
@ -57,7 +60,7 @@ export async function initBackEndControlRoutes() {
* @description 用于左侧菜单横向菜单的显示
* @description 用于 tagsView菜单搜索中未过滤隐藏的(isHide)
*/
export function setFilterMenuAndCacheTagsViewRoutes() {
export async function setFilterMenuAndCacheTagsViewRoutes() {
const storesRoutesList = useRoutesList(pinia);
storesRoutesList.setRoutesList(dynamicRoutes[0].children);
setCacheTagsViewRoutes();
@ -118,8 +121,8 @@ export function getBackEndControlRoutes() {
* @description 用于菜单管理界面刷新菜单未进行测试
* @description 路径/src/views/system/menu/component/addMenu.vue
*/
export function setBackEndControlRefreshRoutes() {
getBackEndControlRoutes();
export async function setBackEndControlRefreshRoutes() {
await getBackEndControlRoutes();
}
/**

View File

@ -25,6 +25,9 @@ export async function initFrontEndControlRoutes() {
// 触发初始化用户信息 pinia
// https://gitee.com/lyt-top/vue-next-admin/issues/I5F1HP
await useUserInfo(pinia).setUserInfos();
// 无登录权限时,添加判断
// https://gitee.com/lyt-top/vue-next-admin/issues/I64HVO
if (useUserInfo().userInfos.roles.length <= 0) return Promise.resolve(true);
// 添加动态路由
await setAddRoute();
// 设置递归过滤有权限的路由到 pinia routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组

View File

@ -89,13 +89,13 @@ export const useThemeConfig = defineStore('themeConfig', {
// 是否开启 TagsView 共用
isShareTagsView: false,
// 是否开启 Footer 底部版权信息
isFooter: true,
isFooter: false,
// 是否开启灰色模式
isGrayscale: true,
isGrayscale: false,
// 是否开启色弱模式
isInvert: false,
// 是否开启水印
isWartermark: false,
isWartermark: true,
// 水印文案
wartermarkText: 'vue-next-admin',

View File

@ -19,9 +19,6 @@
/* Input 输入框InputNumber 计数器
------------------------------- */
.el-input {
height: 100%;
}
// 菜单搜索
.el-autocomplete-suggestion__wrap {
max-height: 280px !important;

View File

@ -5,64 +5,25 @@
.icon-selector-warp {
height: 260px;
overflow: hidden;
position: relative;
.icon-selector-warp-title {
position: absolute;
height: 40px;
line-height: 40px;
padding: 0 15px;
.icon-selector-warp-title-tab {
span {
cursor: pointer;
&:hover {
color: var(--el-color-primary);
text-decoration: underline;
}
}
.span-active {
color: var(--el-color-primary);
text-decoration: underline;
}
}
left: 15px;
}
.icon-selector-warp-row {
height: 230px;
overflow: hidden;
border-top: 1px solid var(--el-border-color);
.el-row {
padding: 15px;
}
.el-scrollbar__bar.is-horizontal {
display: none;
}
.icon-selector-warp-item {
display: flex;
border: 1px solid var(--el-border-color);
padding: 5px;
border-radius: 5px;
margin-bottom: 10px;
.icon-selector-warp-item-value {
i {
font-size: 20px;
color: var(--el-text-color-regular);
}
.el-tabs__header {
display: flex;
justify-content: flex-end;
padding: 0 15px;
border-bottom: 1px solid var(--el-border-color-light);
margin: 0 !important;
.el-tabs__nav-wrap {
&::after {
height: 0 !important;
}
&:hover {
cursor: pointer;
background-color: var(--el-color-primary-light-9);
border: 1px solid var(--el-color-primary-light-5);
.icon-selector-warp-item-value {
i {
color: var(--el-color-primary);
}
}
}
}
.icon-selector-active {
background-color: var(--el-color-primary-light-9);
border: 1px solid var(--el-color-primary-light-5);
.icon-selector-warp-item-value {
i {
color: var(--el-color-primary);
}
.el-tabs__item {
padding: 0 5px !important;
}
}
}

View File

@ -16,4 +16,16 @@
// 响应式表单时登录页需要重新处理
display: unset !important;
}
// 表格演示中的表单筛选
.table-form-btn {
display: flex !important;
.el-form-item__label {
width: auto !important;
}
}
// 表格演示中的表单筛选最大高度适配移动端
.table-search-container {
max-height: 160px;
overflow: auto;
}
}

View File

@ -1,5 +1,6 @@
import axios from 'axios';
import { ElMessage, ElMessageBox } from 'element-plus';
import qs from 'qs';
import { Session } from '/@/utils/storage';
// 配置新建一个 axios 实例
@ -7,6 +8,11 @@ const service = axios.create({
baseURL: import.meta.env.VITE_API_URL,
timeout: 50000,
headers: { 'Content-Type': 'application/json' },
paramsSerializer: {
serialize(params) {
return qs.stringify(params, { allowDots: true });
},
},
});
// 添加请求拦截器

View File

@ -84,37 +84,41 @@ const onSignIn = async () => {
Cookies.set('userName', state.ruleForm.userName);
if (!themeConfig.value.isRequestRoutes) {
// 2
await initFrontEndControlRoutes();
signInSuccess();
const isNoPower = await initFrontEndControlRoutes();
signInSuccess(isNoPower);
} else {
// isRequestRoutes true
// router No match found for location with path "/"
await initBackEndControlRoutes();
const isNoPower = await initBackEndControlRoutes();
// initBackEndControlRoutes signInSuccess
signInSuccess();
signInSuccess(isNoPower);
}
};
//
const signInSuccess = () => {
//
let currentTimeInfo = currentTime.value;
//
// /
if (route.query?.redirect) {
router.push({
path: route.query?.redirect,
query: Object.keys(route.query?.params).length > 0 ? JSON.parse(route.query?.params) : '',
});
const signInSuccess = (isNoPower) => {
if (isNoPower) {
ElMessage.warning('抱歉,您没有登录权限');
Session.clear();
} else {
router.push('/');
//
let currentTimeInfo = currentTime.value;
//
// /
if (route.query?.redirect) {
router.push({
path: route.query?.redirect,
query: Object.keys(route.query?.params).length > 0 ? JSON.parse(route.query?.params) : '',
});
} else {
router.push('/');
}
//
const signInText = '欢迎回来!';
ElMessage.success(`${currentTimeInfo}${signInText}`);
// loading
NextLoading.start();
}
//
// loading
state.loading.signIn = true;
const signInText = '欢迎回来!';
ElMessage.success(`${currentTimeInfo}${signInText}`);
// loading
NextLoading.start();
state.loading.signIn = false;
};
</script>

View File

@ -1,146 +0,0 @@
<template>
<div class="system-edit-dept-container">
<el-dialog title="修改部门" v-model="state.isShowDialog" width="769px">
<el-form :model="state.ruleForm" size="default" label-width="90px">
<el-row :gutter="35">
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="上级部门">
<el-cascader
:options="state.deptData"
:props="{ checkStrictly: true, value: 'deptName', label: 'deptName' }"
placeholder="请选择部门"
clearable
class="w100"
v-model="state.ruleForm.deptLevel"
>
<template #default="{ node, data }">
<span>{{ data.deptName }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="部门名称">
<el-input v-model="state.ruleForm.deptName" placeholder="请输入部门名称" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="负责人">
<el-input v-model="state.ruleForm.person" placeholder="请输入负责人" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="手机号">
<el-input v-model="state.ruleForm.phone" placeholder="请输入手机号" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="邮箱">
<el-input v-model="state.ruleForm.email" placeholder="请输入" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="排序">
<el-input-number v-model="state.ruleForm.sort" :min="0" :max="999" controls-position="right" placeholder="请输入排序" class="w100" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="部门状态">
<el-switch v-model="state.ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="部门描述">
<el-input v-model="state.ruleForm.describe" type="textarea" placeholder="请输入部门描述" maxlength="150"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="systemEditDept">
//
const state = reactive({
isShowDialog: false,
ruleForm: {
deptLevel: [], //
deptName: '', //
person: '', //
phone: '', //
email: '', //
sort: 0, //
status: true, //
describe: '', //
},
deptData: [], //
});
//
const openDialog = (row) => {
row.deptLevel = ['vueNextAdmin'];
row.person = 'lyt';
row.phone = '12345678910';
row.email = 'vueNextAdmin@123.com';
state.ruleForm = row;
state.isShowDialog = true;
};
//
const closeDialog = () => {
state.isShowDialog = false;
};
//
const onCancel = () => {
closeDialog();
};
//
const onSubmit = () => {
closeDialog();
};
//
const initTableData = () => {
state.deptData.push({
deptName: 'vueNextAdmin',
createTime: new Date().toLocaleString(),
status: true,
sort: Math.random(),
describe: '顶级部门',
id: Math.random(),
children: [
{
deptName: 'IT外包服务',
createTime: new Date().toLocaleString(),
status: true,
sort: Math.random(),
describe: '总部',
id: Math.random(),
},
{
deptName: '资本控股',
createTime: new Date().toLocaleString(),
status: true,
sort: Math.random(),
describe: '分部',
id: Math.random(),
},
],
});
};
//
onMounted(() => {
initTableData();
});
//
defineExpose({
openDialog,
});
</script>

View File

@ -1,7 +1,7 @@
<template>
<div class="system-add-dept-container">
<el-dialog title="新增部门" v-model="state.isShowDialog" width="769px">
<el-form :model="state.ruleForm" size="default" label-width="90px">
<div class="system-dept-dialog-container">
<el-dialog :title="state.dialog.title" v-model="state.dialog.isShowDialog" width="769px">
<el-form ref="deptDialogFormRef" :model="state.ruleForm" size="default" label-width="90px">
<el-row :gutter="35">
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="上级部门">
@ -60,17 +60,20 @@
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="systemAddDept">
<script setup name="systemDeptDialog">
// /
const emit = defineEmits(['refresh']);
//
const deptDialogFormRef = ref();
const state = reactive({
isShowDialog: false,
ruleForm: {
deptLevel: [], //
deptName: '', //
@ -82,26 +85,51 @@ const state = reactive({
describe: '', //
},
deptData: [], //
dialog: {
isShowDialog: false,
type: '',
title: '',
submitTxt: '',
},
});
//
const openDialog = () => {
state.isShowDialog = true;
const openDialog = (type, row) => {
if (type === 'edit') {
row.deptLevel = ['vueNextAdmin'];
row.person = 'lyt';
row.phone = '12345678910';
row.email = 'vueNextAdmin@123.com';
state.ruleForm = row;
state.dialog.title = '修改部门';
state.dialog.submitTxt = '修 改';
} else {
state.dialog.title = '新增部门';
state.dialog.submitTxt = '新 增';
// 使
// nextTick(() => {
// deptDialogFormRef.value.resetFields();
// });
}
state.dialog.isShowDialog = true;
getMenuData();
};
//
const closeDialog = () => {
state.isShowDialog = false;
state.dialog.isShowDialog = false;
};
//
const onCancel = () => {
closeDialog();
};
//
//
const onSubmit = () => {
closeDialog();
emit('refresh');
// if (state.dialog.type === 'add') { }
};
//
const initTableData = () => {
const getMenuData = () => {
state.deptData.push({
deptName: 'vueNextAdmin',
createTime: new Date().toLocaleString(),
@ -129,10 +157,6 @@ const initTableData = () => {
],
});
};
//
onMounted(() => {
initTableData();
});
//
defineExpose({

View File

@ -9,7 +9,7 @@
</el-icon>
查询
</el-button>
<el-button size="default" type="success" class="ml10" @click="onOpenAddDept">
<el-button size="default" type="success" class="ml10" @click="onOpenAddDept('add')">
<el-icon>
<ele-FolderAdd />
</el-icon>
@ -18,6 +18,7 @@
</div>
<el-table
:data="state.tableData.data"
v-loading="state.tableData.loading"
style="width: 100%"
row-key="id"
default-expand-all
@ -39,15 +40,14 @@
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" show-overflow-tooltip width="140">
<template #default="scope">
<el-button size="small" text type="primary" @click="onOpenAddDept">新增</el-button>
<el-button size="small" text type="primary" @click="onOpenEditDept(scope.row)">修改</el-button>
<el-button size="small" text type="primary" @click="onOpenAddDept('add')">新增</el-button>
<el-button size="small" text type="primary" @click="onOpenEditDept('edit', scope.row)">修改</el-button>
<el-button size="small" text type="primary" @click="onTabelRowDel(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<AddDept ref="addDeptRef" />
<EditDept ref="editDeptRef" />
<DeptDialog ref="deptDialogRef" @refresh="getTableData()" />
</div>
</template>
@ -55,12 +55,10 @@
import { ElMessageBox, ElMessage } from 'element-plus';
//
const AddDept = defineAsyncComponent(() => import('/@/views/system/dept/component/addDept.vue'));
const EditDept = defineAsyncComponent(() => import('/@/views/system/dept/component/editDept.vue'));
const DeptDialog = defineAsyncComponent(() => import('/@/views/system/dept/dialog.vue'));
//
const addDeptRef = ref();
const editDeptRef = ref();
const deptDialogRef = ref();
const state = reactive({
tableData: {
data: [],
@ -74,7 +72,9 @@ const state = reactive({
});
//
const initTableData = () => {
const getTableData = () => {
state.tableData.loading = true;
state.tableData.data = [];
state.tableData.data.push({
deptName: 'vueNextAdmin',
createTime: new Date().toLocaleString(),
@ -102,14 +102,17 @@ const initTableData = () => {
],
});
state.tableData.total = state.tableData.data.length;
setTimeout(() => {
state.tableData.loading = false;
}, 500);
};
//
const onOpenAddDept = () => {
addDeptRef.value.openDialog();
const onOpenAddDept = (type) => {
deptDialogRef.value.openDialog(type);
};
//
const onOpenEditDept = (row) => {
editDeptRef.value.openDialog(row);
const onOpenEditDept = (type, row) => {
deptDialogRef.value.openDialog(type, row);
};
//
const onTabelRowDel = (row) => {
@ -119,12 +122,13 @@ const onTabelRowDel = (row) => {
type: 'warning',
})
.then(() => {
getTableData();
ElMessage.success('删除成功');
})
.catch(() => {});
};
//
onMounted(() => {
initTableData();
getTableData();
});
</script>

View File

@ -1,112 +0,0 @@
<template>
<div class="system-add-dic-container">
<el-dialog title="新增字典" v-model="state.isShowDialog" width="769px">
<el-alert title="半成品,交互过于复杂,请自行扩展!" type="warning" :closable="false" class="mb20"> </el-alert>
<el-form :model="state.ruleForm" size="default" label-width="90px">
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="字典名称">
<el-input v-model="state.ruleForm.dicName" placeholder="请输入字典名称" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="字段名">
<el-input v-model="state.ruleForm.fieldName" placeholder="请输入字段名,拼接 ruleForm.list" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="字典状态">
<el-switch v-model="state.ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-row :gutter="35" v-for="(v, k) in state.ruleForm.list" :key="k">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item :prop="`list[${k}].label`">
<template #label>
<el-button type="primary" circle size="small" @click="onAddRow" v-if="k === 0">
<el-icon>
<ele-Plus />
</el-icon>
</el-button>
<el-button type="danger" circle size="small" @click="onDelRow(k)" v-else>
<el-icon>
<ele-Delete />
</el-icon>
</el-button>
<span class="ml10">字段</span>
</template>
<el-input v-model="v.label" style="width: 100%" placeholder="请输入字段名"> </el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="属性" :prop="`list[${k}].value`">
<el-input v-model="v.value" style="width: 100%" placeholder="请输入属性值"> </el-input>
</el-form-item>
</el-col>
</el-row>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="字典描述">
<el-input v-model="state.ruleForm.describe" type="textarea" placeholder="请输入字典描述" maxlength="150"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="systemAddDic">
//
const state = reactive({
isShowDialog: false,
ruleForm: {
dicName: '', //
fieldName: '', //
status: true, //
list: [], // +
describe: '', //
},
});
//
const openDialog = () => {
state.isShowDialog = true;
};
//
const closeDialog = () => {
state.isShowDialog = false;
};
//
const onCancel = () => {
closeDialog();
};
//
const onSubmit = () => {
closeDialog();
};
//
const onAddRow = () => {
state.ruleForm.list.push({
id: Math.random(),
label: '',
value: '',
});
};
//
const onDelRow = (k) => {
state.ruleForm.list.splice(k, 1);
};
//
defineExpose({
openDialog,
});
</script>

View File

@ -1,8 +1,8 @@
<template>
<div class="system-edit-dic-container">
<el-dialog title="修改字典" v-model="state.isShowDialog" width="769px">
<div class="system-dic-dialog-container">
<el-dialog :title="state.dialog.title" v-model="state.dialog.isShowDialog" width="769px">
<el-alert title="半成品,交互过于复杂,请自行扩展!" type="warning" :closable="false" class="mb20"> </el-alert>
<el-form :model="state.ruleForm" size="default" label-width="90px">
<el-form ref="dicDialogFormRef" :model="state.ruleForm" size="default" label-width="90px">
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="字典名称">
@ -56,17 +56,20 @@
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="systemEditDic">
<script setup name="systemDicDialog">
// /
const emit = defineEmits(['refresh']);
//
const dicDialogFormRef = ref();
const state = reactive({
isShowDialog: false,
ruleForm: {
dicName: '', //
fieldName: '', //
@ -74,37 +77,56 @@ const state = reactive({
list: [], // +
describe: '', //
},
dialog: {
isShowDialog: false,
type: '',
title: '',
submitTxt: '',
},
});
//
const openDialog = (row) => {
if (row.fieldName === 'SYS_UERINFO') {
row.list = [
{ id: Math.random(), label: 'sex', value: '1' },
{ id: Math.random(), label: 'sex', value: '0' },
];
const openDialog = (type, row) => {
if (type === 'edit') {
if (row.fieldName === 'SYS_UERINFO') {
row.list = [
{ id: Math.random(), label: 'sex', value: '1' },
{ id: Math.random(), label: 'sex', value: '0' },
];
} else {
row.list = [
{ id: Math.random(), label: 'role', value: 'admin' },
{ id: Math.random(), label: 'role', value: 'common' },
{ id: Math.random(), label: 'roleName', value: '超级管理员' },
{ id: Math.random(), label: 'roleName', value: '普通用户' },
];
}
state.ruleForm = row;
state.dialog.title = '修改字典';
state.dialog.submitTxt = '修 改';
} else {
row.list = [
{ id: Math.random(), label: 'role', value: 'admin' },
{ id: Math.random(), label: 'role', value: 'common' },
{ id: Math.random(), label: 'roleName', value: '超级管理员' },
{ id: Math.random(), label: 'roleName', value: '普通用户' },
];
state.dialog.title = '新增字典';
state.dialog.submitTxt = '新 增';
// 使
// nextTick(() => {
// dicDialogFormRef.value.resetFields();
// });
}
state.ruleForm = row;
state.isShowDialog = true;
state.dialog.isShowDialog = true;
};
//
const closeDialog = () => {
state.isShowDialog = false;
state.dialog.isShowDialog = false;
};
//
const onCancel = () => {
closeDialog();
};
//
//
const onSubmit = () => {
closeDialog();
emit('refresh');
// if (state.dialog.type === 'add') { }
};
//
const onAddRow = () => {

View File

@ -9,14 +9,14 @@
</el-icon>
查询
</el-button>
<el-button size="default" type="success" class="ml10" @click="onOpenAddDic">
<el-button size="default" type="success" class="ml10" @click="onOpenAddDic('add')">
<el-icon>
<ele-FolderAdd />
</el-icon>
新增字典
</el-button>
</div>
<el-table :data="state.tableData.data" style="width: 100%">
<el-table :data="state.tableData.data" v-loading="state.tableData.loading" style="width: 100%">
<el-table-column type="index" label="序号" width="50" />
<el-table-column prop="dicName" label="字典名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="fieldName" label="字段名" show-overflow-tooltip></el-table-column>
@ -30,7 +30,7 @@
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" width="100">
<template #default="scope">
<el-button size="small" text type="primary" @click="onOpenEditDic(scope.row)">修改</el-button>
<el-button size="small" text type="primary" @click="onOpenEditDic('edit', scope.row)">修改</el-button>
<el-button size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button>
</template>
</el-table-column>
@ -49,8 +49,7 @@
>
</el-pagination>
</el-card>
<AddDic ref="addDicRef" />
<EditDic ref="editDicRef" />
<DicDialog ref="dicDialogRef" @refresh="getTableData()" />
</div>
</template>
@ -58,12 +57,10 @@
import { ElMessageBox, ElMessage } from 'element-plus';
//
const AddDic = defineAsyncComponent(() => import('/@/views/system/dic/component/addDic.vue'));
const EditDic = defineAsyncComponent(() => import('/@/views/system/dic/component/editDic.vue'));
const DicDialog = defineAsyncComponent(() => import('/@/views/system/dic/dialog.vue'));
//
const addDicRef = ref();
const editDicRef = ref();
const dicDialogRef = ref();
const state = reactive({
tableData: {
data: [],
@ -77,7 +74,8 @@ const state = reactive({
});
//
const initTableData = () => {
const getTableData = () => {
state.tableData.loading = true;
const data = [];
for (let i = 0; i < 2; i++) {
data.push({
@ -91,14 +89,17 @@ const initTableData = () => {
}
state.tableData.data = data;
state.tableData.total = state.tableData.data.length;
setTimeout(() => {
state.tableData.loading = false;
}, 500);
};
//
const onOpenAddDic = () => {
addDicRef.value.openDialog();
const onOpenAddDic = (type) => {
dicDialogRef.value.openDialog(type);
};
//
const onOpenEditDic = (row) => {
editDicRef.value.openDialog(row);
const onOpenEditDic = (type, row) => {
dicDialogRef.value.openDialog(type, row);
};
//
const onRowDel = (row) => {
@ -108,6 +109,7 @@ const onRowDel = (row) => {
type: 'warning',
})
.then(() => {
getTableData();
ElMessage.success('删除成功');
})
.catch(() => {});
@ -115,13 +117,15 @@ const onRowDel = (row) => {
//
const onHandleSizeChange = (val) => {
state.tableData.param.pageSize = val;
getTableData();
};
//
const onHandleCurrentChange = (val) => {
state.tableData.param.pageNum = val;
getTableData();
};
//
onMounted(() => {
initTableData();
getTableData();
});
</script>

View File

@ -1,235 +0,0 @@
<template>
<div class="system-edit-menu-container">
<el-dialog title="修改菜单" v-model="state.isShowDialog" width="769px">
<el-form :model="state.ruleForm" size="default" label-width="80px">
<el-row :gutter="35">
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="上级菜单">
<el-cascader
:options="state.menuData"
:props="{ checkStrictly: true, value: 'path', label: 'title' }"
placeholder="请选择上级菜单"
clearable
class="w100"
v-model="state.ruleForm.menuSuperior"
>
<template #default="{ node, data }">
<span>{{ data.title }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="菜单类型">
<el-radio-group v-model="state.ruleForm.menuType">
<el-radio label="menu">菜单</el-radio>
<el-radio label="btn">按钮</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="菜单名称">
<el-input v-model="state.ruleForm.meta.title" placeholder="格式message.router.xxx" clearable></el-input>
</el-form-item>
</el-col>
<template v-if="state.ruleForm.menuType === 'menu'">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="路由名称">
<el-input v-model="state.ruleForm.name" placeholder="路由中的 name 值" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="路由路径">
<el-input v-model="state.ruleForm.path" placeholder="路由中的 path 值" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="重定向">
<el-input v-model="state.ruleForm.redirect" placeholder="请输入路由重定向" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="菜单图标">
<IconSelector placeholder="请输入菜单图标" v-model="state.ruleForm.meta.icon" type="all" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="组件路径">
<el-input v-model="state.ruleForm.component" placeholder="组件路径" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="链接地址">
<el-input
v-model="state.ruleForm.meta.isLink"
placeholder="外链/内嵌时链接地址http:xxx.com"
clearable
:disabled="!state.ruleForm.isLink"
>
</el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="权限标识">
<el-select v-model="state.ruleForm.meta.roles" multiple placeholder="取角色管理" clearable class="w100">
<el-option label="admin" value="admin"></el-option>
<el-option label="common" value="common"></el-option>
</el-select>
</el-form-item>
</el-col>
</template>
<template v-if="state.ruleForm.menuType === 'btn'">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="权限标识">
<el-input v-model="state.ruleForm.btnPower" placeholder="请输入权限标识" clearable></el-input>
</el-form-item>
</el-col>
</template>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="菜单排序">
<el-input-number v-model="state.ruleForm.menuSort" controls-position="right" placeholder="请输入排序" class="w100" />
</el-form-item>
</el-col>
<template v-if="state.ruleForm.menuType === 'menu'">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="是否隐藏">
<el-radio-group v-model="state.ruleForm.meta.isHide">
<el-radio :label="true">隐藏</el-radio>
<el-radio :label="false">不隐藏</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="页面缓存">
<el-radio-group v-model="state.ruleForm.meta.isKeepAlive">
<el-radio :label="true">缓存</el-radio>
<el-radio :label="false">不缓存</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="是否固定">
<el-radio-group v-model="state.ruleForm.meta.isAffix">
<el-radio :label="true">固定</el-radio>
<el-radio :label="false">不固定</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="是否外链">
<el-radio-group v-model="state.ruleForm.isLink" :disabled="state.ruleForm.meta.isIframe">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="是否内嵌">
<el-radio-group v-model="state.ruleForm.meta.isIframe" @change="onSelectIframeChange">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</template>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="systemEditMenu">
import { storeToRefs } from 'pinia';
import { useRoutesList } from '/@/stores/routesList';
// import { setBackEndControlRefreshRoutes } from "/@/router/backEnd";
//
const IconSelector = defineAsyncComponent(() => import('/@/components/iconSelector/index.vue'));
//
const stores = useRoutesList();
const { routesList } = storeToRefs(stores);
const state = reactive({
isShowDialog: false,
// `/src/router/route.ts` `dynamicRoutes`
ruleForm: {
menuSuperior: [], //
menuType: 'menu', //
name: '', //
component: '', //
isLink: false, //
menuSort: 0, //
path: '', //
redirect: '', // children
meta: {
title: '', //
icon: '', //
isHide: false, //
isKeepAlive: true, //
isAffix: false, //
isLink: '', // /http:xxx.com`1isLink: `
isIframe: false, // `1isIframe:true 2isLink`
roles: '', //
},
btnPower: '', //
},
menuData: [], //
});
// pinia
const getMenuData = (routes) => {
const arr = [];
routes.map((val) => {
val['title'] = val.meta?.title;
arr.push({ ...val });
if (val.children) getMenuData(val.children);
});
return arr;
};
//
const openDialog = (row) => {
//
row.menuType = 'menu';
row.menuSort = Math.random();
row.component = `${row.component} `
.match(/\'(.+)\'/g)
?.join('')
.replace(/\'/g, '');
state.ruleForm = row;
state.isShowDialog = true;
};
//
const closeDialog = () => {
state.isShowDialog = false;
};
//
const onSelectIframeChange = () => {
if (state.ruleForm.meta.isIframe) state.ruleForm.isLink = true;
else state.ruleForm.isLink = false;
};
//
const onCancel = () => {
closeDialog();
};
//
const onSubmit = () => {
closeDialog(); //
// setBackEndControlRefreshRoutes() //
};
//
onMounted(() => {
state.menuData = getMenuData(routesList.value);
});
//
defineExpose({
openDialog,
});
</script>

View File

@ -1,7 +1,7 @@
<template>
<div class="system-add-menu-container">
<el-dialog title="新增菜单" v-model="state.isShowDialog" width="769px">
<el-form :model="state.ruleForm" size="default" label-width="80px">
<div class="system-menu-dialog-container">
<el-dialog :title="state.dialog.title" v-model="state.dialog.isShowDialog" width="769px">
<el-form ref="menuDialogFormRef" :model="state.ruleForm" size="default" label-width="80px">
<el-row :gutter="35">
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="上级菜单">
@ -51,7 +51,7 @@
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="菜单图标">
<IconSelector placeholder="请输入菜单图标" v-model="state.ruleForm.meta.icon" type="all" />
<IconSelector placeholder="请输入菜单图标" v-model="state.ruleForm.meta.icon" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
@ -138,26 +138,29 @@
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="systemAddMenu">
<script setup name="systemMenuDialog">
import { storeToRefs } from 'pinia';
import { useRoutesList } from '/@/stores/routesList';
// import { setBackEndControlRefreshRoutes } from "/@/router/backEnd";
// /
const emit = defineEmits(['refresh']);
//
const IconSelector = defineAsyncComponent(() => import('/@/components/iconSelector/index.vue'));
//
const menuDialogFormRef = ref();
const stores = useRoutesList();
const { routesList } = storeToRefs(stores);
const state = reactive({
isShowDialog: false,
// `/src/router/route.ts` `dynamicRoutes`
ruleForm: {
menuSuperior: [], //
@ -181,6 +184,12 @@ const state = reactive({
btnPower: '', //
},
menuData: [], //
dialog: {
isShowDialog: false,
type: '',
title: '',
submitTxt: '',
},
});
// pinia
@ -194,12 +203,32 @@ const getMenuData = (routes) => {
return arr;
};
//
const openDialog = () => {
state.isShowDialog = true;
const openDialog = (type, row) => {
if (type === 'edit') {
//
row.menuType = 'menu';
row.menuSort = Math.random();
row.component = `${row.component} `
.match(/\'(.+)\'/g)
?.join('')
.replace(/\'/g, '');
state.ruleForm = row;
state.dialog.title = '修改菜单';
state.dialog.submitTxt = '修 改';
} else {
state.dialog.title = '新增菜单';
state.dialog.submitTxt = '新 增';
// 使
// nextTick(() => {
// menuDialogFormRef.value.resetFields();
// });
}
state.dialog.type = type;
state.dialog.isShowDialog = true;
};
//
const closeDialog = () => {
state.isShowDialog = false;
state.dialog.isShowDialog = false;
};
//
const onSelectIframeChange = () => {
@ -210,9 +239,11 @@ const onSelectIframeChange = () => {
const onCancel = () => {
closeDialog();
};
//
//
const onSubmit = () => {
closeDialog(); //
emit('refresh');
// if (state.dialog.type === 'add') { }
// setBackEndControlRefreshRoutes() //
};
//

View File

@ -16,7 +16,13 @@
新增菜单
</el-button>
</div>
<el-table :data="menuTableData" style="width: 100%" row-key="path" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
<el-table
:data="state.tableData.data"
v-loading="state.tableData.loading"
style="width: 100%"
row-key="path"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column label="菜单名称" show-overflow-tooltip>
<template #default="scope">
<SvgIcon :name="scope.row.meta.icon" />
@ -46,15 +52,14 @@
</el-table-column>
<el-table-column label="操作" show-overflow-tooltip width="140">
<template #default="scope">
<el-button size="small" text type="primary" @click="onOpenAddMenu">新增</el-button>
<el-button size="small" text type="primary" @click="onOpenEditMenu(scope.row)">修改</el-button>
<el-button size="small" text type="primary" @click="onOpenAddMenu('add')">新增</el-button>
<el-button size="small" text type="primary" @click="onOpenEditMenu('edit', scope.row)">修改</el-button>
<el-button size="small" text type="primary" @click="onTabelRowDel(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<AddMenu ref="addMenuRef" />
<EditMenu ref="editMenuRef" />
<MenuDialog ref="menuDialogRef" @refresh="getTableData()" />
</div>
</template>
@ -62,28 +67,37 @@
import { ElMessageBox, ElMessage } from 'element-plus';
import { storeToRefs } from 'pinia';
import { useRoutesList } from '/@/stores/routesList';
// import { setBackEndControlRefreshRoutes } from "/@/router/backEnd";
//
const AddMenu = defineAsyncComponent(() => import('/@/views/system/menu/component/addMenu.vue'));
const EditMenu = defineAsyncComponent(() => import('/@/views/system/menu/component/editMenu.vue'));
const MenuDialog = defineAsyncComponent(() => import('/@/views/system/menu/dialog.vue'));
//
const stores = useRoutesList();
const { routesList } = storeToRefs(stores);
const addMenuRef = ref();
const editMenuRef = ref();
// pinia
const menuTableData = computed(() => {
return routesList.value;
const menuDialogRef = ref();
const state = reactive({
tableData: {
data: [],
loading: true,
},
});
//
const getTableData = () => {
state.tableData.loading = true;
state.tableData.data = routesList.value;
setTimeout(() => {
state.tableData.loading = false;
}, 500);
};
//
const onOpenAddMenu = () => {
addMenuRef.value.openDialog();
const onOpenAddMenu = (type) => {
menuDialogRef.value.openDialog(type);
};
//
const onOpenEditMenu = (row) => {
editMenuRef.value.openDialog(row);
const onOpenEditMenu = (type, row) => {
menuDialogRef.value.openDialog(type, row);
};
//
const onTabelRowDel = (row) => {
@ -94,7 +108,13 @@ const onTabelRowDel = (row) => {
})
.then(() => {
ElMessage.success('删除成功');
getTableData();
//await setBackEndControlRefreshRoutes() //
})
.catch(() => {});
};
//
onMounted(() => {
getTableData();
});
</script>

View File

@ -1,219 +0,0 @@
<template>
<div class="system-edit-role-container">
<el-dialog title="修改角色" v-model="state.isShowDialog" width="769px">
<el-form :model="state.ruleForm" size="default" label-width="90px">
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="角色名称">
<el-input v-model="state.ruleForm.roleName" placeholder="请输入角色名称" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="角色标识">
<template #label>
<el-tooltip effect="dark" content="用于 `router/route.ts` meta.roles" placement="top-start">
<span>角色标识</span>
</el-tooltip>
</template>
<el-input v-model="state.ruleForm.roleSign" placeholder="请输入角色标识" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="排序">
<el-input-number v-model="state.ruleForm.sort" :min="0" :max="999" controls-position="right" placeholder="请输入排序" class="w100" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="角色状态">
<el-switch v-model="state.ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="角色描述">
<el-input v-model="state.ruleForm.describe" type="textarea" placeholder="请输入角色描述" maxlength="150"></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="菜单权限">
<el-tree
:data="state.menuData"
:props="state.menuProps"
:default-checked-keys="[112, 113]"
node-key="id"
show-checkbox
class="menu-data-tree"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="systemEditRole">
//
const state = reactive({
isShowDialog: false,
ruleForm: {
roleName: '', //
roleSign: '', //
sort: 0, //
status: true, //
describe: '', //
},
menuData: [],
menuProps: {
children: 'children',
label: 'label',
},
});
//
const openDialog = (row) => {
state.ruleForm = row;
state.isShowDialog = true;
getMenuData();
};
//
const closeDialog = () => {
state.isShowDialog = false;
};
//
const onCancel = () => {
closeDialog();
};
//
const onSubmit = () => {
closeDialog();
};
//
const getMenuData = () => {
state.menuData = [
{
id: 1,
label: '系统管理',
children: [
{
id: 11,
label: '菜单管理',
children: [
{
id: 111,
label: '菜单新增',
},
{
id: 112,
label: '菜单修改',
},
{
id: 113,
label: '菜单删除',
},
{
id: 114,
label: '菜单查询',
},
],
},
{
id: 12,
label: '角色管理',
children: [
{
id: 121,
label: '角色新增',
},
{
id: 122,
label: '角色修改',
},
{
id: 123,
label: '角色删除',
},
{
id: 124,
label: '角色查询',
},
],
},
{
id: 13,
label: '用户管理',
children: [
{
id: 131,
label: '用户新增',
},
{
id: 132,
label: '用户修改',
},
{
id: 133,
label: '用户删除',
},
{
id: 134,
label: '用户查询',
},
],
},
],
},
{
id: 2,
label: '权限管理',
children: [
{
id: 21,
label: '前端控制',
children: [
{
id: 211,
label: '页面权限',
},
{
id: 212,
label: '页面权限',
},
],
},
{
id: 22,
label: '后端控制',
children: [
{
id: 221,
label: '页面权限',
},
],
},
],
},
];
};
//
defineExpose({
openDialog,
});
</script>
<style scoped lang="scss">
.system-edit-role-container {
.menu-data-tree {
width: 100%;
border: 1px solid var(--el-border-color);
border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
padding: 5px;
}
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<div class="system-add-role-container">
<el-dialog title="新增角色" v-model="state.isShowDialog" width="769px">
<el-form :model="state.ruleForm" size="default" label-width="90px">
<div class="system-role-dialog-container">
<el-dialog :title="state.dialog.title" v-model="state.dialog.isShowDialog" width="769px">
<el-form ref="roleDialogFormRef" :model="state.ruleForm" size="default" label-width="90px">
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="角色名称">
@ -43,17 +43,20 @@
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="systemAddRole">
<script setup name="systemRoleDialog">
// /
const emit = defineEmits(['refresh']);
//
const roleDialogFormRef = ref();
const state = reactive({
isShowDialog: false,
ruleForm: {
roleName: '', //
roleSign: '', //
@ -66,24 +69,44 @@ const state = reactive({
children: 'children',
label: 'label',
},
dialog: {
isShowDialog: false,
type: '',
title: '',
submitTxt: '',
},
});
//
const openDialog = () => {
state.isShowDialog = true;
const openDialog = (type, row) => {
if (type === 'edit') {
state.ruleForm = row;
state.dialog.title = '修改角色';
state.dialog.submitTxt = '修 改';
} else {
state.dialog.title = '新增角色';
state.dialog.submitTxt = '新 增';
// 使
// nextTick(() => {
// roleDialogFormRef.value.resetFields();
// });
}
state.dialog.isShowDialog = true;
getMenuData();
};
//
const closeDialog = () => {
state.isShowDialog = false;
state.dialog.isShowDialog = false;
};
//
const onCancel = () => {
closeDialog();
};
//
//
const onSubmit = () => {
closeDialog();
emit('refresh');
// if (state.dialog.type === 'add') { }
};
//
const getMenuData = () => {
@ -200,7 +223,7 @@ defineExpose({
</script>
<style scoped lang="scss">
.system-add-role-container {
.system-role-dialog-container {
.menu-data-tree {
width: 100%;
border: 1px solid var(--el-border-color);

View File

@ -9,14 +9,14 @@
</el-icon>
查询
</el-button>
<el-button size="default" type="success" class="ml10" @click="onOpenAddRole">
<el-button size="default" type="success" class="ml10" @click="onOpenAddRole('add')">
<el-icon>
<ele-FolderAdd />
</el-icon>
新增角色
</el-button>
</div>
<el-table :data="state.tableData.data" style="width: 100%">
<el-table :data="state.tableData.data" v-loading="state.tableData.loading" style="width: 100%">
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="roleName" label="角色名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="roleSign" label="角色标识" show-overflow-tooltip></el-table-column>
@ -31,7 +31,7 @@
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" width="100">
<template #default="scope">
<el-button :disabled="scope.row.roleName === '超级管理员'" size="small" text type="primary" @click="onOpenEditRole(scope.row)"
<el-button :disabled="scope.row.roleName === '超级管理员'" size="small" text type="primary" @click="onOpenEditRole('edit', scope.row)"
>修改</el-button
>
<el-button :disabled="scope.row.roleName === '超级管理员'" size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button>
@ -52,8 +52,7 @@
>
</el-pagination>
</div>
<AddRole ref="addRoleRef" />
<EditRole ref="editRoleRef" />
<RoleDialog ref="roleDialogRef" @refresh="getTableData()" />
</div>
</template>
@ -61,12 +60,10 @@
import { ElMessageBox, ElMessage } from 'element-plus';
//
const AddRole = defineAsyncComponent(() => import('/@/views/system/role/component/addRole.vue'));
const EditRole = defineAsyncComponent(() => import('/@/views/system/role/component/editRole.vue'));
const RoleDialog = defineAsyncComponent(() => import('/@/views/system/role/dialog.vue'));
//
const addRoleRef = ref();
const editRoleRef = ref();
const roleDialogRef = ref();
const state = reactive({
tableData: {
data: [],
@ -79,9 +76,9 @@ const state = reactive({
},
},
});
//
const initTableData = () => {
const getTableData = () => {
state.tableData.loading = true;
const data = [];
for (let i = 0; i < 20; i++) {
data.push({
@ -95,14 +92,17 @@ const initTableData = () => {
}
state.tableData.data = data;
state.tableData.total = state.tableData.data.length;
setTimeout(() => {
state.tableData.loading = false;
}, 500);
};
//
const onOpenAddRole = () => {
addRoleRef.value.openDialog();
const onOpenAddRole = (type) => {
roleDialogRef.value.openDialog(type);
};
//
const onOpenEditRole = (row) => {
editRoleRef.value.openDialog(row);
const onOpenEditRole = (type, row) => {
roleDialogRef.value.openDialog(type, row);
};
//
const onRowDel = (row) => {
@ -112,6 +112,7 @@ const onRowDel = (row) => {
type: 'warning',
})
.then(() => {
getTableData();
ElMessage.success('删除成功');
})
.catch(() => {});
@ -119,14 +120,16 @@ const onRowDel = (row) => {
//
const onHandleSizeChange = (val) => {
state.tableData.param.pageSize = val;
getTableData();
};
//
const onHandleCurrentChange = (val) => {
state.tableData.param.pageNum = val;
getTableData();
};
//
onMounted(() => {
initTableData();
getTableData();
});
</script>

View File

@ -1,166 +0,0 @@
<template>
<div class="system-edit-user-container">
<el-dialog title="修改用户" v-model="state.isShowDialog" width="769px">
<el-form :model="state.ruleForm" size="default" label-width="90px">
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="账户名称">
<el-input v-model="state.ruleForm.userName" placeholder="请输入账户名称" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="用户昵称">
<el-input v-model="state.ruleForm.userNickname" placeholder="请输入用户昵称" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="关联角色">
<el-select v-model="state.ruleForm.roleSign" placeholder="请选择" clearable class="w100">
<el-option label="超级管理员" value="admin"></el-option>
<el-option label="普通用户" value="common"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="部门">
<el-cascader
:options="state.deptData"
:props="{ checkStrictly: true, value: 'deptName', label: 'deptName' }"
placeholder="请选择部门"
clearable
class="w100"
v-model="state.ruleForm.department"
>
<template #default="{ node, data }">
<span>{{ data.deptName }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="手机号">
<el-input v-model="state.ruleForm.phone" placeholder="请输入手机号" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="邮箱">
<el-input v-model="state.ruleForm.email" placeholder="请输入" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="性别">
<el-select v-model="state.ruleForm.sex" placeholder="请选择" clearable class="w100">
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="账户密码">
<el-input v-model="state.ruleForm.password" placeholder="请输入" type="password" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="账户过期">
<el-date-picker v-model="state.ruleForm.overdueTime" type="date" placeholder="请选择" class="w100"> </el-date-picker>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="用户状态">
<el-switch v-model="state.ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="用户描述">
<el-input v-model="state.ruleForm.describe" type="textarea" placeholder="请输入用户描述" maxlength="150"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="systemEditUser">
//
const state = reactive({
isShowDialog: false,
ruleForm: {
userName: '', //
userNickname: '', //
roleSign: '', //
department: [], //
phone: '', //
email: '', //
sex: '', //
password: '', //
overdueTime: '', //
status: true, //
describe: '', //
},
deptData: [], //
});
//
const openDialog = (row) => {
state.ruleForm = row;
state.isShowDialog = true;
};
//
const closeDialog = () => {
state.isShowDialog = false;
};
//
const onCancel = () => {
closeDialog();
};
//
const onSubmit = () => {
closeDialog();
};
//
const initTableData = () => {
state.deptData.push({
deptName: 'vueNextAdmin',
createTime: new Date().toLocaleString(),
status: true,
sort: Math.random(),
describe: '顶级部门',
id: Math.random(),
children: [
{
deptName: 'IT外包服务',
createTime: new Date().toLocaleString(),
status: true,
sort: Math.random(),
describe: '总部',
id: Math.random(),
},
{
deptName: '资本控股',
createTime: new Date().toLocaleString(),
status: true,
sort: Math.random(),
describe: '分部',
id: Math.random(),
},
],
});
};
//
onMounted(() => {
initTableData();
});
//
defineExpose({
openDialog,
});
</script>

View File

@ -1,7 +1,7 @@
<template>
<div class="system-add-user-container">
<el-dialog title="新增用户" v-model="state.isShowDialog" width="769px">
<el-form :model="state.ruleForm" size="default" label-width="90px">
<div class="system-user-dialog-container">
<el-dialog :title="state.dialog.title" v-model="state.dialog.isShowDialog" width="769px">
<el-form ref="userDialogFormRef" :model="state.ruleForm" size="default" label-width="90px">
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="账户名称">
@ -81,17 +81,20 @@
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="systemAddUser">
<script setup name="systemUserDialog">
// /
const emit = defineEmits(['refresh']);
//
const userDialogFormRef = ref();
const state = reactive({
isShowDialog: false,
ruleForm: {
userName: '', //
userNickname: '', //
@ -106,26 +109,47 @@ const state = reactive({
describe: '', //
},
deptData: [], //
dialog: {
isShowDialog: false,
type: '',
title: '',
submitTxt: '',
},
});
//
const openDialog = () => {
state.isShowDialog = true;
const openDialog = (type, row) => {
if (type === 'edit') {
state.ruleForm = row;
state.dialog.title = '修改用户';
state.dialog.submitTxt = '修 改';
} else {
state.dialog.title = '新增用户';
state.dialog.submitTxt = '新 增';
// 使
// nextTick(() => {
// userDialogFormRef.value.resetFields();
// });
}
state.dialog.isShowDialog = true;
getMenuData();
};
//
const closeDialog = () => {
state.isShowDialog = false;
state.dialog.isShowDialog = false;
};
//
const onCancel = () => {
closeDialog();
};
//
//
const onSubmit = () => {
closeDialog();
emit('refresh');
// if (state.dialog.type === 'add') { }
};
//
const initTableData = () => {
const getMenuData = () => {
state.deptData.push({
deptName: 'vueNextAdmin',
createTime: new Date().toLocaleString(),
@ -153,10 +177,6 @@ const initTableData = () => {
],
});
};
//
onMounted(() => {
initTableData();
});
//
defineExpose({

View File

@ -9,14 +9,14 @@
</el-icon>
查询
</el-button>
<el-button size="default" type="success" class="ml10" @click="onOpenAddUser">
<el-button size="default" type="success" class="ml10" @click="onOpenAddUser('add')">
<el-icon>
<ele-FolderAdd />
</el-icon>
新增用户
</el-button>
</div>
<el-table :data="state.tableData.data" style="width: 100%">
<el-table :data="state.tableData.data" v-loading="state.tableData.loading" style="width: 100%">
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="userName" label="账户名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="userNickname" label="用户昵称" show-overflow-tooltip></el-table-column>
@ -34,7 +34,9 @@
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" width="100">
<template #default="scope">
<el-button :disabled="scope.row.userName === 'admin'" size="small" text type="primary" @click="onOpenEditUser(scope.row)">修改</el-button>
<el-button :disabled="scope.row.userName === 'admin'" size="small" text type="primary" @click="onOpenEditUser('edit', scope.row)"
>修改</el-button
>
<el-button :disabled="scope.row.userName === 'admin'" size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button>
</template>
</el-table-column>
@ -53,8 +55,7 @@
>
</el-pagination>
</el-card>
<AddUer ref="addUserRef" />
<EditUser ref="editUserRef" />
<UserDialog ref="userDialogRef" @refresh="getTableData()" />
</div>
</template>
@ -62,12 +63,10 @@
import { ElMessageBox, ElMessage } from 'element-plus';
//
const AddUer = defineAsyncComponent(() => import('/@/views/system/user/component/addUser.vue'));
const EditUser = defineAsyncComponent(() => import('/@/views/system/user/component/editUser.vue'));
const UserDialog = defineAsyncComponent(() => import('/@/views/system/user/dialog.vue'));
//
const addUserRef = ref();
const editUserRef = ref();
const userDialogRef = ref();
const state = reactive({
tableData: {
data: [],
@ -81,7 +80,8 @@ const state = reactive({
});
//
const initTableData = () => {
const getTableData = () => {
state.tableData.loading = true;
const data = [];
for (let i = 0; i < 2; i++) {
data.push({
@ -101,14 +101,17 @@ const initTableData = () => {
}
state.tableData.data = data;
state.tableData.total = state.tableData.data.length;
setTimeout(() => {
state.tableData.loading = false;
}, 500);
};
//
const onOpenAddUser = () => {
addUserRef.value.openDialog();
const onOpenAddUser = (type) => {
userDialogRef.value.openDialog(type);
};
//
const onOpenEditUser = (row) => {
editUserRef.value.openDialog(row);
const onOpenEditUser = (type, row) => {
userDialogRef.value.openDialog(type, row);
};
//
const onRowDel = (row) => {
@ -118,6 +121,7 @@ const onRowDel = (row) => {
type: 'warning',
})
.then(() => {
getTableData();
ElMessage.success('删除成功');
})
.catch(() => {});
@ -125,14 +129,16 @@ const onRowDel = (row) => {
//
const onHandleSizeChange = (val) => {
state.tableData.param.pageSize = val;
getTableData();
};
//
const onHandleCurrentChange = (val) => {
state.tableData.param.pageNum = val;
getTableData();
};
//
onMounted(() => {
initTableData();
getTableData();
});
</script>

View File

@ -29,6 +29,7 @@ const viteConfig = defineConfig((mode) => {
host: '0.0.0.0',
port: env.VITE_PORT,
open: env.VITE_OPEN,
hmr: true,
proxy: {
'/gitee': {
target: 'https://gitee.com',
@ -40,7 +41,6 @@ const viteConfig = defineConfig((mode) => {
},
build: {
outDir: 'dist',
sourcemap: false,
chunkSizeWarningLimit: 1500,
rollupOptions: {
output: {