初始化版本,引入智慧食堂模块,第三方模块
This commit is contained in:
commit
d22f88efd3
677 files changed
+69341
No files matched your search
@@ -0,0 +1,56 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
title: '审计日志',
|
||||
icon: 'DocumentCopy',
|
||||
description: '审计日志列表',
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="box-card h-96">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>{{ $t('home.auditLogsTip') }}</span>
|
||||
<el-button link class="button" text @click="handleRoutr">{{ $t('home.moreTip') }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<el-timeline v-if="auditState.dataList.length > 0">
|
||||
<el-timeline-item v-for="(item, index) in auditState.dataList" :key="index" :timestamp="item.createTime">
|
||||
{{ item.createBy }} : {{ item.auditField }} {{ item.afterVal }} => {{ item.beforeVal }}
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
<el-empty :image-size="120" v-else />
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="SysAuditLogDashboard">
|
||||
import { BasicTableProps, useTable } from '/@/hooks/table';
|
||||
import { fetchList } from '/@/api/admin/audit';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
// 创建基本表格参数对象
|
||||
const auditState: BasicTableProps = reactive({
|
||||
queryForm: {},
|
||||
pageList: fetchList,
|
||||
descs: ['create_time'],
|
||||
pagination: {
|
||||
size: 4, // 每页显示数据量
|
||||
},
|
||||
});
|
||||
|
||||
// 使用实例
|
||||
useTable(auditState);
|
||||
|
||||
// 跳转路由
|
||||
const handleRoutr = () => {
|
||||
router.push('/admin/audit/index');
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,186 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
title: '日程管理',
|
||||
icon: 'Calendar',
|
||||
description: '日历组件展示',
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-card class="h-96 box-card">
|
||||
<Calendar
|
||||
view="weekly"
|
||||
:locale="locale"
|
||||
:attributes="reminders"
|
||||
ref="calendar"
|
||||
title-position="center"
|
||||
@did-move="weeknumberClick"
|
||||
@dayclick="dayClick"
|
||||
:masks="masks"
|
||||
v-bind="themeConfig?.isDark ? { 'is-dark': true } : {}"
|
||||
transparent
|
||||
borderless
|
||||
expanded
|
||||
/>
|
||||
<div v-if="calendar" class="py-4 px-6 w-full h-[18rem] overflow-y-auto">
|
||||
<template v-for="{ day, cells } in Object.values(dayCells)">
|
||||
<ul v-if="cells.length > 0" class="py-2 space-y-2" :key="day">
|
||||
<li v-for="cell in cells" :key="cell">
|
||||
<div class="flex items-center space-x-4">
|
||||
<!--Icon-->
|
||||
<div class="flex-grow-0 flex-shrink-0">
|
||||
<div :class="`flex justify-center items-center w-10 h-10 rounded-lg bg-blue-100 text-blue-500 dark:bg-blue-400 dark:text-white`">
|
||||
<el-icon>
|
||||
<CircleCheck />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between flex-grow">
|
||||
<div>
|
||||
<p class="font-medium">
|
||||
{{ cell.data.customData.title }}
|
||||
</p>
|
||||
<p class="text-xs font-medium text-gray-400 dark:text-gray-400 leading-2">
|
||||
{{ cell.data.customData.scheduleDate }} {{ cell.data.customData.scheduleTime }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-switch @change="changeSwitch(cell.data.customData.id)"></el-switch>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
<el-empty :image-size="120" v-if="reminders.length === 0" class="text-center" />
|
||||
</div>
|
||||
<!-- 新增日程的表单 -->
|
||||
<schedule-form ref="scheduleFormRef" @refresh="initscheduleList()" />
|
||||
<!-- 日程查询 -->
|
||||
<schedule ref="scheduleRef" @refresh="initscheduleList()" />
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="scheduleCalendar">
|
||||
import { Calendar } from 'v-calendar';
|
||||
import 'v-calendar/style.css';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import { parseDate } from '/@/utils/formatTime';
|
||||
import { list, putObj } from '/@/api/admin/schedule';
|
||||
|
||||
const ScheduleForm = defineAsyncComponent(() => import('/@/views/home/schedule/form.vue'));
|
||||
const Schedule = defineAsyncComponent(() => import('/@/views/home/schedule/index.vue'));
|
||||
|
||||
// 获取当前国际化方言
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
const locale = computed(() => {
|
||||
return themeConfig.value.globalI18n;
|
||||
});
|
||||
|
||||
const masks = ref({
|
||||
weekdays: 'WWW',
|
||||
});
|
||||
|
||||
const reminders = ref([]);
|
||||
const calendar = ref<any>(null);
|
||||
const scheduleFormRef = ref();
|
||||
const scheduleRef = ref();
|
||||
|
||||
// 添加类型定义
|
||||
interface DayCell {
|
||||
day: string;
|
||||
cells: Array<{
|
||||
data: {
|
||||
customData: {
|
||||
id: string;
|
||||
title: string;
|
||||
scheduleDate: string;
|
||||
scheduleTime: string;
|
||||
};
|
||||
};
|
||||
}>;
|
||||
}
|
||||
|
||||
// 修改 dayCells 的类型定义
|
||||
const dayCells = computed<Record<string, DayCell>>(() => {
|
||||
if (!calendar.value) return {};
|
||||
return calendar.value.dayCells || {};
|
||||
});
|
||||
|
||||
// 日期范围的开始日期引用
|
||||
const startDateRef = ref();
|
||||
// 日期范围的结束日期引用
|
||||
const endDateRef = ref();
|
||||
|
||||
// 点击周数的回调函数
|
||||
const weeknumberClick = (page: any) => {
|
||||
// 获取当前周的第一天和最后一天的日期
|
||||
const startDate = page[0].viewDays[0].id;
|
||||
const endDate = page[0].viewDays[6].id;
|
||||
|
||||
// 更新开始日期引用和结束日期引用
|
||||
startDateRef.value = startDate;
|
||||
endDateRef.value = endDate;
|
||||
|
||||
// 初始化日程列表
|
||||
initscheduleList();
|
||||
};
|
||||
|
||||
//处理日程安排事件,若当前日期下没有日程则打开表单对话框,否则打开日程详情页面
|
||||
const dayClick = (day: any) => {
|
||||
if (filterCellSelected(day.id)) {
|
||||
scheduleRef.value.open({ date: parseDate(day.id, null) });
|
||||
} else {
|
||||
scheduleFormRef.value.openDialog(null, { date: parseDate(day.id, null) });
|
||||
}
|
||||
};
|
||||
|
||||
// 修改开关状态
|
||||
const changeSwitch = async (id: string) => {
|
||||
// 修改对象的状态为'3'
|
||||
await putObj({ id: id, scheduleState: '3' });
|
||||
// 初始化调度列表
|
||||
initscheduleList();
|
||||
};
|
||||
|
||||
const initscheduleList = () => {
|
||||
// 初始化日程列表
|
||||
list({
|
||||
startDate: startDateRef.value,
|
||||
endDate: endDateRef.value,
|
||||
}).then((res) => {
|
||||
// 获取返回结果的数据并转换为合适的格式
|
||||
reminders.value = res.data.map((item: any) => {
|
||||
return {
|
||||
key: item.id,
|
||||
highlight: {
|
||||
color: 'primary',
|
||||
fillMode: 'outline',
|
||||
},
|
||||
dates: item.scheduleDate,
|
||||
customData: item,
|
||||
};
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// 过滤日历中选中的单元格是否有日程
|
||||
const filterCellSelected = (day: string) => {
|
||||
return (
|
||||
reminders.value.filter((item: any) => {
|
||||
return item.dates.includes(day);
|
||||
}).length > 0
|
||||
);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
initscheduleList();
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,78 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
title: '当前用户',
|
||||
icon: 'User',
|
||||
description: '获取当前用户信息展示',
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-card class="flex items-center justify-center h-[191px]">
|
||||
<div class="flex items-center justify-center">
|
||||
<div class="relative">
|
||||
<img class="object-cover w-16 h-16 rounded-full" :src="userData.avatar" alt="Avatar" />
|
||||
<div class="absolute inset-0 rounded-full shadow-inner"></div>
|
||||
</div>
|
||||
<div class="ml-8">
|
||||
<h2 class="text-lg font-bold dark:text-gray-100">{{ userData.name }}</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400">{{ userData.deptName }} | {{ userData.postName }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="currentUser">
|
||||
import { useUserInfo } from '/@/stores/userInfo';
|
||||
import { getObj } from '/@/api/admin/user';
|
||||
import { getCurrentInstance } from 'vue';
|
||||
|
||||
const instance = getCurrentInstance();
|
||||
const proxy = instance?.proxy;
|
||||
|
||||
if (!proxy) {
|
||||
throw new Error('Failed to get component instance');
|
||||
}
|
||||
|
||||
const userData = ref({
|
||||
postName: '',
|
||||
name: '',
|
||||
username: '',
|
||||
userId: '',
|
||||
avatar: '',
|
||||
deptName: '',
|
||||
} as any);
|
||||
const loading = ref(false);
|
||||
|
||||
onMounted(() => {
|
||||
const data = useUserInfo().userInfos;
|
||||
initUserInfo(data.user.userId);
|
||||
});
|
||||
|
||||
/**
|
||||
* 根据用户 ID 初始化用户信息。
|
||||
* @param {any} userId - 要查询的用户 ID。
|
||||
* @returns {Promise<void>} - 初始化用户信息的 Promise 实例。
|
||||
*/
|
||||
const initUserInfo = async (userId: any): Promise<void> => {
|
||||
try {
|
||||
loading.value = true; // 显示加载状态
|
||||
|
||||
const res = await getObj(userId); // 执行查询操作
|
||||
userData.value = res.data; // 将查询到的数据保存到 userData 变量中
|
||||
userData.value.postName = res.data?.postList?.map((item: any) => item.postName).join(',') || ''; // 将 postList 中的 postName 合并成字符串并保存到 userData 变量中
|
||||
// 文件上传增加后端前缀
|
||||
userData.value.avatar = proxy.baseURL + res.data.avatar;
|
||||
} finally {
|
||||
loading.value = false; // 结束加载状态
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.info {
|
||||
margin-left: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,99 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
title: '示例图表1',
|
||||
icon: 'DocumentCopy',
|
||||
description: '示例图表无意义,可删除',
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="relative h-full">
|
||||
<v-chart class="w-full h-80" :option="option"/>
|
||||
</el-card>
|
||||
</template>
|
||||
<script setup lang="ts" name="demo-chart1">
|
||||
import VChart from 'vue-echarts';
|
||||
import {use} from 'echarts/core';
|
||||
import {PieChart} from 'echarts/charts';
|
||||
import {TooltipComponent, LegendComponent} from 'echarts/components';
|
||||
import {CanvasRenderer} from 'echarts/renderers';
|
||||
import {useTagsViewRoutes} from "/@/stores/tagsViewRoutes";
|
||||
import {useMessage} from "/@/hooks/message";
|
||||
|
||||
|
||||
use([TooltipComponent, LegendComponent, PieChart, CanvasRenderer]);
|
||||
|
||||
const option = reactive({
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b}: {c} ({d}%)',
|
||||
},
|
||||
legend: {
|
||||
data: ['Java17', 'Java8', 'Other'],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Java',
|
||||
type: 'pie',
|
||||
selectedMode: 'single',
|
||||
radius: [0, '30%'],
|
||||
label: {
|
||||
position: 'inner',
|
||||
fontSize: 14,
|
||||
},
|
||||
labelLine: {
|
||||
show: false,
|
||||
},
|
||||
data: [
|
||||
{value: 1548, name: 'Java17'},
|
||||
{value: 775, name: 'Java8'},
|
||||
{value: 679, name: 'Other', selected: true},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '使用率',
|
||||
type: 'pie',
|
||||
radius: ['45%', '60%'],
|
||||
labelLine: {
|
||||
length: 30,
|
||||
},
|
||||
label: {
|
||||
formatter: '{a|{a}}{abg|}\n{hr|}\n {b|{b}:}{c} {per|{d}%} ',
|
||||
backgroundColor: '#F6F8FC',
|
||||
borderColor: '#8C8D8E',
|
||||
borderWidth: 1,
|
||||
borderRadius: 4,
|
||||
rich: {
|
||||
a: {
|
||||
color: '#6E7079',
|
||||
lineHeight: 22,
|
||||
align: 'center',
|
||||
},
|
||||
hr: {
|
||||
borderColor: '#8C8D8E',
|
||||
width: '100%',
|
||||
borderWidth: 1,
|
||||
height: 0,
|
||||
},
|
||||
b: {
|
||||
color: '#4C5058',
|
||||
fontSize: 14,
|
||||
fontWeight: 'bold',
|
||||
lineHeight: 33,
|
||||
},
|
||||
per: {
|
||||
color: '#fff',
|
||||
backgroundColor: '#4C5058',
|
||||
padding: [3, 4],
|
||||
borderRadius: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
data: [
|
||||
{value: 1048, name: 'Java17'},
|
||||
{value: 335, name: 'Java8'},
|
||||
{value: 310, name: 'Other'},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,55 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
title: '示例图表2',
|
||||
icon: 'DocumentCopy',
|
||||
description: '示例图表无意义,可删除',
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="relative h-full">
|
||||
<v-chart class="w-full h-80" :option="option" />
|
||||
</el-card>
|
||||
</template>
|
||||
<script setup lang="ts" name="log-line-chart">
|
||||
import VChart from 'vue-echarts';
|
||||
import { use } from 'echarts/core';
|
||||
import { ScatterChart } from 'echarts/charts';
|
||||
import { TitleComponent, GridComponent } from 'echarts/components';
|
||||
import { CanvasRenderer } from 'echarts/renderers';
|
||||
|
||||
use([TitleComponent, ScatterChart, CanvasRenderer, GridComponent]);
|
||||
const option = reactive({
|
||||
xAxis: {},
|
||||
yAxis: {},
|
||||
series: [
|
||||
{
|
||||
symbolSize: 20,
|
||||
data: [
|
||||
[10.0, 8.04],
|
||||
[8.07, 6.95],
|
||||
[13.0, 7.58],
|
||||
[9.05, 8.81],
|
||||
[11.0, 8.33],
|
||||
[14.0, 7.66],
|
||||
[13.4, 6.81],
|
||||
[10.0, 6.33],
|
||||
[14.0, 8.96],
|
||||
[12.5, 6.82],
|
||||
[9.15, 7.2],
|
||||
[11.5, 7.2],
|
||||
[3.03, 4.23],
|
||||
[12.2, 7.83],
|
||||
[2.02, 4.47],
|
||||
[1.05, 3.33],
|
||||
[4.05, 4.96],
|
||||
[6.03, 7.24],
|
||||
[12.0, 6.26],
|
||||
[12.0, 8.84],
|
||||
[7.08, 5.82],
|
||||
[5.02, 5.68],
|
||||
],
|
||||
type: 'scatter',
|
||||
},
|
||||
],
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,14 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
title: '常用流程',
|
||||
icon: 'Star',
|
||||
description: '常用流程收藏',
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<Shortcut :title="$t('home.quickNavigationFlowsTip')" :empty-description="$t('home.addFlowsRoutesTip')" type="flow"></Shortcut>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="SysFavoriteDashboard">
|
||||
const Shortcut = defineAsyncComponent(() => import('/@/views/home/shortcut/index.vue'));
|
||||
</script>
|
||||
@@ -0,0 +1,14 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
title: '常用功能',
|
||||
icon: 'Star',
|
||||
description: '常用功能收藏',
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<Shortcut :title="$t('home.quickNavigationToolsTip')" :empty-description="$t('home.addFavoriteRoutesTip')" type="menu"></Shortcut>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="SysFavoriteDashboard">
|
||||
const Shortcut = defineAsyncComponent(() => import('/@/views/home/shortcut/index.vue'));
|
||||
</script>
|
||||
@@ -0,0 +1,95 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
title: '工作流信息',
|
||||
icon: 'PieChart',
|
||||
description: '获取工作流信息展示',
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="flex items-center justify-center h-[191px]">
|
||||
<div class="relative flex items-center justify-center">
|
||||
<!-- 待办任务 -->
|
||||
<div class="flex-row items-center w-auto">
|
||||
<div class="p-3 rounded-full bg-lightPrimary dark:bg-navy-700">
|
||||
<span class="flex items-center text-brand-500 dark:text-white">
|
||||
<svg
|
||||
t="1697994355915"
|
||||
class="icon"
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="8441"
|
||||
width="32"
|
||||
height="32"
|
||||
>
|
||||
<path
|
||||
d="M404.266667 85.333333v78.933334h236.8V85.333333h78.933333v78.933334h157.866667A39.466667 39.466667 0 0 1 917.333333 203.733333v631.466667A39.466667 39.466667 0 0 1 877.866667 874.666667H167.466667A39.466667 39.466667 0 0 1 128 835.2V203.733333A39.466667 39.466667 0 0 1 167.466667 164.266667h157.866666V85.333333h78.933334zM838.4 361.6H206.933333V795.733333h631.466667V361.6z m-195.904 84.309333l55.808 55.786667-195.370667 195.370667-139.562666-139.562667 55.893333-55.808 83.712 83.754667 139.541333-139.541334h-0.021333z"
|
||||
fill="#8a8a8a"
|
||||
p-id="8442"
|
||||
></path>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<router-link to="/flow/task/pending">
|
||||
<div class="flex flex-col justify-center w-auto ml-4 h-50">
|
||||
<p class="text-sm font-medium text-gray-600 font-dm">{{ $t('home.pendingTask') }}</p>
|
||||
<h4 class="text-xl font-bold text-navy-700 dark:text-white">{{ state.pendingNum }}</h4>
|
||||
</div>
|
||||
</router-link>
|
||||
<!-- 抄送任务 -->
|
||||
<div class="flex-row items-center w-auto ml-8">
|
||||
<div class="p-3 rounded-full bg-lightPrimary dark:bg-navy-700">
|
||||
<span class="flex items-center text-brand-500 dark:text-white">
|
||||
<svg
|
||||
t="1697994410210"
|
||||
class="icon"
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="9746"
|
||||
width="32"
|
||||
height="32"
|
||||
>
|
||||
<path
|
||||
d="M382.293 692.497a37.956 37.956 0 0 1-32.29 7.373v0.205l-278.118-84.31a39.39 39.39 0 0 1-5.803-73.113l862.14-420.045a39.39 39.39 0 0 1 55.432 45.056L823.228 800.358a39.39 39.39 0 0 1-49.63 27.99l-295.595-89.566a15.428 15.428 0 0 1-12.083-14.814c0-4.437 1.98-8.397 5.12-11.196l356.762-401.135-445.44 380.792h-0.069z m98.031 93.867l54 17.886a15.428 15.428 0 0 1 7.986 23.142l-53.93 81.92a15.428 15.428 0 0 1-28.33-8.533v-99.806a15.428 15.428 0 0 1 20.274-14.61z"
|
||||
p-id="9747"
|
||||
fill="#8a8a8a"
|
||||
></path>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<router-link to="/flow/task/cc">
|
||||
<div class="flex flex-col justify-center w-auto ml-4 h-50">
|
||||
<p class="text-sm font-medium text-gray-600 font-dm">{{ $t('home.copyTask') }}</p>
|
||||
<h4 class="text-xl font-bold text-navy-700 dark:text-white">{{ state.copyNum }}</h4>
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="flowData">
|
||||
import { queryTaskData } from '/@/api/flow/task';
|
||||
|
||||
const state = reactive({
|
||||
pendingNum: 0,
|
||||
copyNum: 0,
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const { data } = await queryTaskData();
|
||||
state.pendingNum = Number.parseInt(data?.pendingNum || 0);
|
||||
state.copyNum = Number.parseInt(data?.copyNum || 0);
|
||||
} catch (error) {
|
||||
// 避免没有启动 flow模块 vue 组件渲染 warning
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.el-col {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,12 @@
|
||||
const resultComps = {};
|
||||
|
||||
const files = import.meta.glob('./*.vue', { import: 'default', eager: true });
|
||||
|
||||
Object.keys(files).forEach((fileName) => {
|
||||
if (fileName) {
|
||||
// @ts-ignore
|
||||
resultComps[fileName.replace(/^\.\/(.*)\.\w+$/, '$1')] = files[fileName];
|
||||
}
|
||||
});
|
||||
|
||||
export default markRaw(resultComps);
|
||||
@@ -0,0 +1,73 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
title: '系统公告',
|
||||
icon: 'MuteNotification',
|
||||
description: '系统公告展示',
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="h-96">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>{{ $t('home.newsletterTip') }}</span>
|
||||
<el-button link class="button" text @click="openList">{{ $t('home.moreTip') }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<el-timeline v-if="newsList.length > 0">
|
||||
<div class="relative">
|
||||
<el-timeline-item v-for="(item, index) in newsList" :key="index" :timestamp="item.createTime" @click="contentRef.openDialog(item)">
|
||||
<button class="absolute right-0 px-3 rotate-[10deg] -top-2 border bg-primary text-white font-bold">
|
||||
{{ item.readFlag === '1' ? $t('msg.readed') : $t('msg.unread') }}
|
||||
</button>
|
||||
<div class="p-2 border border-gray-400 purple_border">
|
||||
{{ item.title }}
|
||||
</div>
|
||||
</el-timeline-item>
|
||||
</div>
|
||||
</el-timeline>
|
||||
<el-empty :image-size="120" v-else />
|
||||
</el-card>
|
||||
|
||||
<!-- 消息列表 -->
|
||||
<news-lists ref="listRef"/>
|
||||
|
||||
<!-- 消息内容 -->
|
||||
<news-content ref="contentRef" @refresh="getUserMessage" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="newsLetter">
|
||||
import { fetchUserMessageList } from '/@/api/admin/message';
|
||||
|
||||
const NewsContent = defineAsyncComponent(() => import('/@/views/home/news/content.vue'));
|
||||
const NewsLists = defineAsyncComponent(() => import('/@/views/home/news/list.vue'));
|
||||
|
||||
const listRef = ref();
|
||||
const contentRef = ref();
|
||||
const visible = ref(false);
|
||||
const showList = ref(false);
|
||||
const newsList = ref([]);
|
||||
|
||||
// 获取用户的信息
|
||||
const getUserMessage = () => {
|
||||
// 取前三条数据
|
||||
return fetchUserMessageList({ current: 1, size: 3, category: '0' }).then((res) => {
|
||||
newsList.value = res.data.records;
|
||||
});
|
||||
};
|
||||
|
||||
const openList = () => {
|
||||
showList.value = true;
|
||||
listRef.value.openDialog('0');
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getUserMessage();
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,15 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
title: '请求折线图',
|
||||
icon: 'DocumentCopy',
|
||||
description: '折线图示例',
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="relative h-full">
|
||||
<log-line-chart />
|
||||
</el-card>
|
||||
</template>
|
||||
<script setup lang="ts" name="line-chart">
|
||||
const LogLineChart = defineAsyncComponent(() => import('/@/views/admin/log/line-chart.vue'));
|
||||
</script>
|
||||
@@ -0,0 +1,57 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
title: '系统日志',
|
||||
icon: 'Monitor',
|
||||
description: '系统日志列表',
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<el-card class="h-96 box-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>{{ $t('home.systemLogsTip') }}</span>
|
||||
<el-button link class="button" text @click="handleRoutr">{{ $t('home.moreTip') }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<el-timeline v-if="logState.dataList.length > 0">
|
||||
<el-timeline-item v-for="(item, index) in logState.dataList" :key="index" :timestamp="item.createTime">
|
||||
{{ item.title }} - {{ item.remoteAddr }}
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="SysLogDashboard">
|
||||
import { BasicTableProps, useTable } from '/@/hooks/table';
|
||||
import { pageList } from '/@/api/admin/log';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
// 创建基本表格参数对象
|
||||
const logState: BasicTableProps = reactive({
|
||||
pageList, // 分页列表数据
|
||||
descs: ['create_time'], // 排序方式
|
||||
pagination: {
|
||||
size: 4, // 每页显示数据量
|
||||
},
|
||||
});
|
||||
|
||||
// 使用实例
|
||||
useTable(logState);
|
||||
|
||||
/**
|
||||
* 处理路由跳转事件
|
||||
* @function
|
||||
*/
|
||||
const handleRoutr = () => {
|
||||
router.push('/admin/log/index'); // 跳转到日志管理页面
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user