This commit is contained in:
z9130 2024-10-23 20:19:23 +08:00
parent abbf400941
commit 8b86874687
9 changed files with 641 additions and 414 deletions

View File

@ -52,6 +52,8 @@
"ant-design-vue": "^4.2.3",
"dayjs": "^1.11.13",
"pinia": "2.2.2",
"pinyin": "4.0.0-alpha.2",
"pinyin-pro": "^3.25.0",
"vue": "^3.5.4",
"vue-grid-layout": "3.0.0-beta1",
"vue-grid-layout-v3": "^3.0.3",

View File

@ -2,11 +2,11 @@
import type { MenuRecordRaw } from '@vben/types';
import type { MenuProps } from '@vben-core/menu-ui';
import { usePreferences } from '@vben/preferences';
import { useAccessStore } from '@vben/stores';
import { Menu } from '@vben-core/menu-ui';
import {
GlobalSearch,
} from './../../global-search';
import { GlobalSearch } from './../../global-search';
interface Props extends MenuProps {
menus: MenuRecordRaw[];
@ -24,20 +24,17 @@ const emit = defineEmits<{
function handleMenuSelect(key: string) {
emit('select', key, props.mode);
}
import { usePreferences } from '@vben/preferences';
const {globalSearchShortcutKey } = usePreferences();
import { useAccessStore } from '@vben/stores';
const { globalSearchShortcutKey } = usePreferences();
const accessStore = useAccessStore();
console.log(accessStore.accessMenus);
</script>
<template>
<GlobalSearch
<GlobalSearch
:enable-shortcut-key="globalSearchShortcutKey"
:menus="accessStore.accessMenus"
class="mr-1 sm:mr-4 pl-3 my-3"
/>
class="my-3 mr-1 pl-3 sm:mr-4"
/>
<Menu
:accordion="accordion"
:collapse="collapse"

View File

@ -6,7 +6,7 @@ import { useRouter } from 'vue-router';
import { SearchX, X } from '@vben/icons';
import { $t } from '@vben/locales';
import { mapTree, traverseTreeValues, uniqueByField } from '@vben/utils';
import { mapTree, uniqueByField } from '@vben/utils';
import { VbenIcon, VbenScrollbar } from '@vben-core/shadcn-ui';
import { isHttpUrl } from '@vben-core/shared/utils';
@ -36,6 +36,48 @@ const searchResults = ref<MenuRecordRaw[]>([]);
const handleSearch = useThrottleFn(search, 200);
interface TreeConfigOptions {
// 'children'
childProps: string;
}
/**
* @zh_CN 遍历树形结构并返回所有节点中指定的值
* @param tree 树形结构数组
* @param getValue 获取节点值的函数
* @param options 作为子节点数组的可选属性名称
* @returns 所有节点中指定的值的数组
*/
function traverseTreeValues<T, V>(
tree: T[],
getValue: (node: T) => V,
options?: TreeConfigOptions,
): V[] {
const result: V[] = [];
const { childProps } = options || {
childProps: 'children',
};
const dfs = (treeNode: T) => {
const value = getValue(treeNode);
result.push(value);
const children = (treeNode as Record<string, any>)?.[childProps];
if (!children) {
return;
}
if (children.length > 0) {
for (const child of children) {
dfs(child);
}
}
};
for (const treeNode of tree) {
dfs(treeNode);
}
return result.filter(Boolean);
}
//
function search(searchKey: string) {
//
@ -55,8 +97,15 @@ function search(searchKey: string) {
//
traverseTreeValues(searchItems.value, (item) => {
const tempSearchKey = searchKey.trim();
//
if (reg.test(item.name?.toLowerCase())) {
console.log(item.name, item.pinyin);
console.log(tempSearchKey);
console.log(item.pinyin && item.pinyin.includes(tempSearchKey));
if (
reg.test(item.name?.toLowerCase()) ||
(item.pinyin && item.pinyin.includes(tempSearchKey))
) {
results.push(item);
}
});

View File

@ -109,7 +109,6 @@ function setupAccessGuard(router: Router) {
// 则会在菜单中显示但是访问会被重定向到403
routes: dynamicRoutes,
});
// 保存菜单信息和路由信息
accessStore.setAccessMenus(accessibleMenus);
accessStore.setAccessRoutes(accessibleRoutes);

View File

@ -1,12 +1,19 @@
import type { RouteRecordRaw } from 'vue-router';
import { pinyin } from 'pinyin-pro';
import { BasicLayout } from '#/layouts';
import { firstRouter, otherRouter } from "./linkdata"
import { firstRouter, otherRouter } from './linkdata';
// 使用 pinyin 库将汉字转为拼音,并提取每个汉字的首字母
const getFirstLetters = (str: string) => {
return pinyin(str, { pattern: 'first' }).replaceAll(/\s+/g, '');
};
const getRouter = (list: any, type: string) => {
let obj = [];
if (type == 'first') {
const obj = [];
if (type === 'first') {
for (let i = 0; i < list.children.length; i++) {
obj.push({
name: list.children[i]?.rName,
@ -15,42 +22,43 @@ const getRouter = (list: any, type: string) => {
meta: {
title: list.children[i]?.name,
link: list.children[i]?.url,
icon: 'oui:dot'
icon: 'oui:dot',
pinyin: getFirstLetters(list.children[i]?.name),
},
})
});
}
} else {
for (let i = 0; i < list.length; i++) {
let chunk:any = {}
for (const [i, element] of list.entries()) {
const chunk: any = {};
chunk.component = BasicLayout;
chunk.meta = {
icon: 'lucide:layout-dashboard',
title: list[i].name,
order: i,
};
chunk.name = list[i].rName;
chunk.path = '/'+list[i].rName;
chunk.meta = {
icon: 'lucide:layout-dashboard',
title: element.name,
order: i,
pinyin: getFirstLetters(element.name),
};
chunk.name = element.rName;
chunk.path = `/${element.rName}`;
chunk.children = [];
for (let j = 0; j < list[i].children.length; j++) {
chunk.children.push({
name: list[i].children[j]?.rName,
path: '',
component: () => null,
meta: {
title: list[i].children[j]?.name,
link: list[i].children[j]?.url,
icon: 'oui:dot'
},
})
}
obj.push(chunk)
chunk.children = [];
for (let j = 0; j < element.children.length; j++) {
chunk.children.push({
name: element.children[j]?.rName,
path: '',
component: () => null,
meta: {
title: element.children[j]?.name,
link: element.children[j]?.url,
icon: 'oui:dot',
pinyin: getFirstLetters(element.children[j]?.name),
},
});
}
obj.push(chunk);
}
}
return obj
}
return obj;
};
const routes: RouteRecordRaw[] = [
{
@ -71,8 +79,8 @@ const routes: RouteRecordRaw[] = [
meta: {
hideInMenu: true,
icon: 'lucide:area-chart',
title: '总部系统',
affixTab: true
title: '首页',
affixTab: true,
},
},
@ -98,7 +106,8 @@ const routes: RouteRecordRaw[] = [
icon: 'lucide:area-chart',
title: '磁贴审核',
},
},{
},
{
name: 'register',
path: '/register',
component: () => import('#/views/dashboard/home/register.vue'),
@ -108,8 +117,8 @@ const routes: RouteRecordRaw[] = [
icon: 'lucide:area-chart',
title: '注册磁贴',
},
}
,{
},
{
name: 'usertemplate',
path: '/usertemplate',
component: () => import('#/views/dashboard/home/usertemplate.vue'),
@ -191,7 +200,7 @@ const routes: RouteRecordRaw[] = [
// },
],
},
...getRouter(otherRouter,'other')
...getRouter(otherRouter, 'other'),
];
export default routes;

View File

@ -1,232 +1,231 @@
let firstRouter = {
"name": "总部系统",
"children": [
{
"name": "中石化新公文系统",
"url": "https://newoa12.sinopec.com?pageCode=zbxt_new_oa",
"rName": "zbxt_new_oa"
},
{
"name": "中石化移动应用平台",
"url": "https://console.m.sinopec.com/ACWeb/Portal/IndexPage?pageCode=zbxt_ydyypt",
"rName": "zbxt_ydyypt"
},
{
"name": "中石化合同系统",
"url": "https://cmis.sinopec.com/zen/portal/#/home?pageCode=zbxt_htxt",
"rName": "zbxt_htxt"
},
{
"name": "中石化党群管理系统",
"url": "https://dj.sinopec.com?pageCode=zbxt_dqgl",
"rName": "zbxt_dqgl"
},
{
"name": "中石化法律共享平台",
"url": "http://slsp.sinopec.com?pageCode=zbxt_flgl",
"rName": "zbxt_flgl"
},
{
"name": "中石化安全管理系统",
"url": "http://safety.sinopec.com:8000/IPWeb/Home?pageCode=zbxt_aqgl",
"rName": "zbxt_aqgl"
},
{
"name": "中石化法治合规管理",
"url": "https://lcrs.sinopec.com/?pageCode=zbxt_nkglxt",
"rName": "zbxt_nkglxt"
},
{
"name": "中石化制度管理系统",
"url": "http://10.249.201.77?pageCode=zbxt_zdgl",
"rName": "zbxt_zdgl"
},
{
"name": "中石化信息化标准系统",
"url": "http://infostd.sinopec.com/?pageCode=zbxt_xxhbz",
"rName": "zbxt_xxhbz"
},
{
"name": "中石化网络学院",
"url": "https://sia.sinopec.com/learn/index.html?pageCode=zbxt_wlxy",
"rName": "zbxt_wlxy"
},
{
"name": "中石化科技管理平台",
"url": "http://istm.sinopec.com/?pageCode=zbxt_kjglpt",
"rName": "zbxt_kjglpt"
},
{
"name": "中石化信创邮件系统",
"url": "https://webmail.sinopec.com/?pageCode=zbxt_xcyj",
"rName": "zbxt_xcyj"
}
]
}
const firstRouter = {
name: '总部系统',
children: [
{
name: '中石化新公文系统',
url: 'https://newoa12.sinopec.com?pageCode=zbxt_new_oa',
rName: 'zbxt_new_oa',
},
{
name: '中石化移动应用平台',
url: 'https://console.m.sinopec.com/ACWeb/Portal/IndexPage?pageCode=zbxt_ydyypt',
rName: 'zbxt_ydyypt',
},
{
name: '中石化合同系统',
url: 'https://cmis.sinopec.com/zen/portal/#/home?pageCode=zbxt_htxt',
rName: 'zbxt_htxt',
},
{
name: '中石化党群管理系统',
url: 'https://dj.sinopec.com?pageCode=zbxt_dqgl',
rName: 'zbxt_dqgl',
},
{
name: '中石化法律共享平台',
url: 'http://slsp.sinopec.com?pageCode=zbxt_flgl',
rName: 'zbxt_flgl',
},
{
name: '中石化安全管理系统',
url: 'http://safety.sinopec.com:8000/IPWeb/Home?pageCode=zbxt_aqgl',
rName: 'zbxt_aqgl',
},
{
name: '中石化法治合规管理',
url: 'https://lcrs.sinopec.com/?pageCode=zbxt_nkglxt',
rName: 'zbxt_nkglxt',
},
{
name: '中石化制度管理系统',
url: 'http://10.249.201.77?pageCode=zbxt_zdgl',
rName: 'zbxt_zdgl',
},
{
name: '中石化信息化标准系统',
url: 'http://infostd.sinopec.com/?pageCode=zbxt_xxhbz',
rName: 'zbxt_xxhbz',
},
{
name: '中石化网络学院',
url: 'https://sia.sinopec.com/learn/index.html?pageCode=zbxt_wlxy',
rName: 'zbxt_wlxy',
},
{
name: '中石化科技管理平台',
url: 'http://istm.sinopec.com/?pageCode=zbxt_kjglpt',
rName: 'zbxt_kjglpt',
},
{
name: '中石化信创邮件系统',
url: 'https://webmail.sinopec.com/?pageCode=zbxt_xcyj',
rName: 'zbxt_xcyj',
},
],
};
let otherRouter =
[
{
"name": "经营管理",
"children": [
{
"name": "市场管理信息系统",
"url": "https://xbscgl.xbyt.sinopec.com?pageCode=jygl_scglxx",
"rName": "jygl_scglxx"
},
{
"name": "工程造价管理",
"url": "http://10.16.0.157:8082/xbscjyweb?pageCode=jygl_gczjgl",
"rName": "jygl_gczjgl"
}
],
"rName": "jygl"
},
{
"name": "勘探开发",
"icon": "lucide:area-chart",
"children": [
{
"name": "油气开发平台",
"url": "http://yqkfyw.xbyt.sinopec.com/webptframe/home_navtree_hn.html?pageCode=yqkfyw_kfpt",
"rName": "yqkfyw_kfpt"
},
{
"name": "地面工程GIS",
"url": "https://ssco.xbsj.sinopec.com/DMGCFZ//HomeXBYTGISFront/Index?pageCode=yqkfyw_gis",
"rName": "yqkfyw_gis"
},
{
"name": "设备管理系统",
"url": "https://sbgl.xbyt.sinopec.com:9006/XBEM?pageCode=yqkfyw_sbxt",
"rName": "yqkfyw_sbxt"
},
{
"name": "石油工程决策系统",
"url": "https://gcjc.xbyt.sinopec.com?pageCode=yqkfyw_sygc",
"rName": "yqkfyw_sygc"
},
{
"name": "完井快报",
"url": "http://xbyt.sinopec.com/wczx/Lists/sc/SinopecAllItems.aspx?pageCode=yqkfyw_",
"rName": "yqkfyw_"
},
{
"name": "钻井数据库系统",
"url": "http://10.16.0.74/tyrz_zjsjk/?pageCode=yqkfyw_zjsjk",
"rName": "yqkfyw_zjsjk"
},
{
"name": "完井测试日报",
"url": "http://xbyt.sinopec.com/wczx/Lists/kt/SinopecAllItems.aspx?pageCode=yqkfyw_wjcs",
"rName": "yqkfyw_wjcs"
},
{
"name": "IPPE",
"url": "http://ippe.sinopec.com/?pageCode=yqkfyw_ippe",
"rName": "yqkfyw_ippe"
}
],
"rName": "yqkfyw"
},
{
"name": "安全生产",
"children": [
{
"name": "生产重点",
"url": "http://10.16.128.237:9528/yxrb/zdbb/scxxyxrb?pageCode=scyx_zdjxx",
"rName": "scyx_zdjxx"
},
{
"name": "集输防腐数据平台",
"url": "https://dmgcysbgl.xbyt.sinopec.com:8080/xbyqjs//xbjqmh_1.0.0/mh/loginSuccess.action?pageCode=scyx_jsffsj",
"rName": "scyx_jsffsj"
},
{
"name": "土地信息管理系统",
"url": "http://10.16.0.73:8888/xbtd?pageCode=scyx_tdxxgl",
"rName": "scyx_tdxxgl"
},
{
"name": "HSSE管理系统",
"url": "http://10.16.128.247:8088/?pageCode=scyx_hseglxx",
"rName": "scyx_hseglxx"
},
{
"name": "生产运行(应急)指挥中心协同平台",
"url": "http://10.16.66.120:8088/home?pageCode=scyx_yjzhxt",
"rName": "scyx_yjzhxt"
}
],
"rName": "scyx"
},
{
"name": "综合行政",
"children": [
{
"name": "领导请销假",
"url": "https://10.16.0.128/xjOA/main/login/leave.jsp?pageCode=gcgl_ldqxj",
"rName": "gcgl_ldqxj"
},
{
"name": "督办管理",
"url": "https://10.16.0.128/xjOA/main/login/urge.jsp?pageCode=gcgl_db",
"rName": "gcgl_db"
},
{
"name": "员工诉求",
"url": "https://10.16.0.128/xjOA/main/login/appeal.jsp?pageCode=gcgl_ygsq",
"rName": "gcgl_ygsq"
},
{
"name": "会议管理系统",
"url": "http://10.16.0.128:8089/HYXT/?pageCode=gcgl_hyxt",
"rName": "gcgl_hyxt"
}
],
"rName": "gcgl"
},
{
"name": "数据管理",
"children": [
{
"name": "GIS数据服务",
"url": "http://10.16.0.210:8017?pageCode=sjgl_gissjfw",
"rName": "sjgl_gissjfw"
},
{
"name": "EPBP",
"url": "http://10.16.128.130/blankSSO.action?pageCode=sjgl_EPBP_ktkfsjcj",
"rName": "sjgl_EPBP_ktkfsjcj"
},
{
"name": "单井数据服务",
"url": "https://ssco.xbsj.sinopec.com/djsjfw/goto.html?pageCode=sjgl_djsjfw",
"rName": "sjgl_djsjfw"
},
{
"name": "数据管理平台",
"url": "http://10.16.3.30:10008/?pageCode=sjgl_sjgl",
"rName": "sjgl_sjgl"
},
{
"name": "文档资料共享环境",
"url": "https://10.16.67.140/xbsjzlgx/sso?pageCode=sjgl_wdzlgx",
"rName": "sjgl_wdzlgx"
},
{
"name": "视频共享平台",
"url": "http://10.16.128.81:8020/?pageCode=sjgl_spgxpt",
"rName": "sjgl_spgxpt"
},
{
"name": "smartbi报表工具",
"url": "http://10.16.67.135:18080/smartbi/vision/index.jsp?pageCode=sjgl_smartbi",
"rName": "sjgl_smartbi"
}
],
"rName": "sjgl"
}
]
const otherRouter = [
{
name: '经营管理',
children: [
{
name: '市场管理信息系统',
url: 'https://xbscgl.xbyt.sinopec.com?pageCode=jygl_scglxx',
rName: 'jygl_scglxx',
},
{
name: '工程造价管理',
url: 'http://10.16.0.157:8082/xbscjyweb?pageCode=jygl_gczjgl',
rName: 'jygl_gczjgl',
},
],
rName: 'jygl',
},
{
name: '勘探开发',
icon: 'lucide:area-chart',
children: [
{
name: '油气开发平台',
url: 'http://yqkfyw.xbyt.sinopec.com/webptframe/home_navtree_hn.html?pageCode=yqkfyw_kfpt',
rName: 'yqkfyw_kfpt',
},
{
name: '地面工程GIS',
url: 'https://ssco.xbsj.sinopec.com/DMGCFZ//HomeXBYTGISFront/Index?pageCode=yqkfyw_gis',
rName: 'yqkfyw_gis',
},
{
name: '设备管理系统',
url: 'https://sbgl.xbyt.sinopec.com:9006/XBEM?pageCode=yqkfyw_sbxt',
rName: 'yqkfyw_sbxt',
},
{
name: '石油工程决策系统',
url: 'https://gcjc.xbyt.sinopec.com?pageCode=yqkfyw_sygc',
rName: 'yqkfyw_sygc',
},
{
name: '完井快报',
url: 'http://xbyt.sinopec.com/wczx/Lists/sc/SinopecAllItems.aspx?pageCode=yqkfyw_',
rName: 'yqkfyw_',
},
{
name: '钻井数据库系统',
url: 'http://10.16.0.74/tyrz_zjsjk/?pageCode=yqkfyw_zjsjk',
rName: 'yqkfyw_zjsjk',
},
{
name: '完井测试日报',
url: 'http://xbyt.sinopec.com/wczx/Lists/kt/SinopecAllItems.aspx?pageCode=yqkfyw_wjcs',
rName: 'yqkfyw_wjcs',
},
{
name: 'IPPE',
url: 'http://ippe.sinopec.com/?pageCode=yqkfyw_ippe',
rName: 'yqkfyw_ippe',
},
],
rName: 'yqkfyw',
},
{
name: '安全生产',
children: [
{
name: '生产重点',
url: 'http://10.16.128.237:9528/yxrb/zdbb/scxxyxrb?pageCode=scyx_zdjxx',
rName: 'scyx_zdjxx',
},
{
name: '集输防腐数据平台',
url: 'https://dmgcysbgl.xbyt.sinopec.com:8080/xbyqjs//xbjqmh_1.0.0/mh/loginSuccess.action?pageCode=scyx_jsffsj',
rName: 'scyx_jsffsj',
},
{
name: '土地信息管理系统',
url: 'http://10.16.0.73:8888/xbtd?pageCode=scyx_tdxxgl',
rName: 'scyx_tdxxgl',
},
{
name: 'HSSE管理系统',
url: 'http://10.16.128.247:8088/?pageCode=scyx_hseglxx',
rName: 'scyx_hseglxx',
},
{
name: '生产运行(应急)指挥中心协同平台',
url: 'http://10.16.66.120:8088/home?pageCode=scyx_yjzhxt',
rName: 'scyx_yjzhxt',
},
],
rName: 'scyx',
},
{
name: '综合行政',
children: [
{
name: '领导请销假',
url: 'https://10.16.0.128/xjOA/main/login/leave.jsp?pageCode=gcgl_ldqxj',
rName: 'gcgl_ldqxj',
},
{
name: '督办管理',
url: 'https://10.16.0.128/xjOA/main/login/urge.jsp?pageCode=gcgl_db',
rName: 'gcgl_db',
},
{
name: '员工诉求',
url: 'https://10.16.0.128/xjOA/main/login/appeal.jsp?pageCode=gcgl_ygsq',
rName: 'gcgl_ygsq',
},
{
name: '会议管理系统',
url: 'http://10.16.0.128:8089/HYXT/?pageCode=gcgl_hyxt',
rName: 'gcgl_hyxt',
},
],
rName: 'gcgl',
},
{
name: '数据管理',
children: [
{
name: 'GIS数据服务',
url: 'http://10.16.0.210:8017?pageCode=sjgl_gissjfw',
rName: 'sjgl_gissjfw',
},
{
name: 'EPBP',
url: 'http://10.16.128.130/blankSSO.action?pageCode=sjgl_EPBP_ktkfsjcj',
rName: 'sjgl_EPBP_ktkfsjcj',
},
{
name: '单井数据服务',
url: 'https://ssco.xbsj.sinopec.com/djsjfw/goto.html?pageCode=sjgl_djsjfw',
rName: 'sjgl_djsjfw',
},
{
name: '数据管理平台',
url: 'http://10.16.3.30:10008/?pageCode=sjgl_sjgl',
rName: 'sjgl_sjgl',
},
{
name: '文档资料共享环境',
url: 'https://10.16.67.140/xbsjzlgx/sso?pageCode=sjgl_wdzlgx',
rName: 'sjgl_wdzlgx',
},
{
name: '视频共享平台',
url: 'http://10.16.128.81:8020/?pageCode=sjgl_spgxpt',
rName: 'sjgl_spgxpt',
},
{
name: 'smartbi报表工具',
url: 'http://10.16.67.135:18080/smartbi/vision/index.jsp?pageCode=sjgl_smartbi',
rName: 'sjgl_smartbi',
},
],
rName: 'sjgl',
},
];
export { firstRouter, otherRouter };
export { firstRouter, otherRouter };

View File

@ -1,15 +1,37 @@
<script setup>
import { defineAsyncComponent, getCurrentInstance, markRaw, onMounted, ref, nextTick } from 'vue';
import {
defineAsyncComponent,
getCurrentInstance,
markRaw,
nextTick,
onMounted,
ref,
} from 'vue';
import { useRouter } from 'vue-router';
import { UndoOutlined, CheckOutlined, CloseCircleFilled, QuestionCircleOutlined, SyncOutlined, ShoppingCartOutlined, EditOutlined } from '@ant-design/icons-vue';
import { CheckboxGroup, Checkbox, Collapse, CollapsePanel, FloatButtonGroup, FloatButton, BackTop, Popover } from 'ant-design-vue';
import {
CheckOutlined,
CloseCircleFilled,
EditOutlined,
ShoppingCartOutlined,
UndoOutlined,
} from '@ant-design/icons-vue';
import {
Checkbox,
CheckboxGroup,
Collapse,
CollapsePanel,
FloatButton,
FloatButtonGroup,
Popover,
} from 'ant-design-vue';
import { storeToRefs } from 'pinia';
import { tilesList } from './tiles'
import { useRouter } from "vue-router";
import { UseTilesStore } from '#/store';
import { storeToRefs } from 'pinia'
const tilesStore = UseTilesStore();
import { tilesList } from './tiles';
const tilesStore = UseTilesStore();
const router = useRouter();
@ -18,18 +40,17 @@ const router = useRouter();
const { proxy, ctx: that } = getCurrentInstance();
const layout = ref([]);
onMounted(() => {
let layoutStr = JSON.parse(localStorage.getItem('layout'));
const layoutStr = JSON.parse(localStorage.getItem('layout'));
if (layoutStr && layoutStr.length > 0) {
for (let i = 0; i < layoutStr.length; i++) {
if (layoutStr[i]&&layoutStr[i].component) {
for (const element of layoutStr) {
if (element && element.component) {
// layoutStr[i].component = loadComponent(layoutStr[i].component);
}
}
layout.value = layoutStr
layout.value = layoutStr;
}
console.log('oooo',layout.value);
})
console.log('oooo', layout.value);
});
const colNum = 12;
let defaultH = 2;
let defaultW = 2;
@ -44,7 +65,7 @@ const DragPos = {
h: null,
i: null,
};
const componentsInfo = tilesList
const componentsInfo = tilesList;
let currentDragCom = null;
onMounted(() => {
document.addEventListener(
@ -111,7 +132,7 @@ const drag = (e, item) => {
try {
proxy.$refs.gridItem[layout.value.length - 1].$refs.item.style.display =
'none';
} catch { }
} catch {}
const el = proxy.$refs.gridItem ? proxy.$refs.gridItem[index] : null;
if (el) {
@ -198,12 +219,11 @@ const dragend = (e) => {
try {
proxy.$refs.gridItem[layout.value.length].$refs.item.style.display =
'block';
} catch {
}
} catch {}
}
nextTick(() => {
tilesIsMove.value = true;
})
});
};
// resize使resize
const resizedEvent = (e) => {
@ -221,73 +241,96 @@ const delItem = (item) => {
};
//
let shop = ref(false)
const shop = ref(false);
//
let editTiles = ref(false)
const editTiles = ref(false);
//
let activeKeyArr = ref(['1', '2', '3'])
const activeKeyArr = ref(['1', '2', '3']);
//
let selectTilseArr = ref([])
const selectTilseArr = ref([]);
//
let addTiles = (val) => {
let arr = JSON.parse(JSON.stringify(selectTilseArr.value))
const addTiles = (val) => {
let arr = JSON.parse(JSON.stringify(selectTilseArr.value));
if (arr.includes(val)) {
arr = arr.filter((item) => {
return item != val
})
return item != val;
});
} else {
arr.push(val)
arr.push(val);
}
selectTilseArr.value = arr
}
selectTilseArr.value = arr;
};
//
let { tilesIsMove } = storeToRefs(tilesStore)
let { tilesIsMove } = storeToRefs(tilesStore);
//
let cancelOrSure = (type) => {
const cancelOrSure = (type) => {
if (type == 'cance') {
editTiles.value = false;
tilesStore.setTilesIsMove(false)
tilesStore.setTilesIsMove(false);
layout.value = layout.value.filter((item) => {
return !item.isNew
})
return !item.isNew;
});
} else if (type == 'sure') {
editTiles.value = false;
tilesStore.setTilesIsMove(false)
tilesStore.setTilesIsMove(false);
layout.value.forEach((element, index) => {
delete element.isNew
delete element.isNew;
});
let newLayout = JSON.parse(JSON.stringify(layout.value));
const newLayout = JSON.parse(JSON.stringify(layout.value));
window.localStorage.setItem('layout', JSON.stringify(newLayout));
} else if (type == 'edit') {
editTiles.value = true;
tilesStore.setTilesIsMove(true)
tilesStore.setTilesIsMove(true);
}
}
};
//
let goPage = (item) => {
const goPage = (item) => {
if (tilesIsMove.value) return;
router.push(item?.path);
}
};
</script>
<template>
<div class="container h-[calc(100%-10px)] px-[20px]">
<!-- 自定义布局的部分 -->
<div class="grid-box select-none index-grid">
<grid-layout ref="gridLayout" v-model:layout="layout" :col-num="12" :is-draggable="tilesIsMove"
:is-mirrored="false" :auto-size="false" :responsive="false" :is-resizable="tilesIsMove" :margin="[10, 10]"
:row-height="70" :vertical-compact="true">
<grid-item v-for="(item, index ) in layout" :key="item.i" ref="gridItem" :h="item.h" :i="item.i" :w="item.w"
:x="item.x" :y="item.y" :dragAllowFrom="item && item.dom ? item.dom : null"
:isResizable="tilesIsMove && item && item.isResize ? item.isResize : false" @resized="resizedEvent">
<span class="close" @click="delItem(item)" v-if="tilesIsMove">
<CloseCircleFilled style="color: #f10215;" />
<div class="grid-box index-grid select-none">
<grid-layout
ref="gridLayout"
v-model:layout="layout"
:auto-size="false"
:col-num="12"
:is-draggable="tilesIsMove"
:is-mirrored="false"
:is-resizable="tilesIsMove"
:margin="[10, 10]"
:responsive="false"
:row-height="70"
:vertical-compact="true"
>
<grid-item
v-for="(item, index) in layout"
:key="item.i"
ref="gridItem"
:drag-allow-from="item && item.dom ? item.dom : null"
:h="item.h"
:i="item.i"
:is-resizable="
tilesIsMove && item && item.isResize ? item.isResize : false
"
:w="item.w"
:x="item.x"
:y="item.y"
@resized="resizedEvent"
>
<span v-if="tilesIsMove" class="close" @click="delItem(item)">
<CloseCircleFilled style="color: #f10215" />
</span>
<div class="py-2 px-4 box-border w-[100%] h-[100%] us-card-box bg-background" @click="goPage(item)">
<component :is="item.loadComp" :data="item" :key="item.i" />
<div
class="us-card-box bg-background box-border h-[100%] w-[100%] px-4 py-2"
@click="goPage(item)"
>
<component :is="item.loadComp" :key="item.i" :data="item" />
</div>
</grid-item>
@ -300,113 +343,207 @@ let goPage = (item) => {
</div>
<!-- 右侧悬浮部分 -->
<FloatButtonGroup shape="circle" :style="{ right: '40px' }">
<FloatButtonGroup :style="{ right: '40px' }" shape="circle">
<template v-if="!editTiles">
<FloatButton tooltip="编辑磁贴" @click="cancelOrSure('edit')">
<template #icon>
<EditOutlined style="font-size: 20px;" />
<EditOutlined style="font-size: 20px" />
</template>
</FloatButton>
</template>
<template v-else>
<FloatButton tooltip="保存修改" @click="cancelOrSure('sure')">
<template #icon>
<CheckOutlined style="font-size: 20px;" />
<CheckOutlined style="font-size: 20px" />
</template>
</FloatButton>
<FloatButton tooltip="取消修改" @click="cancelOrSure('cance')">
<template #icon>
<UndoOutlined style="font-size: 20px;" />
<UndoOutlined style="font-size: 20px" />
</template>
</FloatButton>
<Popover v-model:open="shop" title="磁贴商店127" trigger="click" placement="topRight">
<Popover
v-model:open="shop"
placement="topRight"
title="磁贴商店127"
trigger="click"
>
<template #content>
<div class="shop-box">
<CheckboxGroup style="width: 100%" v-model:value="selectTilseArr">
<Collapse v-model:activeKey="activeKeyArr" style="width: 100%">
<CheckboxGroup v-model:value="selectTilseArr" style="width: 100%">
<Collapse v-model:active-key="activeKeyArr" style="width: 100%">
<CollapsePanel key="1" header="个人工作台22">
<!-- 可拖入的组件部分 -->
<div class="components-box">
<div v-for="item in componentsInfo.slice(0, 22)" :key="item.name" class="ctrl-box bg-background"
draggable="true" @drag="drag" @dragend="dragend($event)" @dragstart="dragstart($event, item)"
@click="addTiles(item.name)" :class="{ 'active': selectTilseArr.includes(item.name) }">
<div class="ctrl-name">{{ item.name + '(' + item.size + ')' }}</div>
<img :src="'/xbyt/' + item.name2" alt="">
<Checkbox :value="item.name" class="absolute bottom-0 right-1" />
<div
v-for="item in componentsInfo.slice(0, 22)"
:key="item.name"
:class="{ active: selectTilseArr.includes(item.name) }"
class="ctrl-box bg-background"
draggable="true"
@click="addTiles(item.name)"
@drag="drag"
@dragend="dragend($event)"
@dragstart="dragstart($event, item)"
>
<div class="ctrl-name">
{{ `${item.name}(${item.size})` }}
</div>
<img :src="`/xbyt/${item.name2}`" alt="" />
<Checkbox
:value="item.name"
class="absolute bottom-0 right-1"
/>
</div>
</div>
</CollapsePanel>
<CollapsePanel key="2" header="综合行政12">
<div class="components-box">
<div v-for="item in componentsInfo.slice(22, 34)" :key="item.name" class="ctrl-box bg-background"
draggable="true" @drag="drag" @dragend="dragend" @dragstart="dragstart($event, item)"
@click="addTiles(item.name)" :class="{ 'active': selectTilseArr.includes(item.name) }">
<div class="ctrl-name">{{ item.name + '(' + item.size + ')' }}</div>
<img :src="'/xbyt/' + item.name2" alt="">
<Checkbox :value="item.name" :checked="selectTilseArr.includes(item.name)"
class="absolute bottom-0 right-1" />
<div
v-for="item in componentsInfo.slice(22, 34)"
:key="item.name"
:class="{ active: selectTilseArr.includes(item.name) }"
class="ctrl-box bg-background"
draggable="true"
@click="addTiles(item.name)"
@drag="drag"
@dragend="dragend"
@dragstart="dragstart($event, item)"
>
<div class="ctrl-name">
{{ `${item.name}(${item.size})` }}
</div>
<img :src="`/xbyt/${item.name2}`" alt="" />
<Checkbox
:checked="selectTilseArr.includes(item.name)"
:value="item.name"
class="absolute bottom-0 right-1"
/>
</div>
</div>
</CollapsePanel>
<CollapsePanel key="3" header="经营管理22">
<div class="components-box">
<div v-for="item in componentsInfo.slice(34, 56)" :key="item.name" class="ctrl-box bg-background"
draggable="true" @drag="drag" @dragend="dragend" @dragstart="dragstart($event, item)"
@click="addTiles(item.name)" :class="{ 'active': selectTilseArr.includes(item.name) }">
<div class="ctrl-name">{{ item.name + '(' + item.size + ')' }}</div>
<img :src="'/xbyt/' + item.name2" alt="">
<Checkbox :value="item.name" :checked="selectTilseArr.includes(item.name)"
class="absolute bottom-0 right-1" />
<div
v-for="item in componentsInfo.slice(34, 56)"
:key="item.name"
:class="{ active: selectTilseArr.includes(item.name) }"
class="ctrl-box bg-background"
draggable="true"
@click="addTiles(item.name)"
@drag="drag"
@dragend="dragend"
@dragstart="dragstart($event, item)"
>
<div class="ctrl-name">
{{ `${item.name}(${item.size})` }}
</div>
<img :src="`/xbyt/${item.name2}`" alt="" />
<Checkbox
:checked="selectTilseArr.includes(item.name)"
:value="item.name"
class="absolute bottom-0 right-1"
/>
</div>
</div>
</CollapsePanel>
<CollapsePanel key="4" header="安全生产19">
<div class="components-box">
<div v-for="item in componentsInfo.slice(56, 75)" :key="item.name" class="ctrl-box bg-background"
draggable="true" @drag="drag" @dragend="dragend" @dragstart="dragstart($event, item)"
@click="addTiles(item.name)" :class="{ 'active': selectTilseArr.includes(item.name) }">
<div class="ctrl-name">{{ item.name + '(' + item.size + ')' }}</div>
<img :src="'/xbyt/' + item.name2" alt="">
<Checkbox :value="item.name" :checked="selectTilseArr.includes(item.name)"
class="absolute bottom-0 right-1" />
<div
v-for="item in componentsInfo.slice(56, 75)"
:key="item.name"
:class="{ active: selectTilseArr.includes(item.name) }"
class="ctrl-box bg-background"
draggable="true"
@click="addTiles(item.name)"
@drag="drag"
@dragend="dragend"
@dragstart="dragstart($event, item)"
>
<div class="ctrl-name">
{{ `${item.name}(${item.size})` }}
</div>
<img :src="`/xbyt/${item.name2}`" alt="" />
<Checkbox
:checked="selectTilseArr.includes(item.name)"
:value="item.name"
class="absolute bottom-0 right-1"
/>
</div>
</div>
</CollapsePanel>
<CollapsePanel key="5" header="勘探开发26">
<div class="components-box">
<div v-for="item in componentsInfo.slice(75, 101)" :key="item.name" class="ctrl-box bg-background"
draggable="true" @drag="drag" @dragend="dragend" @dragstart="dragstart($event, item)"
@click="addTiles(item.name)" :class="{ 'active': selectTilseArr.includes(item.name) }">
<div class="ctrl-name">{{ item.name + '(' + item.size + ')' }}</div>
<img :src="'/xbyt/' + item.name2" alt="">
<Checkbox :value="item.name" :checked="selectTilseArr.includes(item.name)"
class="absolute bottom-0 right-1" />
<div
v-for="item in componentsInfo.slice(75, 101)"
:key="item.name"
:class="{ active: selectTilseArr.includes(item.name) }"
class="ctrl-box bg-background"
draggable="true"
@click="addTiles(item.name)"
@drag="drag"
@dragend="dragend"
@dragstart="dragstart($event, item)"
>
<div class="ctrl-name">
{{ `${item.name}(${item.size})` }}
</div>
<img :src="`/xbyt/${item.name2}`" alt="" />
<Checkbox
:checked="selectTilseArr.includes(item.name)"
:value="item.name"
class="absolute bottom-0 right-1"
/>
</div>
</div>
</CollapsePanel>
<CollapsePanel key="6" header="数据管理1">
<div class="components-box">
<div v-for="item in componentsInfo.slice(101, 102)" :key="item.name"
class="ctrl-box bg-background" draggable="true" @drag="drag" @dragend="dragend"
@dragstart="dragstart($event, item)" @click="addTiles(item.name)"
:class="{ 'active': selectTilseArr.includes(item.name) }">
<div class="ctrl-name">{{ item.name + '(' + item.size + ')' }}</div>
<img :src="'/xbyt/' + item.name2" alt="">
<Checkbox :value="item.name" :checked="selectTilseArr.includes(item.name)"
class="absolute bottom-0 right-1" />
<div
v-for="item in componentsInfo.slice(101, 102)"
:key="item.name"
:class="{ active: selectTilseArr.includes(item.name) }"
class="ctrl-box bg-background"
draggable="true"
@click="addTiles(item.name)"
@drag="drag"
@dragend="dragend"
@dragstart="dragstart($event, item)"
>
<div class="ctrl-name">
{{ `${item.name}(${item.size})` }}
</div>
<img :src="`/xbyt/${item.name2}`" alt="" />
<Checkbox
:checked="selectTilseArr.includes(item.name)"
:value="item.name"
class="absolute bottom-0 right-1"
/>
</div>
</div>
</CollapsePanel>
<CollapsePanel key="7" header="总部系统25">
<div class="components-box">
<div v-for="item in componentsInfo.slice(102, 127)" :key="item.name"
class="ctrl-box bg-background" draggable="true" @drag="drag" @dragend="dragend"
@dragstart="dragstart($event, item)" @click="addTiles(item.name)"
:class="{ 'active': selectTilseArr.includes(item.name) }">
<div class="ctrl-name">{{ item.name + '(' + item.size + ')' }}</div>
<img :src="'/xbyt/' + item.name2" alt="">
<Checkbox :value="item.name" :checked="selectTilseArr.includes(item.name)"
class="absolute bottom-0 right-1" />
<div
v-for="item in componentsInfo.slice(102, 127)"
:key="item.name"
:class="{ active: selectTilseArr.includes(item.name) }"
class="ctrl-box bg-background"
draggable="true"
@click="addTiles(item.name)"
@drag="drag"
@dragend="dragend"
@dragstart="dragstart($event, item)"
>
<div class="ctrl-name">
{{ `${item.name}(${item.size})` }}
</div>
<img :src="`/xbyt/${item.name2}`" alt="" />
<Checkbox
:checked="selectTilseArr.includes(item.name)"
:value="item.name"
class="absolute bottom-0 right-1"
/>
</div>
</div>
</CollapsePanel>
@ -416,7 +553,10 @@ let goPage = (item) => {
</template>
<FloatButton tooltip="磁贴商店">
<template #icon>
<ShoppingCartOutlined style="font-size: 20px;" :visibility-height="0" />
<ShoppingCartOutlined
:visibility-height="0"
style="font-size: 20px"
/>
</template>
</FloatButton>
</Popover>
@ -476,11 +616,10 @@ let goPage = (item) => {
margin-bottom: 8px;
}
img {
width: 100%;
// height: 100%;
object-fit: contain
object-fit: contain;
}
}
}
@ -498,7 +637,7 @@ let goPage = (item) => {
</style>
<style lang="scss" scoped>
.index-grid>:deep(.vue-grid-layout) {
.index-grid > :deep(.vue-grid-layout) {
height: 100% !important;
overflow: auto;
background: transparent;

View File

@ -34,6 +34,7 @@ async function generateMenus(
link,
order,
title = '',
pinyin,
} = meta || {};
const name = (title || routeName || '') as string;
@ -65,6 +66,7 @@ async function generateMenus(
path: resultPath as string,
show: !route?.meta?.hideInMenu,
children: resultChildren || [],
pinyin,
};
});

View File

@ -687,6 +687,12 @@ importers:
pinia:
specifier: 2.2.2
version: 2.2.2(typescript@5.6.2)(vue@3.5.4(typescript@5.6.2))
pinyin:
specifier: 4.0.0-alpha.2
version: 4.0.0-alpha.2
pinyin-pro:
specifier: ^3.25.0
version: 3.25.0
vue:
specifier: 3.5.4
version: 3.5.4(typescript@5.6.2)
@ -702,9 +708,6 @@ importers:
vue3-grid-layout-next:
specifier: ^1.0.7
version: 1.0.7(typescript@5.6.2)
vuedraggable:
specifier: ^4.1.0
version: 4.1.0(vue@3.5.4(typescript@5.6.2))
vxe-table:
specifier: ^4.7.74
version: 4.7.79
@ -5880,6 +5883,10 @@ packages:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
commander@1.1.1:
resolution: {integrity: sha512-71Rod2AhcH3JhkBikVpNd0pA+fWsmAaVoti6OR38T76chA7vE3pSerS0Jor4wDw+tOueD2zLVvFOw5H0Rcj7rA==}
engines: {node: '>= 0.6.x'}
commander@10.0.1:
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
engines: {node: '>=14'}
@ -7975,6 +7982,9 @@ packages:
jws@3.2.2:
resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==}
keypress@0.1.0:
resolution: {integrity: sha512-x0yf9PL/nx9Nw9oLL8ZVErFAk85/lslwEP7Vz7s5SI1ODXZIgit3C5qyWjw4DxOuO/3Hb4866SQh28a1V1d+WA==}
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
@ -8867,6 +8877,25 @@ packages:
typescript:
optional: true
pinyin-pro@3.25.0:
resolution: {integrity: sha512-MpwQPa9Ry+1vVHrsRgfJTvbtoMn0Gk529OZEWqN+O/iiSOqnd2dbKrDMaX87n7YvVPhy2W1/sKakK9zheYNWeg==}
pinyin@4.0.0-alpha.2:
resolution: {integrity: sha512-SED2wWr1X0QwH6rXIDgg20zS1mAk0AVMO8eM3KomUlOYzC8mNMWZnspZWhhI0M8MBIbF2xwa+5r30jTSjAqNsg==}
engines: {install-node: ^18.0.0}
hasBin: true
peerDependencies:
'@node-rs/jieba': ^1.6.0
nodejieba: 2.5.2
segmentit: ^2.0.3
peerDependenciesMeta:
'@node-rs/jieba':
optional: true
nodejieba:
optional: true
segmentit:
optional: true
pirates@4.0.6:
resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
engines: {node: '>= 6'}
@ -10967,11 +10996,6 @@ packages:
peerDependencies:
vue: 3.5.4
vuedraggable@4.1.0:
resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==}
peerDependencies:
vue: 3.5.4
vxe-pc-ui@4.1.27:
resolution: {integrity: sha512-6qWFfiMaI/YSTXgKLAjqmt6gtkB1BcRLrn1hzgAETPJAsRGWIQ+0DEaYYzriWYWmZpwu2TJ6rsDyCuH4PbBUCg==}
@ -13997,10 +14021,10 @@ snapshots:
'@interactjs/feedback@1.10.2': {}
'@interactjs/inertia@1.10.2(@interactjs/core@1.10.2(@interactjs/utils@1.10.2))(@interactjs/modifiers@1.10.2(@interactjs/core@1.10.27(@interactjs/utils@1.10.27))(@interactjs/utils@1.10.27))(@interactjs/utils@1.10.2)':
'@interactjs/inertia@1.10.2(@interactjs/core@1.10.2(@interactjs/utils@1.10.2))(@interactjs/modifiers@1.10.2(@interactjs/core@1.10.2(@interactjs/utils@1.10.2))(@interactjs/utils@1.10.2))(@interactjs/utils@1.10.2)':
dependencies:
'@interactjs/core': 1.10.2(@interactjs/utils@1.10.2)
'@interactjs/modifiers': 1.10.2(@interactjs/core@1.10.27(@interactjs/utils@1.10.27))(@interactjs/utils@1.10.27)
'@interactjs/modifiers': 1.10.2(@interactjs/core@1.10.2(@interactjs/utils@1.10.2))(@interactjs/utils@1.10.2)
'@interactjs/offset': 1.10.2(@interactjs/core@1.10.2(@interactjs/utils@1.10.2))(@interactjs/utils@1.10.2)
'@interactjs/utils': 1.10.2
optionalDependencies:
@ -14036,7 +14060,7 @@ snapshots:
'@interactjs/core': 1.10.2(@interactjs/utils@1.10.2)
'@interactjs/dev-tools': 1.10.2
'@interactjs/feedback': 1.10.2
'@interactjs/inertia': 1.10.2(@interactjs/core@1.10.2(@interactjs/utils@1.10.2))(@interactjs/modifiers@1.10.2(@interactjs/core@1.10.27(@interactjs/utils@1.10.27))(@interactjs/utils@1.10.27))(@interactjs/utils@1.10.2)
'@interactjs/inertia': 1.10.2(@interactjs/core@1.10.2(@interactjs/utils@1.10.2))(@interactjs/modifiers@1.10.2(@interactjs/core@1.10.2(@interactjs/utils@1.10.2))(@interactjs/utils@1.10.2))(@interactjs/utils@1.10.2)
'@interactjs/interact': 1.10.2
'@interactjs/modifiers': 1.10.2(@interactjs/core@1.10.2(@interactjs/utils@1.10.2))(@interactjs/utils@1.10.2)
'@interactjs/multi-target': 1.10.2
@ -16537,6 +16561,10 @@ snapshots:
dependencies:
delayed-stream: 1.0.0
commander@1.1.1:
dependencies:
keypress: 0.1.0
commander@10.0.1: {}
commander@12.1.0: {}
@ -18894,6 +18922,8 @@ snapshots:
jwa: 1.4.1
safe-buffer: 5.2.1
keypress@0.1.0: {}
keyv@4.5.4:
dependencies:
json-buffer: 3.0.1
@ -19859,6 +19889,12 @@ snapshots:
optionalDependencies:
typescript: 5.6.2
pinyin-pro@3.25.0: {}
pinyin@4.0.0-alpha.2:
dependencies:
commander: 1.1.1
pirates@4.0.6: {}
pkg-types@1.2.0:
@ -22176,11 +22212,6 @@ snapshots:
sortablejs: 1.14.0
vue: 3.5.4(typescript@5.6.2)
vuedraggable@4.1.0(vue@3.5.4(typescript@5.6.2)):
dependencies:
sortablejs: 1.14.0
vue: 3.5.4(typescript@5.6.2)
vxe-pc-ui@4.1.27:
dependencies:
'@vxe-ui/core': 4.0.11