Merge branch 'test' of http://172.19.183.27:3000/z9130/pansoft-plrl into test
Frontend CI/CD / build (web-office) (push) Failing after 5m6s Details

This commit is contained in:
z9130 2024-10-25 11:26:38 +08:00
commit 55cad175ad
12 changed files with 3761 additions and 392 deletions

View File

@ -1,15 +1,27 @@
<script lang="ts" setup>
import { computed } from 'vue';
import { useAntdDesignTokens } from '@vben/hooks';
import { useAntdDesignTokens, useWatermark } from '@vben/hooks';
import { preferences, usePreferences } from '@vben/preferences';
import { App, ConfigProvider, theme } from 'ant-design-vue';
import { VxeUI } from 'vxe-table';
import { antdLocale } from '#/locales';
defineOptions({ name: 'App' });
VxeUI.setConfig({
size: 'small',
});
useWatermark().updateWatermark({
content: '',
});
setTimeout(() => {
useWatermark().updateWatermark({
content: '西北油田办公平台',
});
}, 500);
const { isDark } = usePreferences();
const { tokens } = useAntdDesignTokens();

View File

@ -42,26 +42,26 @@ const PRESET = computed((): PresetItem[] => [
tip: '顶部栏仅用于显示全局信息或操作,不包含菜单。',
type: 'sidebar-topbar',
},
{
name: $t('preferences.vertical'),
tip: $t('preferences.verticalTip'),
type: 'sidebar-nav',
},
// {
// name: $t('preferences.vertical'),
// tip: $t('preferences.verticalTip'),
// type: 'sidebar-nav',
// },
{
name: $t('preferences.twoColumn'),
tip: $t('preferences.twoColumnTip'),
type: 'sidebar-mixed-nav',
},
// {
// name: $t('preferences.horizontal'),
// tip: $t('preferences.horizontalTip'),
// type: 'header-nav',
// },
// {
// name: $t('preferences.mixedMenu'),
// tip: $t('preferences.mixedMenuTip'),
// type: 'mixed-nav',
// },
{
name: $t('preferences.horizontal'),
tip: $t('preferences.horizontalTip'),
type: 'header-nav',
},
{
name: $t('preferences.mixedMenu'),
tip: $t('preferences.mixedMenuTip'),
type: 'mixed-nav',
},
// {
// name: $t('preferences.fullContent'),
// tip: $t('preferences.fullContentTip'),

View File

@ -1,144 +1,165 @@
<template>
<Modal title="个人偏好" :visible="visible" @cancel="close" :width="600">
<Tabs v-model:activeKey="activeKey" centered tabPosition="left">
<TabPane key="1" tab="自定义菜单">
<div class="list-box flex flex-col gap-4 my-2">
<div class="list-item-box flex justify-around items-center">
<div class="i-n w-100 shrink-0">
<FolderOutlined class="mr-2" />总部系统
</div>
<div class="i-s">显示菜单<Checkbox v-model:checked="checked"></Checkbox>
</div>
<div class="i-n">排序0</div>
</div>
<div class="list-item-box flex justify-around items-center" v-for="(item, index) in otherRouter"
:key="index">
<div class="i-n w-100 shrink-0">
<FolderOutlined class="mr-2" />{{ item.name }}
</div>
<div class="i-s">显示菜单<Checkbox v-model:checked="checked"></Checkbox>
</div>
<div class="i-n">排序{{ index + 1 }}</div>
</div>
</div>
</TabPane>
<TabPane key="2" tab="菜单区设置" force-render>
<div class="flex justify-center">
<Form style="width: 450px;">
<FormItem label="菜单栏默认打开:" class="mb-3">
<Switch v-model:checked="menuOpen" />
</FormItem>
<FormItem label="深色侧边栏:" class="mb-3">
<Switch v-model:checked="menuTheme" />
</FormItem>
<FormItem label="布局:" class="mb-3">
<layout v-model="layoutVlaue"></layout>
</FormItem>
</Form>
</div>
</TabPane>
<TabPane key="3" tab="主题设置">
<div class="flex justify-center">
<Form style="width: 450px;">
<FormItem label="默认主题:" class="mb-3">
<theme v-model="themeValue"></theme>
</FormItem>
<FormItem label="内置主题:" class="mb-3">
<builtin :isDark="true" v-model="builtinValue"></builtin>
</FormItem>
</Form>
</div>
</TabPane>
<TabPane key="4" tab="消息语音">
<div class="flex justify-center">
<Form style="width: 450px;">
<FormItem label="消息语音提醒:" class="mb-3">
<Switch v-model:checked="checked" class="ml-3" />
</FormItem>
<FormItem label="提示语言选择列表:" class="mb-3">
<Select ref="select" class="ml-3" v-model:value="value1" :options="options1"></Select>
</FormItem>
<FormItem label="提示语音选择文件地址" class="mb-3">
<div class="ml-3 flex flex-col gap-2">
<div class="flex gap-2">
<Button type="primary">试听</Button>
<Button type="primary">上传</Button>
</div>
</div>
</FormItem>
</Form>
</div>
</TabPane>
</Tabs>
<template #footer>
<Button type="link" key="back" @click="close">恢复</Button>
<Button key="back" @click="close">取消</Button>
<Button key="submit" type="primary" @click="close">确定</Button>
</template>
</Modal>
</template>
<script setup lang="ts">
import { Modal, Tabs, Form, FormItem, Select, Button, TabPane, Checkbox, Switch, Radio, RadioGroup } from 'ant-design-vue';
import { ref, watch } from 'vue';
import { preferences, updatePreferences } from '@vben/preferences';
import { FolderOutlined } from '@ant-design/icons-vue';
import {
Button,
Checkbox,
Form,
FormItem,
Modal,
Select,
Switch,
TabPane,
Tabs,
} from 'ant-design-vue';
import { otherRouter } from '#/router/routes/modules/linkdata';
import builtin from './builtin.vue';
import layout from './layout.vue';
import theme from './theme.vue';
import builtin from './builtin.vue';
import { ref, watch } from 'vue';
import { otherRouter } from "#/router/routes/modules/linkdata"
import { preferences, updatePreferences } from '@vben/preferences';
let layoutVlaue = ref(preferences.app.layout)
watch(layoutVlaue, (n, o) => {
updatePreferences({
app: {
layout: n
}
})
})
let themeValue = ref(preferences.theme.mode);
const layoutVlaue = ref(preferences.app.layout);
watch(layoutVlaue, (n, o) => {
updatePreferences({
app: {
layout: n,
},
});
});
const themeValue = ref(preferences.theme.mode);
watch(themeValue, (n, o) => {
updatePreferences({
theme: {
mode: n
}
})
})
let builtinValue = ref(preferences.theme.builtinType);
updatePreferences({
theme: {
mode: n,
},
});
});
const builtinValue = ref(preferences.theme.builtinType);
watch(builtinValue, (n, o) => {
updatePreferences({
theme: {
builtinType: n
}
})
})
let menuOpen = ref(preferences.sidebar.enable)
updatePreferences({
theme: {
builtinType: n,
},
});
});
const menuOpen = ref(preferences.sidebar.enable);
watch(menuOpen, (n, o) => {
updatePreferences({
sidebar: {
enable: n
}
})
})
let menuTheme = ref(preferences.theme.semiDarkSidebar)
updatePreferences({
sidebar: {
enable: n,
},
});
});
const menuTheme = ref(preferences.theme.semiDarkSidebar);
watch(menuTheme, (n, o) => {
updatePreferences({
theme: {
semiDarkSidebar: n
}
})
})
let value1 = ref('')
let activeKey = ref('1');
let checked = ref(true)
let options1 = []
updatePreferences({
theme: {
semiDarkSidebar: n,
},
});
});
const value1 = ref('');
const activeKey = ref('1');
const checked = ref(true);
const options1 = [];
const visible = defineModel<boolean>('visible');
const close = () => {
visible.value = false
}
</script>
visible.value = false;
};
</script>
<template>
<Modal :visible="visible" :width="600" title="个人偏好" @cancel="close">
<Tabs v-model:active-key="activeKey" centered tab-position="left">
<TabPane key="1" tab="自定义菜单">
<div class="list-box my-2 flex flex-col gap-4">
<div class="list-item-box flex items-center justify-around">
<div class="i-n w-100 shrink-0">
<FolderOutlined class="mr-2" />总部系统
</div>
<div class="i-s">
显示菜单<Checkbox v-model:checked="checked" />
</div>
<div class="i-n">排序0</div>
</div>
<div
v-for="(item, index) in otherRouter"
:key="index"
class="list-item-box flex items-center justify-around"
>
<div class="i-n w-100 shrink-0">
<FolderOutlined class="mr-2" />{{ item.name }}
</div>
<div class="i-s">
显示菜单<Checkbox v-model:checked="checked" />
</div>
<div class="i-n">排序{{ index + 1 }}</div>
</div>
</div>
</TabPane>
<TabPane key="2" force-render tab="菜单区设置">
<div class="flex justify-center">
<Form style="width: 450px">
<FormItem class="mb-3" label="菜单栏默认打开:">
<Switch v-model:checked="menuOpen" />
</FormItem>
<FormItem class="mb-3" label="深色侧边栏:">
<Switch v-model:checked="menuTheme" />
</FormItem>
<FormItem class="mb-3" label="布局:">
<layout v-model="layoutVlaue" />
</FormItem>
</Form>
</div>
</TabPane>
<TabPane key="3" tab="主题设置">
<div class="flex justify-center">
<Form style="width: 450px">
<FormItem class="mb-3" label="默认主题:">
<theme v-model="themeValue" />
</FormItem>
<FormItem class="mb-3" label="内置主题:">
<builtin v-model="builtinValue" :is-dark="true" />
</FormItem>
</Form>
</div>
</TabPane>
<TabPane key="4" tab="消息语音">
<div class="flex justify-center">
<Form style="width: 450px">
<FormItem class="mb-3" label="消息语音提醒:">
<Switch v-model:checked="checked" class="ml-3" />
</FormItem>
<FormItem class="mb-3" label="提示语言选择列表:">
<Select
ref="select"
v-model:value="value1"
:options="options1"
class="ml-3"
/>
</FormItem>
<FormItem class="mb-3" label="提示语音选择文件地址">
<div class="ml-3 flex flex-col gap-2">
<div class="flex gap-2">
<Button type="primary">试听</Button>
<Button type="primary">上传</Button>
</div>
</div>
</FormItem>
</Form>
</div>
</TabPane>
</Tabs>
<template #footer>
<Button key="back" type="link" @click="close">恢复</Button>
<Button key="back" @click="close">取消</Button>
<Button key="submit" type="primary" @click="close">确定</Button>
</template>
</Modal>
</template>

View File

@ -28,7 +28,7 @@ export const overridesPreferences = defineOverridesPreferences({
locale: 'zh-CN',
loginExpiredMode: 'page',
preferencesButtonPosition: 'auto',
watermark: false,
watermark: true,
},
logo: {
source: '/logo1.png',
@ -38,5 +38,5 @@ export const overridesPreferences = defineOverridesPreferences({
},
header: {
height: 60,
}
},
});

View File

@ -162,6 +162,17 @@ const routes: RouteRecordRaw[] = [
title: '新建应用',
},
},
{
name: 'template',
path: '/template/:id',
component: () => import('#/views/dashboard/home/template.vue'),
// component: () => import('#/views/dashboard/home/main.vue'),
meta: {
hideInMenu: true,
icon: 'lucide:area-chart',
title: '模板配置',
},
},
// {
// name: 'test',
// path: '/test',

View File

@ -43,42 +43,9 @@ const { list } = toRefs(props);
const { proxy } = getCurrentInstance();
const layout = ref(list.value);
onMounted(() => {
// layout.value = [
// {
// "x": 1,
// "y": 0,
// "w": 1,
// "h": 2,
// "i": "1728964990256",
// "component": {
// "name1": "AUTO_1612155980933.png",
// "name2": "AUTO_1612155980933_C.png",
// "size": "2x2",
// "name": "",
// "w": 1,
// "h": 2,
// "component": "../Output1/index.vue",
// "i": 0
// },
// },
// {
// "x": 4,
// "y": 0,
// "w": 1,
// "h": 2,
// "i": "1728965029729",
// "component": {
// "name1": "AUTO_1612155980933.png",
// "name2": "AUTO_1612155980933_C.png",
// "size": "2x2",
// "name": "",
// "w": 1,
// "h": 2,
// "component": "../Output1/index.vue",
// "i": 0
// },
// },
// ]
for (let i = 0; i < list.value.length; i++) {
list.value[i].loadComp = loadComponent(list.value[i].component);
}
});
const colNum = 12;
let defaultH = 2;
@ -140,7 +107,7 @@ const processLayout = (layoutSetInfo) => {
if (!item.component) {
continue;
}
const resComp = loadComponent(item.component.component);
const resComp = loadComponent(item.component);
item.loadComp = resComp;
}
};
@ -402,7 +369,7 @@ defineExpose({
@click="goPage(item)"
>
<component
:is="loadComponent(item.component)"
:is="item.loadComp"
:key="item.i"
:data="item"
type="sm"

View File

@ -1,96 +1,47 @@
<template>
<div style="width: 100%;height: 100%;" class="flex flex-col">
<div class="head-top-box flex justify-between mb-3 titlt-top">
<div class="flex items-center gap-10">
<Badge :count="9" :offset="[6, -3]">
<div class="flex items-center gap-1 cursor-pointer" :class="{'active': selectTodo == 'db'}" @click="selectTodoClick('db')">
<CalendarOutlined />待办
</div>
</Badge>
<div class="flex items-center gap-1 cursor-pointer" :class="{'active': selectTodo == 'yb'}" @click="selectTodoClick('yb')">
<CarryOutOutlined />已办
</div>
<Badge :count="9" :offset="[6, -3]">
<div class="flex items-center gap-1 cursor-pointer" :class="{'active': selectTodo == 'dy'}" @click="selectTodoClick('dy')">
<ExceptionOutlined />待阅
</div>
</Badge>
<div class="flex items-center gap-1 cursor-pointer" :class="{'active': selectTodo == 'yy'}" @click="selectTodoClick('yy')">
<FileDoneOutlined />已阅
</div>
<div class="flex items-center gap-1 cursor-pointer" :class="{'active': selectTodo == 'gz'}" @click="selectTodoClick('gz')">
<StarOutlined />关注
</div>
</div>
<div class="flex items-center gap-3">
<InputSearch placeholder="任务查询" style="width: 200px" />
<SettingOutlined class="cursor-pointer" @click="userSet = true" />
<ReloadOutlined class="cursor-pointer" />
</div>
</div>
<ul class="f-btn-box">
<li>
<Button :type="selectClass == '全部' ? 'primary' : 'default'" @click="selectedClick('全部')">全部</Button>
</li>
<li v-for="(item) in plainOptions" :key="item" @click="selectedClick(item)">
<Button :type="selectClass == item ? 'primary' : 'default'">{{ item }}</Button>
</li>
</ul>
<div class="flex-1 overflow-hidden">
<vxe-grid v-bind="gridOptions">
<template #attention_default="{ row }">
<StarOutlined class="text-lg"></StarOutlined>
</template>
<template #pager>
<div class="py-2 flex justify-end">
<Pagination size="small" :total="1000" show-size-changer show-quick-jumper />
</div>
</template>
</vxe-grid>
</div>
<Modal v-model:open="userSet" title="个人设置" :okText="'提交'" :width="800">
<div class="flex gap-2">
<div class="shrink-0">接收消息系统</div>
<div>
<Checkbox v-model:checked="state.checkAll" :indeterminate="state.indeterminate" @change="onCheckAllChange">
全选
</Checkbox>
<CheckboxGroup v-model:value="state.checkedList">
<div class="flex flex-wrap gap-2 mt-2">
<Checkbox :value="item" v-for="(item) in plainOptions" :key="item">
<div class="w-[85px] truncate">{{ item }}</div>
</Checkbox>
</div>
</CheckboxGroup>
</div>
</div>
</Modal>
</div>
</template>
<script lang="ts" setup>
import { reactive, watch, ref } from 'vue'
import { type VxeGridProps, VxeUI } from 'vxe-table'
import { CalendarOutlined, CarryOutOutlined, StarOutlined, ExceptionOutlined, FileDoneOutlined, SettingOutlined, ReloadOutlined } from '@ant-design/icons-vue';
import { InputSearch, Pagination, Badge, Modal, Checkbox, CheckboxGroup, Button } from 'ant-design-vue';
import { reactive, ref, watch } from 'vue';
import { preferences } from '@vben/preferences';
watch(() => preferences.theme.mode, (n: any) => {
VxeUI.setTheme(n)
}, {
deep: true,
immediate: true
})
import {
CalendarOutlined,
CarryOutOutlined,
ExceptionOutlined,
FileDoneOutlined,
ReloadOutlined,
SettingOutlined,
StarOutlined,
} from '@ant-design/icons-vue';
import {
Badge,
Button,
Checkbox,
CheckboxGroup,
InputSearch,
Modal,
Pagination,
} from 'ant-design-vue';
import { type VxeGridProps, VxeUI } from 'vxe-table';
watch(
() => preferences.theme.mode,
(n: any) => {
VxeUI.setTheme(n);
},
{
deep: true,
immediate: true,
},
);
interface RowVO {
id: number
title: string
taskName: string
handle: string
attention: string
systemName: string
time: string
id: number;
title: string;
taskName: string;
handle: string;
attention: string;
systemName: string;
time: string;
}
const gridOptions = reactive<VxeGridProps<RowVO>>({
@ -99,52 +50,180 @@ const gridOptions = reactive<VxeGridProps<RowVO>>({
loading: true,
height: 'auto',
columnConfig: {
resizable: true
resizable: true,
},
columns: [
{ field: 'title', title: '标题' },
{ field: 'title', title: '标题', slots: { default: 'title_default' } },
{ field: 'taskName', title: '任务名称' },
{ field: 'systemName', title: '系统名称' },
{ field: 'time', title: '接收时间', sortable: true },
{ field: 'handle', title: '操作' },
{ field: 'attention', title: '关注', slots: { default: 'attention_default' } },
{
field: 'attention',
title: '关注',
slots: { default: 'attention_default' },
},
],
data: [
{ id: 10001, time: '2023年12月24日', title: 'Test1222', taskName: 'Develop', handle: 'Man', attention: 'test abc', systemName: '12313' },
{ id: 10001, time: '2024年12月24日', title: 'Test1222', taskName: 'Develop', handle: 'Man', attention: 'test abc', systemName: '12313' },
{ id: 10002, time: '2023年12月1日', title: 'Test1222', taskName: 'Develop', handle: 'Man', attention: 'test abc', systemName: '12313' },
]
})
{
id: 10_001,
time: '2023年12月24日',
title: 'Test1222',
taskName: 'Develop',
handle: 'Man',
attention: 'test abc',
systemName: '12313',
},
{
id: 10_001,
time: '2024年12月24日',
title: 'Test1222',
taskName: 'Develop',
handle: 'Man',
attention: 'test abc',
systemName: '12313',
},
{
id: 10_002,
time: '2023年12月1日',
title: 'Test1222',
taskName: 'Develop',
handle: 'Man',
attention: 'test abc',
systemName: '12313',
},
],
});
const tablePage = reactive({
total: 0,
currentPage: 1,
pageSize: 10
})
pageSize: 10,
});
const findList = () => {
gridOptions.loading = true
gridOptions.loading = true;
setTimeout(() => {
gridOptions.loading = false
tablePage.total = 10
gridOptions.loading = false;
tablePage.total = 10;
gridOptions.data = [
{ id: 10001, time: '2023年12月24日', title: 'Test1222', taskName: 'Develop', handle: 'Man', attention: 'test abc', systemName: '12313' },
{ id: 10001, time: '2024年12月24日', title: 'Test1222', taskName: 'Develop', handle: 'Man', attention: 'test abc', systemName: '12313' },
{ id: 10002, time: '2023年12月1日', title: 'Test1222', taskName: 'Develop', handle: 'Man', attention: 'test abc', systemName: '12313' }, { id: 10001, time: '2023年12月24日', title: 'Test1222', taskName: 'Develop', handle: 'Man', attention: 'test abc', systemName: '12313' },
{ id: 10001, time: '2024年12月24日', title: 'Test1222', taskName: 'Develop', handle: 'Man', attention: 'test abc', systemName: '12313' },
{ id: 10002, time: '2023年12月1日', title: 'Test1222', taskName: 'Develop', handle: 'Man', attention: 'test abc', systemName: '12313' }, { id: 10001, time: '2023年12月24日', title: 'Test1222', taskName: 'Develop', handle: 'Man', attention: 'test abc', systemName: '12313' },
{ id: 10001, time: '2024年12月24日', title: 'Test1222', taskName: 'Develop', handle: 'Man', attention: 'test abc', systemName: '12313' },
{ id: 10002, time: '2023年12月1日', title: 'Test1222', taskName: 'Develop', handle: 'Man', attention: 'test abc', systemName: '12313' }, { id: 10001, time: '2023年12月24日', title: 'Test1222', taskName: 'Develop', handle: 'Man', attention: 'test abc', systemName: '12313' },
]
}, 300)
}
findList()
{
id: 10_001,
time: '2023年12月24日',
title: 'Test1222',
taskName: 'Develop',
handle: 'Man',
attention: 'test abc',
systemName: '12313',
},
{
id: 10_001,
time: '2024年12月24日',
title: 'Test1222',
taskName: 'Develop',
handle: 'Man',
attention: 'test abc',
systemName: '12313',
},
{
id: 10_002,
time: '2023年12月1日',
title: 'Test1222',
taskName: 'Develop',
handle: 'Man',
attention: 'test abc',
systemName: '12313',
},
{
id: 10_001,
time: '2023年12月24日',
title: 'Test1222',
taskName: 'Develop',
handle: 'Man',
attention: 'test abc',
systemName: '12313',
},
{
id: 10_001,
time: '2024年12月24日',
title: 'Test1222',
taskName: 'Develop',
handle: 'Man',
attention: 'test abc',
systemName: '12313',
},
{
id: 10_002,
time: '2023年12月1日',
title: 'Test1222',
taskName: 'Develop',
handle: 'Man',
attention: 'test abc',
systemName: '12313',
},
{
id: 10_001,
time: '2023年12月24日',
title: 'Test1222',
taskName: 'Develop',
handle: 'Man',
attention: 'test abc',
systemName: '12313',
},
{
id: 10_001,
time: '2024年12月24日',
title: 'Test1222',
taskName: 'Develop',
handle: 'Man',
attention: 'test abc',
systemName: '12313',
},
{
id: 10_002,
time: '2023年12月1日',
title: 'Test1222',
taskName: 'Develop',
handle: 'Man',
attention: 'test abc',
systemName: '12313',
},
{
id: 10_001,
time: '2023年12月24日',
title: 'Test1222',
taskName: 'Develop',
handle: 'Man',
attention: 'test abc',
systemName: '12313',
},
];
}, 300);
};
findList();
//
let userSet = ref(false);
const userSet = ref(false);
const plainOptions = ['公文系统', '合同管理', '物资管理', '督查管理', '市场管理', '电子考勤', '财务管理信息通知', '费用报销', '设备管理', '工程造价', '员工诉求', '即完即结', '科技研发', '标准化系统', '纪检监督系统', '后勤管理系统', '信用风险系统'];
const plainOptions = [
'公文系统',
'合同管理',
'物资管理',
'督查管理',
'市场管理',
'电子考勤',
'财务管理信息通知',
'费用报销',
'设备管理',
'工程造价',
'员工诉求',
'即完即结',
'科技研发',
'标准化系统',
'纪检监督系统',
'后勤管理系统',
'信用风险系统',
];
const state = reactive({
indeterminate: true,
checkAll: false,
@ -159,23 +238,133 @@ const onCheckAllChange = (e: any) => {
};
watch(
() => state.checkedList,
val => {
state.indeterminate = !!val.length && val.length < plainOptions.length;
(val) => {
state.indeterminate = val.length > 0 && val.length < plainOptions.length;
state.checkAll = val.length === plainOptions.length;
},
);
let selectClass = ref('全部')
const selectClass = ref('全部');
let selectedClick = (item: string) => {
selectClass.value = item
}
const selectedClick = (item: string) => {
selectClass.value = item;
};
let selectTodo = ref('');
let selectTodoClick = (item: string) => {
selectTodo.value = item
}
const selectTodo = ref('');
const selectTodoClick = (item: string) => {
selectTodo.value = item;
};
</script>
<template>
<div class="flex flex-col" style="width: 100%; height: 100%">
<div class="head-top-box titlt-top mb-3 flex justify-between">
<div class="flex items-center gap-10">
<Badge :count="9" :offset="[6, -3]">
<div
:class="{ active: selectTodo == 'db' }"
class="flex cursor-pointer items-center gap-1"
@click="selectTodoClick('db')"
>
<CalendarOutlined />待办
</div>
</Badge>
<div
:class="{ active: selectTodo == 'yb' }"
class="flex cursor-pointer items-center gap-1"
@click="selectTodoClick('yb')"
>
<CarryOutOutlined />已办
</div>
<Badge :count="9" :offset="[6, -3]">
<div
:class="{ active: selectTodo == 'dy' }"
class="flex cursor-pointer items-center gap-1"
@click="selectTodoClick('dy')"
>
<ExceptionOutlined />待阅
</div>
</Badge>
<div
:class="{ active: selectTodo == 'yy' }"
class="flex cursor-pointer items-center gap-1"
@click="selectTodoClick('yy')"
>
<FileDoneOutlined />已阅
</div>
<div
:class="{ active: selectTodo == 'gz' }"
class="flex cursor-pointer items-center gap-1"
@click="selectTodoClick('gz')"
>
<StarOutlined />关注
</div>
</div>
<div class="flex items-center gap-3">
<InputSearch placeholder="任务查询" style="width: 200px" />
<SettingOutlined class="cursor-pointer" @click="userSet = true" />
<ReloadOutlined class="cursor-pointer" />
</div>
</div>
<ul class="f-btn-box">
<li>
<Button
:type="selectClass == '全部' ? 'primary' : 'default'"
@click="selectedClick('全部')"
>
全部
</Button>
</li>
<li v-for="item in plainOptions" :key="item" @click="selectedClick(item)">
<Button :type="selectClass == item ? 'primary' : 'default'">
{{ item }}
</Button>
</li>
</ul>
<div class="flex-1 overflow-hidden">
<vxe-grid v-bind="gridOptions">
<template #attention_default="{ row }">
<StarOutlined class="text-lg" />
</template>
<template #title_default="{ row }">
<Button style="padding: 0" type="link">{{ row.title }}</Button>
</template>
<template #pager>
<div class="flex justify-end py-2">
<Pagination
:total="1000"
show-quick-jumper
show-size-changer
size="small"
/>
</div>
</template>
</vxe-grid>
</div>
<Modal v-model:open="userSet" :width="800" ok-text="提交" title="个人设置">
<div class="flex gap-2">
<div class="shrink-0">接收消息系统</div>
<div>
<Checkbox
v-model:checked="state.checkAll"
:indeterminate="state.indeterminate"
@change="onCheckAllChange"
>
全选
</Checkbox>
<CheckboxGroup v-model:value="state.checkedList">
<div class="mt-2 flex flex-wrap gap-2">
<Checkbox v-for="item in plainOptions" :key="item" :value="item">
<div class="w-[85px] truncate">{{ item }}</div>
</Checkbox>
</div>
</CheckboxGroup>
</div>
</div>
</Modal>
</div>
</template>
<style lang="scss">
@import 'vxe-table/lib/style.css';
@ -201,4 +390,4 @@ let selectTodoClick = (item: string) => {
.active {
color: hsl(var(--primary));
}
</style>
</style>

View File

@ -613,6 +613,7 @@ const formState = reactive({
<CloseCircleFilled style="color: #f10215" />
</span>
<div
:class="{ 'cursor-pointer': !tilesIsMove }"
class="us-card-box bg-background box-border h-[100%] w-[100%] px-4 py-2"
@click="goPage(item)"
>
@ -668,7 +669,7 @@ const formState = reactive({
</div>
</template>
<template #content>
<div class="shop-seach flex items-center">
<div class="shop-seach mb-2 flex items-center">
<Select v-model:value="shopFlotter">
<SelectOption value="1">全部应用磁贴</SelectOption>
<SelectOption value="2">Option2</SelectOption>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,970 @@
<script setup>
import {
defineAsyncComponent,
getCurrentInstance,
inject,
markRaw,
nextTick,
onBeforeUnmount,
onMounted,
reactive,
ref,
} from 'vue';
import { useRoute, useRouter } from 'vue-router';
import {
CheckOutlined,
CloseCircleFilled,
CloseOutlined,
EditOutlined,
PlusOutlined,
ShoppingCartOutlined,
UndoOutlined,
} from '@ant-design/icons-vue';
import {
Checkbox,
Collapse,
CollapsePanel,
FloatButton,
FloatButtonGroup,
Form,
FormItem,
Input,
InputSearch,
Modal,
Popover,
Select,
SelectOption,
} from 'ant-design-vue';
import { storeToRefs } from 'pinia';
import { UseTilesStore } from '#/store';
import { tilesList } from './tiles';
import { debounce, updateRowHeight } from './utils';
const tilesStore = UseTilesStore();
const router = useRouter();
const route = useRoute();
// ref map
const componentsRef = ref(new Map());
// ref
const setComponentRef = (el, id) => {
if (el) {
componentsRef.value.set(`child-${id}`, el);
}
};
// import GridGroup from './components/GridGroup/index.vue'
const { proxy, ctx: that } = getCurrentInstance();
const layout = ref([]);
const id = ref('');
onMounted(() => {
id.value = route.params.id;
const list =
JSON.parse(localStorage.getItem(`layout_${id.value}`)) ||
JSON.parse(localStorage.getItem('layout'));
const layoutStr = list;
layout.value = layoutStr;
});
const colNum = 12;
let defaultH = 2;
let defaultW = 2;
const mouseXY = {
x: null,
y: null,
};
const DragPos = {
x: null,
y: null,
w: null,
h: null,
i: null,
};
const componentsInfo = tilesList;
let currentDragCom = null;
/** 行高 */
const rowHeight = ref(0);
/** 屏幕宽度 */
const screenW = ref(0);
// updateRowHeight 200ms
const debouncedUpdateRowHeight = debounce(() => {
rowHeight.value = updateRowHeight('#container-canvas');
}, 0);
// 使 inject C ref
const gridLayoutRef = inject('gridLayoutRef');
onMounted(() => {
window.addEventListener('resize', debouncedUpdateRowHeight);
rowHeight.value = updateRowHeight('#container-canvas'); //
setTimeout(() => {
console.log(gridLayoutRef); // C ref
}, 1000);
document.addEventListener(
'dragover',
(e) => {
e.preventDefault();
mouseXY.x = e.clientX;
mouseXY.y = e.clientY;
},
false,
);
document.addEventListener('dragenter', (event) => {
//
event.preventDefault();
});
processLayout(layout.value);
});
//
onBeforeUnmount(() => {
window.removeEventListener('resize', debouncedUpdateRowHeight);
});
//
const loadComponent = (path) => {
return defineAsyncComponent(markRaw(() => import(`${path}`)));
};
//
const processLayout = (layoutSetInfo) => {
for (const item of layoutSetInfo) {
if (!item.component) {
continue;
}
const resComp = loadComponent(item.component);
item.loadComp = resComp;
}
};
const dragstart = (e, item) => {
e.dataTransfer.effectAllowed = 'move';
currentDragCom = item;
defaultH = item.h;
defaultW = item.w;
};
const drag = (e, item) => {
shop.value = false;
e.preventDefault && e.preventDefault();
const parentRect = document
.querySelector('.grid-box')
.getBoundingClientRect();
let mouseInGrid = false;
if (
mouseXY.x > parentRect.left &&
mouseXY.x < parentRect.right &&
mouseXY.y > parentRect.top &&
mouseXY.y < parentRect.bottom
) {
mouseInGrid = true;
}
if (mouseInGrid === true && !layout.value.some((item) => item.i === 'drop')) {
layout.value.push({
x: (layout.value.length * 2) % (colNum || 12),
y: layout.value.length + (colNum || 12),
w: defaultW,
h: defaultH,
i: 'drop',
});
}
const index = layout.value.findIndex((item) => item.i === 'drop');
if (index !== -1) {
try {
proxy.$refs.gridItem[layout.value.length - 1].$refs.item.style.display =
'none';
} catch {}
const el = proxy.$refs.gridItem ? proxy.$refs.gridItem[index] : null;
if (el) {
el.dragging = {
top: mouseXY.y - parentRect.top,
left: mouseXY.x - parentRect.left,
};
const new_pos =
el &&
el.calcXY(mouseXY.y - parentRect.top, mouseXY.x - parentRect.left);
if (mouseInGrid === true) {
// function dragEvent(eventName, id, x, y, h, w)
proxy.$refs.gridLayout.dragEvent(
'dragstart',
'drop',
new_pos.x || 0,
new_pos.y || 0,
defaultH,
defaultW,
);
DragPos.i = String(Date.now());
DragPos.x = layout.value[index].x;
DragPos.y = layout.value[index].y;
}
if (mouseInGrid === false) {
proxy.$refs.gridLayout.dragEvent(
'dragend',
'drop',
new_pos.x || 0,
new_pos.y || 0,
defaultH,
defaultW,
);
layout.value = layout.value.filter((obj) => obj.i !== 'drop');
}
}
}
};
const dragend = (e) => {
tilesIsMove.value = false;
const parentRect = document
.querySelector('.grid-box')
.getBoundingClientRect();
let mouseInGrid = false;
if (
mouseXY.x > parentRect.left &&
mouseXY.x < parentRect.right &&
mouseXY.y > parentRect.top &&
mouseXY.y < parentRect.bottom
) {
mouseInGrid = true;
}
if (mouseInGrid === true) {
proxy.$refs.gridLayout.dragEvent(
'dragend',
'drop',
DragPos.x,
DragPos.y,
defaultH,
defaultW,
);
const delIndex = layout.value.findIndex((item) => item.i === 'drop');
layout.value.splice(delIndex, 1);
const loadComp = loadComponent(currentDragCom.component);
layout.value.push({
...currentDragCom,
x: DragPos.x,
y: DragPos.y,
w: currentDragCom.w,
h: currentDragCom.h,
i: DragPos.i,
isNew: true,
loadComp,
});
proxy.$refs.gridLayout.dragEvent(
'dragend',
DragPos.i,
DragPos.x,
DragPos.y,
currentDragCom.h,
currentDragCom.w,
);
try {
proxy.$refs.gridItem[layout.value.length].$refs.item.style.display =
'block';
} catch {}
}
shop.value = true;
nextTick(() => {
// eslint-disable-next-line no-use-before-define
tilesIsMove.value = true;
});
};
/** targetLayout */
const targetLayout = ref({});
// resize使resize
const resizedEvent = (e) => {
if (document.createEvent) {
const ev = new Event('resize');
window.dispatchEvent(ev);
} else if (document.createEventObject) {
window.fireEvent('onresize');
}
};
const domIdxxxxx = ref(null);
/** 布局更新事件 */
const layoutUpdatedEvent = (e) => {
// dom
// console.log(domIdxxxxx.value);
// console.log(dom);
console.log('layoutUpdatedEvent', e);
};
/**
* 查找当前页面都有哪些分组
*/
function findGroup() {
const group = [];
layout.value.forEach((item) => {
if (item.childer) {
group.push(item);
}
});
console.log('当前画布存在分组:', group);
return group;
}
//
const checkIfOverTargetCanvas = (item) => {
// (2, 0) 4 6
const targetCanvas = targetLayout.value;
const isOver =
item.x >= targetCanvas.x &&
item.x < targetCanvas.x + targetCanvas.w &&
item.y >= targetCanvas.y &&
item.y < targetCanvas.y + targetCanvas.h;
return isOver;
};
const moveEvent = (e) => {
//
const group = findGroup();
// console.log(':', group);
console.log('moveEvent', e);
// id
// 1. id
const dom = layout.value.findIndex((el) => el.i === e);
// console.log(dom);
if (dom !== -1) {
targetLayout.value = layout.value[dom];
console.log(layout.value[dom]);
//
checkIfOverTargetCanvas(e);
}
};
// item
const delItem = (item) => {
const delIndex = layout.value.findIndex((el) => el.i === item.i);
layout.value.splice(delIndex, 1);
};
//
const shop = ref(false);
//
const editTiles = ref(false);
//
const activeKeyArr = ref([]);
//
const selectTilseArr = ref([]);
//
const addTiles = (val) => {
let arr = JSON.parse(JSON.stringify(selectTilseArr.value));
if (arr.includes(val)) {
arr = arr.filter((item) => {
return item != val;
});
} else {
arr.push(val);
}
selectTilseArr.value = arr;
};
//
let { tilesIsMove } = storeToRefs(tilesStore);
//
const cancelOrSure = (type) => {
if (type == 'cance') {
editTiles.value = false;
tilesStore.setTilesIsMove(false);
const layoutStr = JSON.parse(localStorage.getItem(`layout_${id.value}`));
if (layoutStr && layoutStr.length > 0) {
for (const element of layoutStr) {
if (element && element.component) {
element.loadComp = loadComponent(element.component);
}
}
layout.value = layoutStr;
}
} else if (type == 'sure') {
editTiles.value = false;
tilesStore.setTilesIsMove(false);
layout.value.forEach((element, index) => {
delete element.isNew;
});
const newLayout = JSON.parse(JSON.stringify(layout.value));
window.localStorage.setItem(
`layout_${id.value}`,
JSON.stringify(newLayout),
);
} else if (type == 'edit') {
editTiles.value = true;
tilesStore.setTilesIsMove(true);
}
};
//
const goPage = (item) => {
if (tilesIsMove.value) return;
router.push(item?.path);
};
const addTilesForm = ref(null);
//
const addGroup = () => {
tilesIsMove.value = false;
addTilesForm.value.validateFields().then((res) => {
const arr = JSON.parse(JSON.stringify(layout.value));
const maxY = arr.reduce((max, item) => {
return Math.max(max, item.y);
}, 0);
const obj = {
name: formState.name,
w: formState.w,
h: formState.h,
component: './components/Output5/index.vue',
isResize: true,
x: 0,
dom: '.titlt-top',
y: maxY + 1,
i: Number.parseInt(Math.random() * 10_000),
loadComp: loadComponent('./components/Output5/index.vue'),
childer: [
{
name1: 'AUTO_1612159241967.png',
name2: 'AUTO_1612159241967_C车辆调度.png',
size: '2x2',
name: '车辆调度',
w: 1,
h: 2,
minW: 1,
minH: 2,
i: 0,
x: 1,
y: 1,
component: '../Output1/index.vue',
},
],
};
layout.value.push(obj);
formState.name = '';
formState.w = 4;
formState.h = 4;
addTilesModal.value = false;
nextTick(() => {
tilesIsMove.value = true;
});
});
};
//
const editGroupName = (i, name) => {
layout.value.forEach((element) => {
if (element.i == i) {
element.name = name;
}
});
const newLayout = JSON.parse(JSON.stringify(layout.value));
window.localStorage.setItem('layout', JSON.stringify(newLayout));
};
//
const haveItem = (name) => {
return layout.value.some((item) => item.name == name);
};
//
const shopFlotter = ref('1');
//
const addTilesModal = ref(false);
const formState = reactive({
name: '',
w: 4,
h: 4,
});
</script>
<template>
<div id="container-canvas" class="container h-[calc(100%-10px)] px-[20px]">
<!-- 自定义布局的部分 -->
<!-- {{ screenW }} - {{ rowHeight }}
<div class="layoutJSON">
Displayed as <code>[x, y, w, h]</code>:
<div class="columns">
<div v-for="item in layout">
<b>{{ item.i }}</b
>: [{{ item.x }}, {{ item.y }}, {{ item.w }}, {{ item.h }}]
</div>
</div>
</div> -->
<div class="grid-box index-grid select-none">
<grid-layout
v-if="rowHeight != 0"
ref="gridLayout"
v-model:layout="layout"
:auto-size="true"
:col-num="12"
:is-draggable="tilesIsMove"
:is-mirrored="false"
:is-resizable="tilesIsMove"
:margin="[10, 10]"
:responsive="false"
:row-height="rowHeight"
:vertical-compact="true"
@layout-updated="layoutUpdatedEvent"
>
<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
"
:min-h="item.minH"
:min-w="item.minW"
:w="item.w"
:x="item.x"
:y="item.y"
@move="moveEvent"
@resized="resizedEvent"
>
<span v-if="tilesIsMove" class="close" @click="delItem(item)">
<CloseCircleFilled style="color: #f10215" />
</span>
<div
class="us-card-box bg-background box-border h-[100%] w-[100%] px-4 py-2"
>
<component
:is="item.loadComp"
:key="item.i"
:ref="(el) => setComponentRef(el, item.i)"
:data="item"
@edit-group-name="editGroupName"
/>
</div>
</grid-item>
<!-- <grid-item>
<div style="width: 200px;height: 200px;border: 1px solid #f00;">
</div>
</grid-item> -->
</grid-layout>
</div>
<!-- 右侧悬浮部分 -->
<FloatButtonGroup :style="{ right: '40px' }" shape="circle">
<template v-if="!editTiles">
<FloatButton tooltip="编辑磁贴" @click="cancelOrSure('edit')">
<template #icon>
<EditOutlined style="font-size: 20px" />
</template>
</FloatButton>
</template>
<template v-else>
<FloatButton tooltip="新建分组" @click="addTilesModal = true">
<template #icon>
<PlusOutlined style="font-size: 20px" />
</template>
</FloatButton>
<FloatButton tooltip="保存修改" @click="cancelOrSure('sure')">
<template #icon>
<CheckOutlined style="font-size: 20px" />
</template>
</FloatButton>
<FloatButton tooltip="取消修改" @click="cancelOrSure('cance')">
<template #icon>
<UndoOutlined style="font-size: 20px" />
</template>
</FloatButton>
<Popover v-model:open="shop" placement="topRight" trigger="click">
<template #title>
<div class="flex items-center justify-between">
<div class="text-lg">磁贴商店127</div>
<CloseOutlined class="cursor-pointer" @click="shop = false" />
</div>
</template>
<template #content>
<div class="shop-seach flex items-center">
<Select v-model:value="shopFlotter">
<SelectOption value="1">全部应用磁贴</SelectOption>
<SelectOption value="2">Option2</SelectOption>
</Select>
<InputSearch placeholder="" />
</div>
<div class="shop-box">
<!-- <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="{
'active pointer-events-none !cursor-no-drop': haveItem(
item.name,
),
}"
:draggable="haveItem(item.name)"
class="ctrl-box bg-background relative"
@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
:checked="haveItem(item.name)"
: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="{ 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="{ 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="{ 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="{ 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="{ 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="{ 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>
</Collapse>
<!-- </CheckboxGroup> -->
</div>
</template>
<FloatButton tooltip="磁贴商店">
<template #icon>
<ShoppingCartOutlined
:visibility-height="0"
style="font-size: 20px"
/>
</template>
</FloatButton>
</Popover>
</template>
</FloatButtonGroup>
<Modal
v-model:open="addTilesModal"
centered
title="新建分组"
@ok="addGroup"
>
<Form ref="addTilesForm" :model="formState">
<FormItem
:rules="[
{ required: true, message: '标题不能为空且长度不能超过50字节' },
]"
label="标题"
name="name"
>
<Input v-model:value="formState.name" placeholder="请输入" />
</FormItem>
<FormItem label="尺寸" name="w" required>
<div class="flex items-center gap-2">
<div class="flex items-center">
<Select v-model:value="formState.w">
<template v-for="item in 16" :key="item">
<SelectOption v-if="item >= 4" :value="item">
{{ item }}
</SelectOption>
</template>
</Select>
</div>
×
<div class="flex items-center">
<Select v-model:value="formState.h">
<template v-for="item in 10" :key="item">
<SelectOption v-if="item >= 4" :value="item">
{{ item }}
</SelectOption>
</template>
</Select>
</div>
</div>
</FormItem>
</Form>
</Modal>
</div>
</template>
<style scoped lang="scss">
.container {
min-width: 1000px;
position: relative;
overflow-x: auto;
max-width: unset !important;
}
.grid-box {
min-width: 1000px;
width: 100%;
height: 100%;
}
.components-box {
padding: 12px 20px;
// border: 1px solid rgb(66 66 66 / 100%);
display: flex;
flex-wrap: wrap;
gap: 10px;
align-content: flex-start;
.ctrl-box {
display: flex;
align-items: center;
width: 104px;
height: 130px;
padding: 12px;
// margin-top: 20px;
user-select: none;
flex-direction: column;
border-radius: 10px;
border: 1px solid #ecf1f3;
position: relative;
cursor: pointer;
&:hover {
border: 1px dashed hsl(var(--primary));
}
&.active {
border: 1px solid hsl(var(--primary));
}
.ctrl-name {
font-size: 12px;
color: hsl(var(--primary));
text-align: center;
margin-bottom: 8px;
}
img {
width: 100%;
// height: 100%;
object-fit: contain;
}
}
.mask {
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2;
background: rgba($color: #000000, $alpha: 0.4);
}
}
.us-card-box {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 4px;
}
.shop-box {
width: 550px;
height: 75vh;
overflow-y: auto;
}
</style>
<style lang="scss" scoped>
.index-grid > :deep(.vue-grid-layout) {
height: 100% !important;
overflow: auto;
background: transparent;
// border: 1px solid rgb(66 66 66 / 100%);
// width: 1200px;
margin: 0 auto;
.vue-grid-item {
// padding: 12px 20px;
// background: #2d2d2c;
// border: 1px solid rgb(66 66 66 / 100%);
border-radius: 2px;
}
.close {
position: absolute;
top: -10px;
right: -10px;
display: inline-block;
width: 16px;
height: 16px;
color: rgb(255 255 255 / 60%);
cursor: pointer;
i {
font-size: 20px;
}
&:hover {
color: #fff;
}
}
.vue-grid-item.vue-resizable.vue-grid-placeholder {
background: white !important;
}
}
.shop-seach :deep(button) {
display: flex;
align-items: center;
justify-content: center;
}
</style>

View File

@ -118,10 +118,40 @@ const tilesList = [
maxW: 2,
maxH: 4,
i: 0,
x: 1,
y: 1,
x: 0,
y: 0,
component: '../../components/Output1/index.vue',
},
{
name1: 'AUTO_1649411776285.png',
name2: 'AUTO_1649411776285_C智能化管线.png',
size: '2x2',
name: '智能化管线',
w: 1,
h: 2,
minW: 1,
minH: 2,
maxW: 2,
maxH: 4,
x: 2,
y: 3,
component: '../../components/Output1/index.vue',
i: 8_098_097,
},
{
name1: 'AUTO_1612236164722.png',
name2: 'AUTO_1612236164722_C门户网站.png',
size: '2x2',
name: '门户网站',
minW: 1,
minH: 2,
maxW: 2,
maxH: 4,
w: 3,
h: 3,
component: './components/Output1/index.vue',
i: 3242,
},
],
i: 1,
},

View File

@ -1,86 +1,200 @@
<template>
<div class="bg-background p-5 m-4">
<div class="flex justify-between mb-4">
<Form layout="inline">
<FormItem label="名称">
<Input placeholder="请输入"></Input>
</FormItem>
<FormItem label="编码">
<Input placeholder="请输入"></Input>
</FormItem>
<FormItem label="模板类型">
<Select placeholder="请输入"></Select>
</FormItem>
<Button type="primary">查询</Button>
</Form>
<Button type="primary">添加</Button>
</div>
<vxe-table border ref="tableRef" :data="tableData">
<vxe-column field="ucode" title="租户编码"></vxe-column>
<vxe-column field="name" title="模板名称"></vxe-column>
<vxe-column field="code" title="模板编码"></vxe-column>
<vxe-column field="versions" title="模板版本信息"></vxe-column>
<vxe-column field="type" title="模板类型"></vxe-column>
<vxe-column field="isDefault" title="是否为默认面板"></vxe-column>
<vxe-column field="users" title="创建人"></vxe-column>
<vxe-column field="time" title="创建时间"></vxe-column>
<vxe-column field="maintain" title="维护人"></vxe-column>
<vxe-column field="maintaintime" title="维护时间"></vxe-column>
<vxe-column field="operate" title="操作" width="150">
<template #default="{ row }">
<div class="flex gap-1">
<EditFilled style="color: #5cb15c;font-size: 20px;" />
<DeleteFilled style="color: #e15852;font-size: 20px;"/>
<ContactsFilled style="color: #367cb7;font-size: 20px;"/>
<ToolFilled style="color: #367cb7;font-size: 20px;"/>
<ThunderboltFilled style="color: #e15852;font-size: 20px;"/>
</div>
</template>
</vxe-column>
</vxe-table>
<div class="py-2 flex justify-between">
<div>总共{{ tableData.length }}条数据</div>
<Pagination size="small" :total="1000" show-size-changer show-quick-jumper />
</div>
</div>
</template>
<script setup lang="ts">
import { ref ,watch} from 'vue'
import { EditFilled, DeleteFilled, ContactsFilled, ToolFilled, ThunderboltFilled } from '@ant-design/icons-vue';
import { type VxeGridProps, VxeUI } from 'vxe-table'
import { VXETable, type VxeTableInstance, type VxeTableEvents } from 'vxe-table'
import { ref, watch } from 'vue';
import { useRouter } from 'vue-router';
import { Button, Form, FormItem, Input, Select, Card, Pagination, Textarea, Checkbox } from 'ant-design-vue';
import { preferences } from '@vben/preferences';
watch(() => preferences.theme.mode, (n: any) => {
VxeUI.setTheme(n)
},{
import {
ContactsFilled,
DeleteFilled,
EditFilled,
ThunderboltFilled,
ToolFilled,
} from '@ant-design/icons-vue';
import {
Button,
Form,
FormItem,
Input,
Pagination,
Select,
} from 'ant-design-vue';
import { VxeUI } from 'vxe-table';
import { saveTemplateData } from './template';
saveTemplateData();
watch(
() => preferences.theme.mode,
(n: any) => {
VxeUI.setTheme(n);
},
{
deep: true,
immediate: true
})
immediate: true,
},
);
interface RowVO {
ucode: string
name: string
code: string
versions: string
type: string
isDefault: boolean
users: string
time: string
maintain: string
maintaintime: string
//
operate: string
ucode: string;
name: string;
code: string;
versions: string;
type: string;
isDefault: boolean;
users: string;
time: string;
maintain: string;
maintaintime: string;
//
operate: string;
}
const tableData = ref<RowVO[]>([
{ ucode: 'xbyt', code: "PC_Default", name: "管理员模板", versions: "1.0.0", type: "PC", isDefault: true, users: "admin", time: "2021-01-01 00:00:00", maintain: "admin", maintaintime: "2021-01-01 00:00:00", operate: "编辑" },
{ ucode: 'xbyt', code: "PC_Default", name: "管理员模板", versions: "1.0.0", type: "PC", isDefault: true, users: "admin", time: "2021-01-01 00:00:00", maintain: "admin", maintaintime: "2021-01-01 00:00:00", operate: "编辑" },
{ ucode: 'xbyt', code: "PC_Default", name: "管理员模板", versions: "1.0.0", type: "PC", isDefault: true, users: "admin", time: "2021-01-01 00:00:00", maintain: "admin", maintaintime: "2021-01-01 00:00:00", operate: "编辑" },
{ ucode: 'xbyt', code: "PC_Default", name: "管理员模板", versions: "1.0.0", type: "PC", isDefault: true, users: "admin", time: "2021-01-01 00:00:00", maintain: "admin", maintaintime: "2021-01-01 00:00:00", operate: "编辑" },
{ ucode: 'xbyt', code: "PC_Default", name: "管理员模板", versions: "1.0.0", type: "PC", isDefault: true, users: "admin", time: "2021-01-01 00:00:00", maintain: "admin", maintaintime: "2021-01-01 00:00:00", operate: "编辑" },
])
{
ucode: 'xbyt',
code: '1001',
name: '管理员模板',
versions: '1.0.0',
type: 'PC',
isDefault: true,
users: 'admin',
time: '2021-01-01 00:00:00',
maintain: 'admin',
maintaintime: '2021-01-01 00:00:00',
operate: '编辑',
},
{
ucode: 'xbyt',
code: '1002',
name: '管理员模板',
versions: '1.0.0',
type: 'PC',
isDefault: true,
users: 'admin',
time: '2021-01-01 00:00:00',
maintain: 'admin',
maintaintime: '2021-01-01 00:00:00',
operate: '编辑',
},
{
ucode: 'xbyt',
code: '1003',
name: '管理员模板',
versions: '1.0.0',
type: 'PC',
isDefault: true,
users: 'admin',
time: '2021-01-01 00:00:00',
maintain: 'admin',
maintaintime: '2021-01-01 00:00:00',
operate: '编辑',
},
{
ucode: 'xbyt',
code: '1004',
name: '管理员模板',
versions: '1.0.0',
type: 'PC',
isDefault: true,
users: 'admin',
time: '2021-01-01 00:00:00',
maintain: 'admin',
maintaintime: '2021-01-01 00:00:00',
operate: '编辑',
},
{
ucode: 'xbyt',
code: '1005',
name: '管理员模板',
versions: '1.0.0',
type: 'PC',
isDefault: true,
users: 'admin',
time: '2021-01-01 00:00:00',
maintain: 'admin',
maintaintime: '2021-01-01 00:00:00',
operate: '编辑',
},
]);
const router = useRouter();
const goToSetTemplate = (t) => {
router.push({
name: 'template',
params: { id: t },
});
};
</script>
<style scoped lang="scss"></style>
<template>
<div class="bg-background m-4 p-5">
<div class="mb-4 flex justify-between">
<Form layout="inline">
<FormItem label="名称">
<Input placeholder="请输入" />
</FormItem>
<FormItem label="编码">
<Input placeholder="请输入" />
</FormItem>
<FormItem label="模板类型">
<Select placeholder="请输入" />
</FormItem>
<Button type="primary">查询</Button>
</Form>
<Button type="primary">添加</Button>
</div>
<vxe-table ref="tableRef" :data="tableData" border>
<vxe-column field="ucode" title="租户编码" />
<vxe-column field="name" title="模板名称" />
<vxe-column field="code" title="模板编码" />
<vxe-column field="versions" title="模板版本信息" />
<vxe-column field="type" title="模板类型" />
<vxe-column field="isDefault" title="是否为默认面板">
<template #default="{ row }">
<span v-if="row.isDefault"></span>
<span v-else></span>
</template>
</vxe-column>
<vxe-column field="users" title="创建人" />
<vxe-column field="time" title="创建时间" />
<vxe-column field="maintain" title="维护人" />
<vxe-column field="maintaintime" title="维护时间" />
<vxe-column field="operate" title="操作" width="150">
<template #default="{ row }">
<div class="flex gap-1">
<EditFilled
class="cursor-pointer"
style="color: #5cb15c; font-size: 20px"
/>
<DeleteFilled
class="cursor-pointer"
style="color: #e15852; font-size: 20px"
/>
<ContactsFilled
class="cursor-pointer"
style="color: #367cb7; font-size: 20px"
/>
<ToolFilled
class="cursor-pointer"
style="color: #367cb7; font-size: 20px"
@click="goToSetTemplate(row.code)"
/>
<ThunderboltFilled
class="cursor-pointer"
style="color: #e15852; font-size: 20px"
/>
</div>
</template>
</vxe-column>
</vxe-table>
<div class="flex justify-between py-2">
<div>总共{{ tableData.length }}条数据</div>
<Pagination
:total="1000"
show-quick-jumper
show-size-changer
size="small"
/>
</div>
</div>
</template>
<style scoped lang="scss"></style>