factory_web/src/views/home/my.vue

454 lines
9.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div style="padding: 10px">
<div class="company-card-compact">
<div class="company-main-content">
<div class="company-header-compact">
<h2 class="company-name-compact">光芯科技</h2>
<div class="mission-tag-compact">
<span class="mission-icon-compact"></span>
<span class="mission-text-compact">材料创造美好世界</span>
</div>
</div>
<div class="company-desc-compact">
<p>公司秉承"善用资源,服务建设"的核心理念践行"材料创造美</p>
<p>好世界"的企业使命坚持"创新、绩效、和谐、责任"的核心价</p>
<p>值观努力成长为具有创新精神和全球视野的光芯材料领先企业</p>
</div>
</div>
<div class="company-chip-compact">
<div class="chip-symbol"></div>
</div>
</div>
<div class="statsContainer">
<div class="statCard" @click="goDuty">
<div class="statTitle">我的待办</div>
<div class="statNumber">{{ dutyCount }}</div>
</div>
<div class="statCard" @click="goOwner">
<div class="statTitle">我提交的</div>
<div class="statNumber">{{ ownerCount }}</div>
</div>
</div>
<div class="quickActionsCard">
<div class="quickActionsTitle">发起流程</div>
<div class="quickActionsGrid">
<div class="actionItem" v-for="group in wfOptions" :key="group.category" @click="startGroup(group)">
<div class="actionIcon">↗️</div>
<div class="actionLabel">{{ group.category }}</div>
</div>
</div>
</div>
</div>
<el-dialog v-model="dialogVisible" :title="dialogTitle">
<el-card
v-for="item in currentWfList"
:key="item.id"
:body-style="{ padding: '10px', cursor: 'pointer' }"
style="width: 180px; display: inline-block; margin: 4px; background-color: #f5f7fa;"
shadow="hover"
@click="startTicket(item)"
>
{{ item.name }}
</el-card>
</el-dialog>
<el-drawer v-model="drawer" size="90%" :show-close="false">
<template #header="{ close, titleId, titleClass }">
<h4 :id="titleId" :class="titleClass">{{drawerName}}</h4>
<el-button type="danger" @click="close">关闭</el-button>
</template>
<component :is="currentComponent" :ticketId="ticketId" :t_id="t_id" @closed="drawer = false"
@success="handleSuccess"></component>
</el-drawer>
</template>
<script setup>
import { ref, onMounted, markRaw, defineAsyncComponent } from 'vue'
import API from '@/api'
import TOOL from "@/utils/tool.js";
const dutyCount = ref(0);
const ownerCount = ref(0);
onMounted(() => {
getTicketCount();
getWfOptions();
})
const getTicketCount = () => {
API.wf.ticket.list.req({page: 1, page_size: 0, category: "duty"}).then(res=>{
dutyCount.value = res.count
})
API.wf.ticket.list.req({page: 1, page_size: 0, category: "owner"}).then(res=>{
ownerCount.value = res.count
})
}
const goDuty = () => {
window.location.href = "/#/wf/myticket?category=duty"
}
const goOwner = () => {
window.location.href = "/#/wf/myticket?category=owner"
}
const wfOptions = ref([])
const getWfOptions = () => {
let permissions = TOOL.data.get("PERMISSIONS");
const groups = {};
API.wf.workflow.list.req({ page: 0 }).then((res) => {
res.forEach((item) => {
if(item.key && permissions.includes(item.key)) {
let cate = item.cate;
if (!cate){cate="未分组"}
if (!groups[cate]) {
groups[cate] = [];
}
groups[cate].push(item);
}
})
// 转换为数组形式,便于模板遍历
wfOptions.value = Object.keys(groups).map(category => ({
category,
items: groups[category]
}));
});
}
const dialogVisible = ref(false)
const currentWfList = ref([]);
const dialogTitle = ref("");
const startGroup = (group) => {
dialogVisible.value = true;
dialogTitle.value = group.category;
currentWfList.value = group.items;
}
const drawer = ref(false)
const drawerName = ref(null)
const currentComponent = ref(null)
const ticketId = ref(null)
const t_id = ref(null)
const startTicket = (item) => {
dialogVisible.value = false;
drawer.value = true;
t_id.value = null;
drawerName.value = item.name;
const viewPath = item.view_path;
// 动态 import
currentComponent.value = markRaw(
defineAsyncComponent(() => import(`@/views${viewPath}.vue`))
);
}
const handleSuccess = () => {
drawer.value = false;
getTicketCount();
}
</script>
<style scoped>
.company-card-compact {
width: 100%;
background: linear-gradient(135deg,
rgba(58, 149, 255, 0.95) 0%,
rgba(27, 92, 255, 0.95) 100%);
border-radius: 12px;
padding: 20px;
box-sizing: border-box;
display: flex;
align-items: flex-start;
justify-content: space-between;
position: relative;
overflow: hidden;
box-shadow: 0 4px 12px rgba(27, 92, 255, 0.2);
color: #ffffff;
margin-bottom: 10px;
height: auto;
min-height: 160px;
}
.company-card-compact::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: radial-gradient(
circle at 90% 20%,
rgba(255, 255, 255, 0.08) 0%,
transparent 60%
);
pointer-events: none;
}
.company-main-content {
flex: 1;
padding-right: 15px;
z-index: 1;
}
.company-header-compact {
margin-bottom: 12px;
}
.company-name-compact {
font-size: 20px;
font-weight: 700;
margin: 0 0 8px 0;
letter-spacing: 0.5px;
line-height: 1.2;
}
.mission-tag-compact {
display: inline-flex;
align-items: center;
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(5px);
border-radius: 12px;
padding: 4px 10px;
border: 1px solid rgba(255, 255, 255, 0.15);
}
.mission-icon-compact {
font-size: 12px;
margin-right: 6px;
}
.mission-text-compact {
font-size: 12px;
font-weight: 500;
opacity: 0.95;
}
.company-desc-compact {
line-height: 1.4;
}
.company-desc-compact p {
margin: 0 0 4px 0;
font-size: 12px;
opacity: 0.9;
line-height: 1.3;
}
.company-desc-compact p:last-child {
margin-bottom: 0;
}
.company-chip-compact {
display: flex;
align-items: center;
justify-content: center;
width: 60px;
height: 60px;
flex-shrink: 0;
z-index: 1;
}
.chip-symbol {
width: 50px;
height: 50px;
background: linear-gradient(135deg,
rgba(255, 255, 255, 0.95) 0%,
rgba(255, 255, 255, 0.8) 100%);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
font-weight: 700;
color: #1b5cff;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
/* transform: rotate(45deg); */
}
.chip-symbol::before {
content: '';
position: absolute;
top: 4px;
left: 4px;
right: 4px;
bottom: 4px;
border: 1px solid rgba(27, 92, 255, 0.2);
border-radius: 8px;
}
/* 平板适配 */
@media (min-width: 768px) {
.company-card-compact {
padding: 20px 25px;
min-height: 140px;
}
.company-name-compact {
font-size: 22px;
}
.company-desc-compact p {
font-size: 13px;
}
.chip-symbol {
width: 55px;
height: 55px;
font-size: 22px;
}
}
/* 桌面适配 */
@media (min-width: 1024px) {
.company-card-compact {
padding: 20px 30px;
}
.company-name-compact {
font-size: 24px;
}
.company-desc-compact p {
font-size: 14px;
}
.company-chip-compact {
width: 70px;
height: 70px;
}
.chip-symbol {
width: 60px;
height: 60px;
font-size: 24px;
}
}
/* 小屏幕手机适配 */
@media (max-width: 375px) {
.company-card-compact {
padding: 16px;
min-height: 140px;
}
.company-name-compact {
font-size: 18px;
}
.company-desc-compact p {
font-size: 11px;
}
.mission-tag-compact {
padding: 3px 8px;
}
.mission-text-compact {
font-size: 11px;
}
.company-chip-compact {
width: 50px;
height: 50px;
}
.chip-symbol {
width: 45px;
height: 45px;
font-size: 18px;
}
}
/* 数量统计卡片样式 */
.statsContainer {
display: flex;
gap: 15px;
margin-bottom: 10px;
}
.statCard {
flex: 1;
background: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
text-align: center;
}
.statTitle {
font-size: 18px;
color: #666;
font-weight: bold;
margin-bottom: 10px;
}
.statNumber {
font-size: 28px;
font-weight: bold;
color: #333;
}
/* 快速操作卡片样式 */
.quickActionsCard {
background: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
.quickActionsTitle {
font-size: 16px;
font-weight: bold;
color: #333;
margin-bottom: 20px;
padding-left: 8px;
}
.quickActionsGrid {
display: grid;
grid-template-columns: repeat(8, 1fr);
gap: 6px;
}
.actionItem {
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
transition: transform 0.2s;
}
.actionItem:hover {
transform: translateY(-2px);
}
.actionIcon {
font-size: 24px;
margin-bottom: 8px;
width: 60px;
height: 60px;
background: #f0f7ff;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
color: #1b5cff;
}
.actionLabel {
font-size: 16px;
color: #333;
text-align: center;
font-weight: 500;
}
/* 响应式设计 */
@media (max-width: 768px) {
.quickActionsGrid {
grid-template-columns: repeat(2, 1fr);
}
.statsContainer {
flex-direction: column;
}
}
</style>