初始化
This commit is contained in:
264
src/views/system/user/modules/user-org-leader-dialog.vue
Normal file
264
src/views/system/user/modules/user-org-leader-dialog.vue
Normal file
@@ -0,0 +1,264 @@
|
||||
<script setup lang="tsx">
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { ElButton, ElEmpty, ElTag } from 'element-plus';
|
||||
import dayjs from 'dayjs';
|
||||
import {
|
||||
fetchDeleteOrgLeaderRelation,
|
||||
fetchGetOrgLeaderCandidateUsers,
|
||||
fetchGetOrgLeaderListByDept,
|
||||
fetchGetUserPage
|
||||
} from '@/service/api';
|
||||
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
import BusinessTableActionCell from '@/components/custom/business-table-action-cell';
|
||||
import { $t } from '@/locales';
|
||||
import UserOrgLeaderOperateDialog from './user-org-leader-operate-dialog.vue';
|
||||
|
||||
defineOptions({ name: 'UserOrgLeaderDialog' });
|
||||
|
||||
interface Props {
|
||||
dept?: Api.SystemManage.Dept | null;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const visible = defineModel<boolean>('visible', {
|
||||
default: false
|
||||
});
|
||||
|
||||
const loading = ref(false);
|
||||
const relations = ref<Api.SystemManage.OrgLeaderRelation[]>([]);
|
||||
const candidateUsers = ref<Api.SystemManage.OrgLeaderCandidateUser[]>([]);
|
||||
const operateVisible = ref(false);
|
||||
const operateType = ref<UI.TableOperateType>('add');
|
||||
const editingData = ref<Api.SystemManage.OrgLeaderRelation | null>(null);
|
||||
|
||||
const title = computed(() => {
|
||||
if (props.dept?.name) {
|
||||
return `${$t('page.system.user.orgLeaderTitle')} / ${props.dept.name}`;
|
||||
}
|
||||
|
||||
return $t('page.system.user.orgLeaderTitle');
|
||||
});
|
||||
|
||||
const total = computed(() => relations.value.length);
|
||||
|
||||
function formatTime(value?: number | null) {
|
||||
if (!value) {
|
||||
return '--';
|
||||
}
|
||||
|
||||
return dayjs(value).format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
|
||||
function isCandidateUser(item: unknown): item is Api.SystemManage.OrgLeaderCandidateUser {
|
||||
if (!item || typeof item !== 'object') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const record = item as Record<string, unknown>;
|
||||
|
||||
return typeof record.id === 'number' && typeof record.nickname === 'string' && typeof record.deptId === 'number';
|
||||
}
|
||||
|
||||
function mapUsersToCandidateUsers(users: Api.SystemManage.User[]): Api.SystemManage.OrgLeaderCandidateUser[] {
|
||||
const now = Date.now();
|
||||
|
||||
return users
|
||||
.filter(item => !item.resignedAt || item.resignedAt > now)
|
||||
.map(item => ({
|
||||
id: item.id,
|
||||
nickname: item.nickname?.trim() || item.username,
|
||||
deptId: item.deptId,
|
||||
deptName: item.deptName ?? null
|
||||
}));
|
||||
}
|
||||
|
||||
async function loadCandidateUsers(deptId: number) {
|
||||
const candidateResult = await fetchGetOrgLeaderCandidateUsers(deptId);
|
||||
|
||||
if (!candidateResult.error && Array.isArray(candidateResult.data) && candidateResult.data.every(isCandidateUser)) {
|
||||
return candidateResult.data;
|
||||
}
|
||||
|
||||
const userResult = await fetchGetUserPage({
|
||||
pageNo: 1,
|
||||
pageSize: 200,
|
||||
deptId,
|
||||
status: 0
|
||||
});
|
||||
|
||||
if (userResult.error) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return mapUsersToCandidateUsers(userResult.data.list);
|
||||
}
|
||||
|
||||
async function loadData() {
|
||||
if (!props.dept?.id) {
|
||||
relations.value = [];
|
||||
candidateUsers.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
|
||||
const [relationResult, candidates] = await Promise.all([
|
||||
fetchGetOrgLeaderListByDept(props.dept.id),
|
||||
loadCandidateUsers(props.dept.id)
|
||||
]);
|
||||
|
||||
loading.value = false;
|
||||
|
||||
relations.value = relationResult.error ? [] : relationResult.data;
|
||||
candidateUsers.value = candidates;
|
||||
}
|
||||
|
||||
function openAdd() {
|
||||
operateType.value = 'add';
|
||||
editingData.value = null;
|
||||
operateVisible.value = true;
|
||||
}
|
||||
|
||||
function openEdit(row: Api.SystemManage.OrgLeaderRelation) {
|
||||
operateType.value = 'edit';
|
||||
editingData.value = row;
|
||||
operateVisible.value = true;
|
||||
}
|
||||
|
||||
async function handleDelete(row: Api.SystemManage.OrgLeaderRelation) {
|
||||
const { error } = await fetchDeleteOrgLeaderRelation(row.id);
|
||||
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.$message?.success($t('common.deleteSuccess'));
|
||||
await loadData();
|
||||
}
|
||||
|
||||
async function handleDeleteAction(row: Api.SystemManage.OrgLeaderRelation) {
|
||||
try {
|
||||
await window.$messageBox?.confirm($t('common.confirmDelete'), $t('common.warning'), {
|
||||
confirmButtonText: $t('common.confirm'),
|
||||
cancelButtonText: $t('common.cancel'),
|
||||
type: 'warning'
|
||||
});
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
await handleDelete(row);
|
||||
}
|
||||
|
||||
async function handleSubmitted() {
|
||||
operateVisible.value = false;
|
||||
await loadData();
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [visible.value, props.dept?.id] as const,
|
||||
async ([dialogVisible, deptId]) => {
|
||||
if (!dialogVisible || !deptId) {
|
||||
return;
|
||||
}
|
||||
|
||||
await loadData();
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BusinessFormDialog v-model="visible" :title="title" preset="lg" :show-footer="false">
|
||||
<div class="flex-col-stretch gap-16px">
|
||||
<div class="flex items-center justify-between gap-12px">
|
||||
<div class="flex items-center gap-8px">
|
||||
<ElTag type="primary" effect="light">{{ dept?.name || $t('common.noData') }}</ElTag>
|
||||
<ElTag effect="plain">{{ total }}</ElTag>
|
||||
</div>
|
||||
<div class="flex items-center gap-8px">
|
||||
<ElButton type="primary" plain size="small" @click="openAdd">
|
||||
<template #icon>
|
||||
<icon-ic-round-plus class="text-icon" />
|
||||
</template>
|
||||
{{ $t('common.add') }}
|
||||
</ElButton>
|
||||
<ElButton plain size="small" @click="loadData">
|
||||
<template #icon>
|
||||
<icon-mdi-refresh class="text-icon" />
|
||||
</template>
|
||||
{{ $t('common.refresh') }}
|
||||
</ElButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-loading="loading" class="min-h-260px">
|
||||
<template v-if="relations.length">
|
||||
<div class="min-h-260px">
|
||||
<ElTable border :data="relations" :max-height="420">
|
||||
<ElTableColumn type="index" :label="$t('common.index')" width="64" />
|
||||
<ElTableColumn prop="userNickname" :label="$t('page.system.user.orgLeader')" min-width="140" />
|
||||
<ElTableColumn
|
||||
prop="effectiveFrom"
|
||||
:label="$t('page.system.user.effectiveFrom')"
|
||||
min-width="170"
|
||||
:formatter="row => formatTime(row.effectiveFrom)"
|
||||
/>
|
||||
<ElTableColumn
|
||||
prop="effectiveUntil"
|
||||
:label="$t('page.system.user.effectiveUntil')"
|
||||
min-width="170"
|
||||
:formatter="row => formatTime(row.effectiveUntil)"
|
||||
/>
|
||||
<ElTableColumn
|
||||
prop="remark"
|
||||
:label="$t('page.system.user.relationRemark')"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<ElTableColumn
|
||||
prop="createTime"
|
||||
:label="$t('page.system.user.createTime')"
|
||||
min-width="170"
|
||||
:formatter="row => formatTime(row.createTime)"
|
||||
/>
|
||||
<ElTableColumn :label="$t('common.operate')" width="196" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<BusinessTableActionCell
|
||||
:actions="[
|
||||
{
|
||||
key: 'edit',
|
||||
label: $t('common.edit'),
|
||||
buttonType: 'primary',
|
||||
onClick: () => openEdit(row)
|
||||
},
|
||||
{
|
||||
key: 'delete',
|
||||
label: $t('common.delete'),
|
||||
buttonType: 'danger',
|
||||
onClick: () => handleDeleteAction(row)
|
||||
}
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
</ElTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-else class="min-h-260px flex items-center justify-center">
|
||||
<ElEmpty :description="$t('page.system.user.emptyLeader')" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<UserOrgLeaderOperateDialog
|
||||
v-model:visible="operateVisible"
|
||||
:operate-type="operateType"
|
||||
:row-data="editingData"
|
||||
:dept="dept"
|
||||
:candidate-users="candidateUsers"
|
||||
@submitted="handleSubmitted"
|
||||
/>
|
||||
</BusinessFormDialog>
|
||||
</template>
|
||||
Reference in New Issue
Block a user