czh-20260520-增加初版首页

This commit is contained in:
zhihao
2026-05-20 10:57:57 +08:00
parent e051205167
commit 3a7455b39c
6 changed files with 810 additions and 0 deletions
@@ -0,0 +1,342 @@
<template>
<div class="my-work">
<div class="my-work__header">
<h2 class="my-work__title">我的工作</h2>
<div class="my-work__actions">
<div class="my-work__tabs">
<div class="my-work__tab" :class="{ 'my-work__tab--active': activeTab === 'todo' }" @click="activeTab = 'todo'">
待办
<span class="my-work__badge my-work__badge--danger">{{ todoTotal }}</span>
</div>
<div class="my-work__tab" :class="{ 'my-work__tab--active': activeTab === 'cc' }" @click="activeTab = 'cc'">我的抄送</div>
</div>
<a class="my-work__more" @click="goMore">
更多
<RightOutlined class="my-work__more-icon" />
</a>
</div>
</div>
<div class="my-work__body">
<template v-if="activeTab === 'todo'">
<BasicTable @register="registerTodoTable">
<template #action="{ record }">
<TableAction :actions="getTodoTableAction(record)" />
</template>
</BasicTable>
</template>
<template v-if="activeTab === 'cc'">
<BasicTable @register="registerCcTable">
<template #action="{ record }">
<TableAction :actions="getCcTableAction(record)" />
</template>
</BasicTable>
</template>
</div>
<task-handle-modal @register="registerHandleModal" @success="reloadTodo" />
<select-entruster-modal @register="registerEntrusterModal" @selected="selectedEntruster" />
<select-entruster-modal @register="registerComplaintModal" @selected="selectedComplaint" />
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { BasicTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { useModal } from '/@/components/Modal';
import { RightOutlined } from '@ant-design/icons-vue';
import TaskHandleModal from '/@/views/super/bpm/process/personalOffice/myHandleTask/modal/TaskHandleModal.vue';
import SelectEntrusterModal from '/@/views/super/bpm/process/personalOffice/myHandleTask/modal/SelectEntrusterModal.vue';
import { getTaskInfoForHistory } from '/@/views/super/bpm/process/personalOffice/myHandleTask/useTaskList';
import { todoColumns } from '../data/todo.data';
import { ccColumns } from '../data/cc.data';
import {
list as todoList,
taskNodeInfo,
taskEntrust,
taskClaim,
taskComplaint,
} from '/@/views/super/bpm/process/personalOffice/myHandleTask/task.handle.api';
import { list as ccList } from '/@/views/super/bpm/process/personalOffice/myCcTask/task.cc.api';
const router = useRouter();
const activeTab = ref<'todo' | 'cc'>('todo');
const todoTotal = ref(0);
const { tableContext: todoContext } = useListPage({
designScope: 'process-portal-todo',
pagination: true,
tableProps: {
api: (params) => todoList('run', params),
columns: todoColumns,
showIndexColumn: true,
showTableSetting: false,
canResize: false,
scroll: { x: 900 },
actionColumn: { dataIndex: 'action', fixed: 'right', width: 180 },
useSearchForm: false,
},
});
const [registerTodoTable, { reload: reloadTodo }] = todoContext;
const { tableContext: ccContext } = useListPage({
designScope: 'process-portal-cc',
pagination: true,
tableProps: {
api: ccList,
columns: ccColumns,
showIndexColumn: true,
showTableSetting: false,
canResize: false,
scroll: { x: 900 },
actionColumn: { dataIndex: 'action', fixed: 'right', width: 120 },
useSearchForm: false,
},
});
const [registerCcTable] = ccContext;
onMounted(() => {
fetchTodoTotal();
});
async function fetchTodoTotal() {
try {
const res = await todoList('run', { pageNo: 1, pageSize: 1 });
todoTotal.value = res?.total ?? 0;
} catch (e) {
todoTotal.value = 0;
}
}
function goMore() {
if (activeTab.value === 'todo') {
router.push('/task/myHandleTaskInfo');
} else {
router.push('/task/myCcTaskList');
}
}
const [registerHandleModal, { openModal: openHandleModal }] = useModal();
const [registerEntrusterModal, { openModal: openEntrusterModal }] = useModal();
const [registerComplaintModal, { openModal: openComplaintModal }] = useModal();
async function handleProcess(record) {
let { formData, formUrl } = await getTaskNodeInfo(record);
formData['PROCESS_TAB_TYPE'] = 'run';
openHandleModal(true, { formData, formUrl, title: '流程办理' });
}
async function getTaskNodeInfo(record) {
let params = { taskId: record.id };
const result = await taskNodeInfo('run', params);
let procInsId = record.processInstanceId || (result.records ? result.records.BPM_INST_ID : '');
let realDataId = (result.records && result.records.business_id) || result.dataId;
let realTableName = (result.records && result.records.business_tablename) || result.tableName;
let formData: any = {
taskId: record.id,
taskDefKey: result.taskDefKey,
procInsId: procInsId,
dataId: realDataId,
tableName: realTableName,
processDataId: result.dataId,
processTableName: result.tableName,
permissionList: result.permissionList,
subPermissionList: result.subPermissionList,
vars: result.records,
};
let tempFormUrl = result.formUrl;
if (tempFormUrl && tempFormUrl.indexOf('?') != -1 && !/^http[s]?:\/\/.*/.test(tempFormUrl) && tempFormUrl.indexOf('{{DOMAIN_URL}}') == -1) {
tempFormUrl = result.formUrl.split('?')[0];
}
return { formData, formUrl: tempFormUrl };
}
async function handleClaim(record) {
await taskClaim({ taskId: record.id });
await reloadTodo();
await fetchTodoTotal();
}
function handleSelectEntruster(record) {
openEntrusterModal(true, { taskId: record.id });
}
function handleComplaintEntruster(record) {
openComplaintModal(true, { taskId: record.id });
}
async function selectedEntruster(params) {
await taskEntrust(params);
await reloadTodo();
}
async function selectedComplaint(params) {
await taskComplaint(params);
await reloadTodo();
}
async function showCcHistory(record) {
let { formData, formUrl } = await getTaskInfoForHistory(record);
formData['PROCESS_TAB_TYPE'] = 'history';
openHandleModal(true, { formData, formUrl, title: '流程历史' });
}
function getTodoTableAction(record) {
let arr = [];
if (record.taskAssigneeId && record.taskAssigneeId != '') {
arr.push({ label: '办理', onClick: handleProcess.bind(null, record) });
} else {
arr.push({
label: '签收',
popConfirm: {
title: '确定签收吗?',
placement: 'left',
confirm: handleClaim.bind(null, record),
},
});
}
arr.push({ label: '转办', onClick: handleComplaintEntruster.bind(null, record) });
arr.push({ label: '委托', onClick: handleSelectEntruster.bind(null, record) });
return arr;
}
function getCcTableAction(record) {
return [{ label: '查看审批', onClick: showCcHistory.bind(null, record) }];
}
</script>
<style lang="less" scoped>
.my-work {
background: #fff;
border-radius: 12px;
border: 1px solid #f0f0f0;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
margin-bottom: 16px;
overflow: hidden;
&__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 20px;
border-bottom: 1px solid #f0f0f0;
}
&__title {
font-size: 15px;
font-weight: 600;
color: rgba(0, 0, 0, 0.85);
margin: 0;
}
&__actions {
display: flex;
align-items: center;
gap: 16px;
}
&__tabs {
display: flex;
align-items: center;
gap: 4px;
padding: 3px;
background: #f5f5f5;
border-radius: 8px;
}
&__tab {
padding: 5px 14px;
font-size: 13px;
font-weight: 500;
color: rgba(0, 0, 0, 0.45);
border-radius: 6px;
cursor: pointer;
transition: all 0.2s;
user-select: none;
display: flex;
align-items: center;
gap: 6px;
&:hover {
color: rgba(0, 0, 0, 0.65);
}
&--active {
background: #fff;
color: rgba(0, 0, 0, 0.85);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}
}
&__badge {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 18px;
height: 18px;
padding: 0 5px;
font-size: 11px;
font-weight: 600;
border-radius: 9px;
line-height: 1;
&--danger {
background: #ff4d4f;
color: #fff;
}
}
&__more {
font-size: 13px;
color: #1890ff;
cursor: pointer;
display: flex;
align-items: center;
gap: 2px;
white-space: nowrap;
&:hover {
color: #40a9ff;
}
}
&__more-icon {
font-size: 10px;
}
&__body {
padding: 12px 20px;
:deep(.ant-table) {
table {
table-layout: fixed;
width: 100%;
}
.ant-table-thead > tr > th {
background: #fafafa;
font-weight: 600;
font-size: 13px;
color: rgba(0, 0, 0, 0.65);
padding: 10px 12px;
white-space: nowrap;
}
.ant-table-tbody > tr > td {
padding: 10px 12px;
font-size: 13px;
}
.ant-table-tbody > tr:hover > td {
background: #f0f7ff;
}
.ant-table-cell {
white-space: nowrap;
}
}
}
}
</style>