mps-platform/cds-fontend-2025.V1/src/views/system/dept-transfer/index.vue
SGK\17962 2179577540 导入-修改导入权限,删除增删改按钮
将中文名改成业务子类id
分成比例编辑页面不可编辑支行
调岗时间修改格式
删除冗余代码
2025-09-05 11:08:41 +08:00

329 lines
8.7 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.

<script setup lang="tsx">
import { ref, watch } from 'vue';
import { NDivider } from 'naive-ui';
import { fetchBatchDeleteDeptTransfer, fetchGetDeptTransferList } from '@/service/api/system/dept-transfer';
import {fetchGetDeptTree, fetchGetMuUserSelect} from '@/service/api/system';
import { useAppStore } from '@/store/modules/app';
import { useAuth } from '@/hooks/business/auth';
import { useDownload } from '@/hooks/business/download';
import { useTable, useTableOperate } from '@/hooks/common/table';
import { $t } from '@/locales';
import ButtonIcon from '@/components/custom/button-icon.vue';
import DeptTransferOperateDrawer from './modules/dept-transfer-operate-drawer.vue';
import DeptTransferSearch from './modules/dept-transfer-search.vue';
import DeptTransferImportModal from './modules/dept-transfer-import-modal.vue';
import { useBoolean, useLoading } from '~/packages/hooks';
defineOptions({
name: 'DeptTransferList'
});
const appStore = useAppStore();
const { download } = useDownload();
const { hasAuth } = useAuth();
const { bool: importVisible, setTrue: openImportModal } = useBoolean();
const {
columns,
columnChecks,
data,
getData,
getDataByPage,
loading,
mobilePagination,
searchParams,
resetSearchParams
} = useTable({
apiFn: fetchGetDeptTransferList,
apiParams: {
pageNum: 1,
pageSize: 10,
// if you want to use the searchParams in Form, you need to define the following properties, and the value is null
// the value can not be undefined, otherwise the property in Form will not be reactive
nickName: null,
mktNo: null,
oldDeptId: null,
newDeptId: null,
transferDate: null,
params: {}
},
columns: () => [
{
type: 'selection',
align: 'center',
width: 48
},
{
key: 'index',
title: $t('common.index'),
align: 'center',
width: 64,
resizable: true
},
// {
// key: 'id',
// title: '主键ID',
// align: 'center',
// minWidth: 120,
// ellipsis: true,
// resizable: true
// },
{
key: 'nickName',
title: '用户姓名',
align: 'center',
minWidth: 120,
ellipsis: true,
resizable: true
},
{
key: 'mktNo',
title: '营销编号',
align: 'center',
minWidth: 120,
ellipsis: true,
resizable: true
},
{
key: 'oldDeptName',
title: '调岗前部门',
align: 'center',
minWidth: 120,
ellipsis: true,
resizable: true
},
{
key: 'newDeptName',
title: '调岗后部门',
align: 'center',
minWidth: 120,
ellipsis: true,
resizable: true
},
{
key: 'transferDate',
title: '调岗时间',
align: 'center',
minWidth: 120,
ellipsis: true,
resizable: true
},
{
key: 'remark',
title: '备注',
align: 'center',
minWidth: 120,
ellipsis: true,
resizable: true
},
{
key: 'operate',
title: $t('common.operate'),
fixed: 'right',
width: 130,
render: row => {
const divider = () => {
if (!hasAuth('system:deptTransfer:edit') || !hasAuth('system:deptTransfer:remove')) {
return null;
}
return <NDivider vertical />;
};
const editBtn = () => {
if (!hasAuth('system:deptTransfer:edit')) {
return null;
}
return (
<ButtonIcon
text
type="primary"
local-icon="drive-file-rename-outline-outline"
tooltipContent={$t('common.edit')}
onClick={() => edit(row.id!)}
/>
);
};
const deleteBtn = () => {
if (!hasAuth('system:deptTransfer:remove')) {
return null;
}
return (
<ButtonIcon
text
type="error"
local-icon="delete-outline"
tooltipContent={$t('common.delete')}
popconfirmContent={$t('common.confirmDelete')}
onPositiveClick={() => handleDelete(row.id!)}
/>
);
};
return (
<div class="flex-center gap-8px">
{editBtn()}
{divider()}
{deleteBtn()}
</div>
);
}
}
]
});
const scrollX = ref(0);
// 计算总宽度函数
const calculateTotalWidth = () => {
let totalWidth = 0;
const visibleColumns = columns.value;
for (let i = 0; i < visibleColumns.length; i++) {
const column = visibleColumns[i];
// 获取列的实际渲染宽度
// 注意:调整大小时会更新 column.width
let width = column.width;
// 如果没有显式宽度则使用minWidth或默认值
if (!width) {
width = column.minWidth || 120;
}
// 转换为数字类型
width = typeof width === 'string' ? Number.parseInt(width) : width;
totalWidth += width;
}
// 添加额外的50px余量防止边缘裁剪
return totalWidth + 50;
};
// 监听列变化并计算宽度
watch(
columns,
newColumns => {
scrollX.value = calculateTotalWidth();
},
{ deep: true }
);
const {startLoading: startDeptLoading, endLoading: endDeptLoading } = useLoading();
const operatorIdOptions = ref<CommonType.Option<CommonType.IdType>[]>([]);
async function getoperatorIdOptions() {
startDeptLoading();
const { error, data } = await fetchGetMuUserSelect();
if (!error) {
operatorIdOptions.value = data.map(item => ({
label: item.nickName,
value: item.mktNo
}));
}
endDeptLoading();
}
getoperatorIdOptions();
const deptData = ref<Api.Common.CommonTreeRecord>([]);
async function getTreeData() {
startDeptLoading();
const { data: tree, error } = await fetchGetDeptTree();
if (!error) {
deptData.value = tree;
}
endDeptLoading();
}
getTreeData();
const { drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted } =
useTableOperate(data, getData);
async function handleBatchDelete() {
// request
const { error } = await fetchBatchDeleteDeptTransfer(checkedRowKeys.value);
if (error) return;
onBatchDeleted();
}
async function handleDelete(id: CommonType.IdType) {
// request
const { error } = await fetchBatchDeleteDeptTransfer([id]);
if (error) return;
onDeleted();
}
function edit(id: CommonType.IdType) {
handleEdit('id', id);
}
function handleImport() {
openImportModal();
}
function handleExport() {
download('/system/deptTransfer/export', searchParams, `部门调整_${new Date().getTime()}.xlsx`);
}
</script>
<template>
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
<DeptTransferSearch
v-model:model="searchParams"
:dept-data="deptData"
:operator-id-options="operatorIdOptions"
@reset="resetSearchParams"
@search="getDataByPage"
/>
<NCard title="部门调整列表" :bordered="false" size="small" class="card-wrapper sm:flex-1-hidden">
<template #header-extra>
<TableHeaderOperation
v-model:columns="columnChecks"
:disabled-delete="checkedRowKeys.length === 0"
:loading="loading"
:show-add="hasAuth('system:deptTransfer:add')"
:show-delete="hasAuth('system:deptTransfer:remove')"
:show-export="hasAuth('system:deptTransfer:export')"
@add="handleAdd"
@delete="handleBatchDelete"
@export="handleExport"
@refresh="getData"
>
<template #after>
<NButton v-if="hasAuth('system:deptTransfer:import')" size="small" ghost @click="handleImport">
<template #icon>
<SvgIcon local-icon="upload-rounded" />
</template>
{{ $t('common.import') }}
</NButton>
</template>
</TableHeaderOperation>
</template>
<!--scroll-x : 所有表格列宽度之和(包含操作列)+操作列宽度-->
<NDataTable
v-model:checked-row-keys="checkedRowKeys"
:columns="columns"
:data="data"
size="small"
:flex-height="!appStore.isMobile"
:scroll-x="scrollX"
:loading="loading"
remote
:row-key="row => row.id"
:pagination="mobilePagination"
class="sm:h-full"
@update-resize-widths="scrollX = calculateTotalWidth()"
/>
<DeptTransferImportModal v-model:visible="importVisible" @submitted="getDataByPage" />
<DeptTransferOperateDrawer
v-model:visible="drawerVisible"
:operate-type="operateType"
:row-data="editingData"
:dept-data="deptData"
:operator-id-options="operatorIdOptions"
@submitted="getDataByPage"
/>
</NCard>
</div>
</template>
<style scoped></style>