调整 用户

This commit is contained in:
2026-09-18 18:25:52 +08:00
parent 84d9e098ba
commit bcbc45bb03
6 changed files with 286 additions and 85 deletions
+12
View File
@@ -1354,6 +1354,13 @@ export default {
.filter(fileType => !uploadedTypes.has(fileType));
},
},
watch: {
'$route.fullPath'() {
if (this.isProjectFormPage) {
this.openProjectFormPage();
}
},
},
created() {
this.loadDeptOptions();
this.loadCargoTypeOptions();
@@ -1363,6 +1370,11 @@ export default {
this.openProjectFormPage();
}
},
activated() {
if (this.isProjectFormPage && !this.projectBox) {
this.openProjectFormPage();
}
},
methods: {
buildTableOption() {
return {
-30
View File
@@ -22,14 +22,6 @@
@tree-load="treeLoad"
>
<template #menu-left>
<el-button
type="primary"
plain
:loading="iamSyncLoading"
v-if="userInfo.authority.includes('admin')"
@click="handleIamOrganizationSync"
>同步组织
</el-button>
<el-button
type="danger"
icon="el-icon-delete"
@@ -135,7 +127,6 @@ import {
add,
getDept,
getDeptTree,
syncIamOrganizations,
} from '@/api/system/dept';
import { getLeaderList } from '@/api/system/user';
import { getList as getCustomerArchiveList } from '@/api/vehicle/customer-archive';
@@ -168,7 +159,6 @@ export default {
selectionList: [],
query: {},
loading: true,
iamSyncLoading: false,
parentId: 0,
page: {
pageSize: 10,
@@ -708,26 +698,6 @@ export default {
done(row);
});
},
handleIamOrganizationSync() {
this.$confirm('确定从IAM同步组织信息?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
this.iamSyncLoading = true;
return syncIamOrganizations();
})
.then(res => {
const count = res?.data?.data ?? 0;
this.$message.success(`IAM组织同步完成,共处理${count}`);
this.parentId = 0;
this.onLoad(this.page, this.query);
})
.finally(() => {
this.iamSyncLoading = false;
});
},
handleDelete() {
if (this.selectionList.length === 0) {
this.$message.warning('请选择至少一条数据');
+218 -15
View File
@@ -340,6 +340,45 @@
</template>
</el-dialog>
<el-dialog
v-model="oaSyncVisible"
width="480px"
append-to-body
:close-on-click-modal="false"
:close-on-press-escape="!oaSyncRunning"
:show-close="!oaSyncRunning"
class="oa-sync-dialog"
@close="closeOaSyncDialog"
>
<template #header>
<span class="dialog-title">{{ oaSyncDialogTitle }}</span>
</template>
<div class="oa-sync-body">
<el-progress
:percentage="oaSyncPercent"
:status="oaSyncProgressStatus"
:stroke-width="12"
/>
<div class="oa-sync-meta">当前进度 {{ oaSyncProgress.current || 0 }} / {{ oaSyncTotalPage }} </div>
<div class="oa-sync-stats">
<div class="oa-sync-stat">
<span class="oa-sync-stat__label">同步成功</span>
<span class="oa-sync-stat__value oa-sync-stat__value--success">{{ oaSyncProgress.synced }}</span>
</div>
<div class="oa-sync-stat">
<span class="oa-sync-stat__label">跳过</span>
<span class="oa-sync-stat__value oa-sync-stat__value--skip">{{ oaSyncProgress.skipped }}</span>
</div>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button v-if="oaSyncRunning" @click="cancelOaSync">取消</el-button>
<el-button v-else type="primary" @click="closeOaSyncDialog">关闭</el-button>
</span>
</template>
</el-dialog>
<!-- 认证日志组件 -->
<auth-log ref="authLog" />
<!-- 认证锁定配置组件 -->
@@ -403,6 +442,18 @@ export default {
query: {},
loading: true,
iamSyncLoading: false,
oaSyncVisible: false,
oaSyncRunning: false,
oaSyncCancelled: false,
oaSyncStatus: 'running',
oaSyncController: null,
oaSyncProgress: {
current: 0,
size: 50,
total: 0,
synced: 0,
skipped: 0,
},
page: {
pageSize: 10,
currentPage: 1,
@@ -453,6 +504,46 @@ export default {
},
computed: {
...mapGetters(['userInfo', 'permission']),
oaSyncDialogTitle() {
if (this.oaSyncStatus === 'done') {
return '同步完成';
}
if (this.oaSyncStatus === 'cancelled') {
return '已取消同步';
}
if (this.oaSyncStatus === 'error') {
return '同步失败';
}
return '同步人员';
},
oaSyncTotalPage() {
const total = Number(this.oaSyncProgress.total) || 0;
const size = Number(this.oaSyncProgress.size) || 50;
if (total <= 0) {
return this.oaSyncProgress.current || 0;
}
return Math.max(1, Math.ceil(total / size));
},
oaSyncPercent() {
if (this.oaSyncStatus === 'done') {
return 100;
}
const totalPage = this.oaSyncTotalPage;
const current = Number(this.oaSyncProgress.current) || 0;
if (totalPage <= 0) {
return 0;
}
return Math.min(100, Math.round((current / totalPage) * 100));
},
oaSyncProgressStatus() {
if (this.oaSyncStatus === 'done') {
return 'success';
}
if (this.oaSyncStatus === 'error') {
return 'exception';
}
return undefined;
},
// 所属组织级联配置:checkStrictly 为 false 时只能选择最后一级(叶子节点)
deptCascaderProps() {
return {
@@ -564,23 +655,87 @@ export default {
}
},
handleIamSync() {
this.$confirm('确定从IAM同步人员信息?', '提示', {
this.$confirm('确定从OA同步人员及组织信息?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
this.iamSyncLoading = true;
return syncIamAccounts();
})
.then(res => {
const count = res?.data?.data ?? 0;
this.$message.success(`IAM人员同步完成,共处理${count}`);
}).then(() => {
this.startOaSync();
});
},
startOaSync() {
this.iamSyncLoading = true;
this.oaSyncVisible = true;
this.oaSyncRunning = true;
this.oaSyncCancelled = false;
this.oaSyncStatus = 'running';
this.oaSyncController = new AbortController();
this.oaSyncProgress = {
current: 0,
size: 50,
total: 0,
synced: 0,
skipped: 0,
};
this.runOaSyncPages();
},
isOaSyncCanceledError(error) {
return (
this.oaSyncCancelled ||
error?.code === 'ERR_CANCELED' ||
error?.name === 'CanceledError' ||
error?.name === 'AbortError'
);
},
async runOaSyncPages() {
const size = 50;
let current = 1;
try {
while (!this.oaSyncCancelled) {
const res = await syncIamAccounts(current, size, this.oaSyncController?.signal);
const page = res?.data?.data || {};
this.oaSyncProgress.current = page.current || current;
this.oaSyncProgress.size = page.size || size;
this.oaSyncProgress.total = page.total || 0;
this.oaSyncProgress.synced += page.syncedCount || 0;
this.oaSyncProgress.skipped += page.skippedCount || 0;
if (page.finished) {
this.oaSyncStatus = 'done';
break;
}
current += 1;
}
if (this.oaSyncCancelled && this.oaSyncStatus === 'running') {
this.oaSyncStatus = 'cancelled';
}
} catch (error) {
if (this.isOaSyncCanceledError(error)) {
this.oaSyncStatus = 'cancelled';
} else {
this.oaSyncStatus = 'error';
this.$message.error(error?.message || 'OA人员同步失败');
}
} finally {
this.oaSyncRunning = false;
this.iamSyncLoading = false;
if (this.oaSyncStatus === 'done' || this.oaSyncStatus === 'cancelled') {
this.onLoad(this.page, this.query);
})
.finally(() => {
this.iamSyncLoading = false;
});
}
}
},
cancelOaSync() {
if (!this.oaSyncRunning) {
return;
}
this.oaSyncCancelled = true;
this.oaSyncController?.abort();
},
closeOaSyncDialog() {
if (this.oaSyncRunning) {
this.cancelOaSync();
return;
}
this.oaSyncVisible = false;
},
handleSetLeader(row) {
const tip = row.isLeader === 1 ? '确定取消用户的主管职务?' : '确定设置用户为主管职务?';
@@ -1150,14 +1305,16 @@ export default {
margin-top: 8px;
}
.user-edit-dialog .dialog-title {
.user-edit-dialog .dialog-title,
.oa-sync-dialog .dialog-title {
display: inline-flex;
align-items: center;
font-size: 16px;
font-weight: 600;
}
.user-edit-dialog .dialog-title::before {
.user-edit-dialog .dialog-title::before,
.oa-sync-dialog .dialog-title::before {
width: 4px;
height: 18px;
margin-right: 8px;
@@ -1165,6 +1322,52 @@ export default {
content: '';
}
.oa-sync-body {
padding: 8px 4px 0;
}
.oa-sync-meta {
margin-top: 12px;
color: #606266;
font-size: 13px;
}
.oa-sync-stats {
display: flex;
gap: 16px;
margin-top: 16px;
}
.oa-sync-stat {
flex: 1;
padding: 12px 16px;
background: #fafafa;
border: 1px solid #eff1f7;
border-radius: 4px;
}
.oa-sync-stat__label {
display: block;
color: #909399;
font-size: 12px;
}
.oa-sync-stat__value {
display: block;
margin-top: 6px;
font-size: 22px;
font-weight: 600;
line-height: 1.2;
}
.oa-sync-stat__value--success {
color: #409eff;
}
.oa-sync-stat__value--skip {
color: #909399;
}
.user-edit-dialog .el-form-item {
margin-bottom: 14px;
}