优化菜单结构

This commit is contained in:
2024-07-23 05:24:43 +08:00
parent 65ba85dcdb
commit a657ff04ad
70 changed files with 11824 additions and 1 deletions
@@ -0,0 +1,154 @@
<!-- 项目进度 -->
<template>
<a-card
title="全部待处理"
:bordered="false"
:body-style="{ padding: '14px', height: '315px' }"
>
<template #extra>
<more-icon @remove="onRemove" @edit="onEdit" />
</template>
<a-table
row-key="taskId"
size="middle"
:pagination="false"
:customRow="customRow"
:data-source="taskList"
:columns="taskColumns"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'content'">
<a @click="openUrl('/oa/task/detail/' + record.taskId)">{{
record.content
}}</a>
</template>
<template v-else-if="column.key === 'status'">
<a-tag v-if="record.progress === TOBEARRANGED" color="red"
>待安排</a-tag
>
<a-tag v-if="record.progress === PENDING" color="orange"
>待处理</a-tag
>
<a-tag v-if="record.progress === PROCESSING" color="purple"
>处理中</a-tag
>
<a-tag v-if="record.progress === TOBECONFIRMED" color="cyan"
>待评价</a-tag
>
<a-tag v-if="record.progress === COMPLETED" color="green"
>已完成</a-tag
>
<a-tag v-if="record.progress === CLOSED">已关闭</a-tag>
</template>
<template v-else-if="column.key === 'progress'">
<a-progress :percent="record.progress * 2" :steps="5" />
</template>
</template>
</a-table>
</a-card>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import type { ColumnsType } from 'ant-design-vue/es/table';
import { pageTask } from '@/api/oa/task';
import { openUrl } from '@/utils/common';
import type { Task } from '@/api/oa/task/model';
import {
CLOSED,
COMPLETED,
PENDING,
PROCESSING,
TOBEARRANGED,
TOBECONFIRMED
} from '@/api/oa/task/model/progress';
import { toDateString } from 'ele-admin-pro';
defineProps<{
title?: string;
}>();
const emit = defineEmits<{
(e: 'remove'): void;
(e: 'edit'): void;
}>();
const taskColumns = ref<ColumnsType>([
{
key: 'index',
align: 'center',
width: 48,
customRender: ({ index }) => index + 1,
fixed: 'left'
},
{
title: '工单类型',
dataIndex: 'taskType',
width: 120
},
{
title: '问题描述',
dataIndex: 'content',
key: 'content',
ellipsis: true
},
{
title: '问题描述',
dataIndex: 'content',
key: 'content',
ellipsis: true
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
width: 120
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
width: 120,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
}
]);
// 项目进度数据
const taskList = ref<Task[]>([]);
/* 查询项目进度 */
const queryTaskList = () => {
pageTask({ limit: 5, status: 0 }).then((data) => {
if (data) {
taskList.value = data.list;
}
});
};
const onRemove = () => {
emit('remove');
};
const onEdit = () => {
emit('edit');
};
queryTaskList();
/* 自定义行属性 */
const customRow = (record: Task) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
window.open('/oa/task/detail/' + record.taskId);
// openInfo(record);
}
};
};
</script>
@@ -0,0 +1,153 @@
<!-- 项目进度 -->
<template>
<a-card
title="待处理工单"
:bordered="false"
:body-style="{ padding: '14px', height: '315px' }"
>
<template #extra>
<more-icon @remove="onRemove" @edit="onEdit" />
</template>
<a-table
row-key="taskId"
size="middle"
:pagination="false"
:customRow="customRow"
:data-source="taskList"
:columns="taskColumns"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'content'">
<a @click="openUrl('/oa/task/detail/' + record.taskId)">{{
record.content
}}</a>
</template>
<template v-else-if="column.key === 'status'">
<a-tag v-if="record.progress === TOBEARRANGED" color="red"
>待安排</a-tag
>
<a-tag v-if="record.progress === PENDING" color="orange"
>待处理</a-tag
>
<a-tag v-if="record.progress === PROCESSING" color="purple"
>处理中</a-tag
>
<a-tag v-if="record.progress === TOBECONFIRMED" color="cyan"
>待评价</a-tag
>
<a-tag v-if="record.progress === COMPLETED" color="green"
>已完成</a-tag
>
<a-tag v-if="record.progress === CLOSED">已关闭</a-tag>
</template>
<template v-else-if="column.key === 'progress'">
<a-progress :percent="record.progress * 2" :steps="5" />
</template>
</template>
</a-table>
</a-card>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import type { ColumnsType } from 'ant-design-vue/es/table';
import { pageTask } from '@/api/oa/task';
import { openUrl } from '@/utils/common';
import type { Task } from '@/api/oa/task/model';
import {
CLOSED,
COMPLETED,
PENDING,
PROCESSING,
TOBEARRANGED,
TOBECONFIRMED
} from '@/api/oa/task/model/progress';
import { EleProTable, toDateString } from 'ele-admin-pro';
import { useUserStore } from '@/store/modules/user';
import { storeToRefs } from 'pinia';
defineProps<{
title?: string;
}>();
const emit = defineEmits<{
(e: 'remove'): void;
(e: 'edit'): void;
}>();
const taskColumns = ref<ColumnsType>([
{
key: 'index',
align: 'center',
width: 48,
customRender: ({ index }) => index + 1,
fixed: 'left'
},
{
title: '工单类型',
dataIndex: 'taskType',
width: 120
},
{
title: '问题描述',
dataIndex: 'content',
key: 'content',
ellipsis: true
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
width: 120
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
width: 120,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
}
]);
// 项目进度数据
const taskList = ref<Task[]>([]);
/* 查询项目进度 */
const queryTaskList = () => {
const userStore = useUserStore();
const { info } = storeToRefs(userStore);
const userId = info.value?.userId;
pageTask({ limit: 5, status: 0, userId }).then((data) => {
if (data) {
taskList.value = data.list;
}
});
};
const onRemove = () => {
emit('remove');
};
const onEdit = () => {
emit('edit');
};
queryTaskList();
/* 自定义行属性 */
const customRow = (record: Task) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
window.open('/oa/task/detail/' + record.taskId);
// openInfo(record);
}
};
};
</script>
@@ -0,0 +1,86 @@
<template>
<a-card :bordered="false" title="用户评价" :body-style="{ padding: '14px', height: '315px' }">
<div class="ele-cell ele-cell-align-bottom">
<div style="font-size: 51px; line-height: 1">4.5</div>
<div class="ele-cell-content">
<a-rate :value="userRate" disabled />
<span style="color: #fadb14; margin-left: 8px">很棒</span>
</div>
</div>
<div class="ele-cell" style="margin: 18px 0">
<div style="font-size: 28px; line-height: 1" class="ele-text-placeholder">
-0%
</div>
<div class="ele-cell-content ele-text-small ele-text-secondary">
当前没有评价波动
</div>
</div>
<div class="ele-cell">
<div class="ele-cell-content">
<a-progress :percent="60" stroke-color="#52c41a" :show-info="false" />
</div>
<div class="monitor-evaluate-text">
<star-filled />
<span>5 : 368 人</span>
</div>
</div>
<div class="ele-cell">
<div class="ele-cell-content">
<a-progress :percent="40" stroke-color="#1890ff" :show-info="false" />
</div>
<div class="monitor-evaluate-text">
<star-filled />
<span>4 : 256 人</span>
</div>
</div>
<div class="ele-cell">
<div class="ele-cell-content">
<a-progress :percent="20" stroke-color="#faad14" :show-info="false" />
</div>
<div class="monitor-evaluate-text">
<star-filled />
<span>3 : 49 人</span>
</div>
</div>
<div class="ele-cell">
<div class="ele-cell-content">
<a-progress :percent="10" stroke-color="#f5222d" :show-info="false" />
</div>
<div class="monitor-evaluate-text">
<star-filled />
<span>2 : 14 人</span>
</div>
</div>
<div class="ele-cell">
<div class="ele-cell-content">
<a-progress :percent="0" :show-info="false" />
</div>
<div class="monitor-evaluate-text">
<star-filled />
<span>1 : 0 人</span>
</div>
</div>
</a-card>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { StarFilled } from '@ant-design/icons-vue';
// 用户评分
const userRate = ref(4.5);
</script>
<style lang="less" scoped>
.monitor-evaluate-text {
width: 90px;
flex-shrink: 0;
white-space: nowrap;
opacity: 0.8;
& > .anticon {
font-size: 12px;
margin: 0 6px 0 8px;
}
}
</style>
@@ -0,0 +1,79 @@
<template>
<a-card :bordered="false" title="用户满意度" :body-style="{ padding: '14px', height: '315px' }">
<div class="ele-cell ele-text-center">
<div class="ele-cell-content" style="font-size: 24px">856</div>
<div class="ele-cell-content">
<div class="monitor-face-smile"><i></i></div>
<div class="ele-text-secondary ele-elip" style="margin-top: 8px">
正面评论
</div>
</div>
<h2 class="ele-cell-content ele-text-success">82%</h2>
</div>
<a-divider style="margin: 26px 0" />
<div class="ele-cell ele-text-center">
<div class="ele-cell-content" style="font-size: 24px">60</div>
<div class="ele-cell-content">
<div class="monitor-face-cry"><i></i></div>
<div class="ele-text-secondary ele-elip" style="margin-top: 8px">
负面评论
</div>
</div>
<h2 class="ele-cell-content ele-text-danger">9%</h2>
</div>
</a-card>
</template>
<style lang="less" scoped>
.monitor-face-smile,
.monitor-face-cry {
width: 50px;
height: 50px;
display: inline-block;
background: #fbd971;
border-radius: 50%;
position: relative;
}
.monitor-face-smile > i,
.monitor-face-smile:before,
.monitor-face-smile:after,
.monitor-face-cry > i,
.monitor-face-cry:before,
.monitor-face-cry:after {
width: 28px;
height: 28px;
border-radius: 50%;
transform: rotate(225deg);
border: 3px solid #f0c419;
border-right-color: transparent !important;
border-bottom-color: transparent !important;
position: absolute;
bottom: 8px;
left: 11px;
}
.monitor-face-smile:before,
.monitor-face-smile:after,
.monitor-face-cry:before,
.monitor-face-cry:after {
content: '';
width: 12px;
height: 12px;
left: 8px;
top: 14px;
border-color: #f29c1f;
transform: rotate(45deg);
}
.monitor-face-smile:after,
.monitor-face-cry:after {
left: auto;
right: 8px;
}
.monitor-face-cry > i {
transform: rotate(45deg);
bottom: -6px;
}
</style>
@@ -0,0 +1,66 @@
<template>
<ele-modal
:width="400"
:visible="visible"
:title="`工单号:${taskId}`"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
:footer="null"
@ok="save"
>
<div
class="qrcode-list"
style="display: flex; justify-content: space-around"
>
<div>
<img :src="qrcode" width="240" height="240" />
<div
style="
display: flex;
justify-content: center;
font-size: 26px;
padding-top: 20px;
"
>微信扫一扫</div
>
</div>
</div>
</ele-modal>
</template>
<script lang="ts" setup>
import { User } from '@/api/system/user/model';
import { reactive, ref } from 'vue';
defineProps<{
// 弹窗是否打开
visible: boolean;
}>();
const emit = defineEmits<{
(e: 'done', user: User): void;
(e: 'update:visible', visible: boolean): void;
}>();
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
const qrcode = ref('https://file.jimeigroup.cn/reg-code3/hgkghiji.png');
// 用户信息
const form = reactive<User>({
userId: undefined,
nickname: undefined
});
const chooseUser = (item: User) => {
form.userId = item.userId;
form.nickname = item.nickname;
};
const save = () => {
emit('done', form);
};
</script>
<style scoped lang="less"></style>
+150
View File
@@ -0,0 +1,150 @@
<template>
<div class="ele-body ele-body-card">
<a-row :gutter="16">
<a-col v-bind="styleResponsive ? { md: 6, sm: 24, xs: 24 } : { span: 8 }">
<a-card class="analysis-chart-card" :bordered="false">
<div class="ele-text-secondary ele-cell">
<div class="ele-cell-content">待处理</div>
</div>
<h1 class="ele-text-danger">
{{ pendingCount }}
</h1>
</a-card>
</a-col>
<a-col v-bind="styleResponsive ? { md: 6, sm: 24, xs: 24 } : { span: 8 }">
<a-card class="analysis-chart-card" :bordered="false">
<div class="ele-text-secondary ele-cell">
<div class="ele-cell-content">今日处理</div>
<ele-tag color="red">日</ele-tag>
</div>
<h1 class="analysis-chart-card-num">{{ todayCount }}</h1>
</a-card>
</a-col>
<a-col v-bind="styleResponsive ? { md: 6, sm: 24, xs: 24 } : { span: 8 }">
<a-card class="analysis-chart-card" :bordered="false">
<div class="ele-text-secondary ele-cell">
<div class="ele-cell-content">本月处理</div>
<ele-tag color="blue">月</ele-tag>
</div>
<h1 class="analysis-chart-card-num">{{ monthCount }}</h1>
</a-card>
</a-col>
<a-col v-bind="styleResponsive ? { md: 6, sm: 24, xs: 24 } : { span: 8 }">
<a-card class="analysis-chart-card" :bordered="false">
<div class="ele-text-secondary ele-cell">
<div class="ele-cell-content">今年处理</div>
<ele-tag color="green">年</ele-tag>
</div>
<h1 class="analysis-chart-card-num">{{ yearCount }}</h1>
</a-card>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col
v-bind="
styleResponsive
? { xl: 12, lg: 12, md: 12, sm: 12, xs: 24 }
: { span: 6 }
"
>
<CountPendingAll />
</a-col>
<a-col
v-bind="
styleResponsive
? { xl: 6, lg: 24, md: 24, sm: 24, xs: 24 }
: { span: 12 }
"
>
<CountRate />
</a-col>
<a-col
v-bind="
styleResponsive
? { xl: 6, lg: 12, md: 12, sm: 12, xs: 24 }
: { span: 6 }
"
>
<CountSatisfaction />
</a-col>
<a-col
v-bind="
styleResponsive
? { xl: 6, lg: 12, md: 12, sm: 12, xs: 24 }
: { span: 6 }
"
>
<Qrcode />
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import CountSatisfaction from './components/count-satisfaction.vue';
import CountRate from './components/count-rate.vue';
import CountPendingAll from './components/count-pending-all.vue';
import Qrcode from './components/qrcode.vue';
import { pageTask } from '@/api/oa/task';
import { ref } from 'vue';
import { useUserStore } from '@/store/modules/user';
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
// 当前登录用户
const userStore = useUserStore();
const { info } = storeToRefs(userStore);
const pendingCount = ref(0);
const pendingAllCount = ref(0);
const todayCount = ref(0);
const monthCount = ref(0);
const yearCount = ref(0);
const queryTaskCount = () => {
if (info.value?.roles) {
}
const userId = info.value?.userId;
pageTask({ status: 0, userId }).then((res) => {
if (res) {
pendingCount.value = res.count;
}
});
pageTask({ status: 0 }).then((res) => {
if (res) {
pendingAllCount.value = res.count;
}
});
pageTask({}).then((res) => {
if (res) {
todayCount.value = res.count;
}
});
pageTask({}).then((res) => {
if (res) {
monthCount.value = res.count;
}
});
pageTask({}).then((res) => {
if (res) {
yearCount.value = res.count;
}
});
};
queryTaskCount();
</script>
<script lang="ts">
export default {
name: 'CountIndex'
};
</script>
<style lang="less" scoped>
.a-cursor {
cursor: pointer;
}
</style>