feat: ship OA drafts/badges, role dual-track, and test-env deploy tooling.

Add approval instance drafts with menu badges, dual-track user/role read model and role bound names, form-designer outline docs, and bare-metal test deploy scripts. Ignore local test-server credential file.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-08-06 13:58:47 +08:00
1 parent 7af53fc344
commit de22678c87
56 files changed
+11861 -6082

No files matched your search

+49 -1
View File
@@ -72,7 +72,46 @@
min-width="140"
align="center"
header-align="center"
/>
>
<template #default="{ row }">
<el-button
class="no-auto-icon"
link
type="primary"
@click="handleView(row)"
>
{{ row.roleName || '-' }}
</el-button>
</template>
</el-table-column>
<el-table-column
label="拥有用户"
min-width="180"
align="center"
header-align="center"
>
<template #default="{ row }">
<span class="role-bound-names-cell">{{
(row.boundUserNames || []).length
? (row.boundUserNames || []).join('、')
: '—'
}}</span>
</template>
</el-table-column>
<el-table-column
label="关联职位"
min-width="160"
align="center"
header-align="center"
>
<template #default="{ row }">
<span class="role-bound-names-cell">{{
(row.boundPostNames || []).length
? (row.boundPostNames || []).join('、')
: '—'
}}</span>
</template>
</el-table-column>
<el-table-column
prop="dataScope"
label="数据权限"
@@ -1054,6 +1093,15 @@
</script>
<style scoped lang="scss">
.role-bound-names-cell {
display: inline-block;
max-width: 100%;
white-space: normal;
word-break: break-word;
line-height: 1.45;
text-align: center;
}
.role-dialog-form,
.data-scope-form {
:deep(.el-form-item) {
+63 -27
View File
@@ -5,7 +5,7 @@
<section class="panel">
<div class="flex gap-4">
<!-- 左侧:组织树 -->
<div class="user-dept-aside w-[280px] shrink-0 border-r border-[var(--mint-border)] pr-4">
<div class="user-dept-aside w-[200px] shrink-0 border-r border-[var(--mint-border)] pr-4">
<!-- 标题与搜索同处 panel-top:避免标题栏底边与独立输入框之间出现不可控的视觉断层 -->
<div class="panel-top user-dept-aside__head">
<h2>组织</h2>
@@ -131,7 +131,14 @@
<template #default="{ row }">
<div class="user-nick-cell">
<el-avatar :size="24" :src="resolveUserAvatarFromInfo(row)" />
<span class="user-nick-cell__name">{{ row.nickName }}</span>
<el-button
class="user-nick-cell__name no-auto-icon"
link
type="primary"
@click="handleView(row)"
>
{{ row.nickName || '-' }}
</el-button>
</div>
</template>
</el-table-column>
@@ -146,6 +153,26 @@
{{ formatUserDeptDisplay(row) }}
</template>
</el-table-column>
<el-table-column
label="职位"
min-width="140"
align="left"
header-align="left"
>
<template #default="{ row }">
<span class="user-multi-label-cell">{{ formatUserPostDisplay(row) }}</span>
</template>
</el-table-column>
<el-table-column
label="角色"
min-width="160"
align="left"
header-align="left"
>
<template #default="{ row }">
<span class="user-multi-label-cell">{{ formatUserEffectiveRoleDisplay(row) }}</span>
</template>
</el-table-column>
<el-table-column
prop="phoneNo"
label="手机号"
@@ -357,22 +384,6 @@
<el-option label="停用" value="0" />
</el-select>
</el-form-item>
<el-form-item label="角色" style="grid-column: 1 / -1">
<el-select
v-model="formData.roleIds"
multiple
filterable
placeholder="请选择角色"
style="width: 100%"
>
<el-option
v-for="item in roleOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="职位" style="grid-column: 1 / -1">
<el-select
v-model="formData.postIds"
@@ -511,15 +522,28 @@
return deptPathLabelMap.value.get(id) || row.deptName || '—'
}
function formatUserRoleDisplay(row: Api.User.UserItem) {
const ids = row.roleIds || []
if (!ids.length) return '—'
function formatRoleIdsDisplay(ids: string[] | undefined | null) {
if (!ids?.length) return '—'
const labels = ids
.map((id) => roleOptions.value.find((o) => o.value === id)?.label)
.filter((name): name is string => Boolean(name))
return labels.length ? labels.join('、') : '—'
}
function formatUserEffectiveRoleDisplay(row: Api.User.UserItem) {
const names = row.effectiveRoleNames || []
if (names.length) return names.join('、')
return formatRoleIdsDisplay(row.effectiveRoleIds)
}
function formatUserDirectRoleDisplay(row: Api.User.UserItem) {
return formatRoleIdsDisplay(row.roleIds)
}
function formatUserPostInheritedRoleDisplay(row: Api.User.UserItem) {
return formatRoleIdsDisplay(row.postInheritedRoleIds)
}
function formatUserPostDisplay(row: Api.User.UserItem) {
const ids = row.postIds || []
if (!ids.length) return '—'
@@ -558,7 +582,6 @@
status: '1',
orderNum: 0,
remark: '',
roleIds: [] as string[],
postIds: [] as string[]
})
@@ -667,7 +690,6 @@
formData.status = '1'
formData.orderNum = 0
formData.remark = ''
formData.roleIds = []
formData.postIds = []
supervisorUserOptions.value = []
editingId.value = null
@@ -708,7 +730,6 @@
formData.status = detail.status || '1'
formData.orderNum = detail.orderNum ?? 0
formData.remark = detail.remark || ''
formData.roleIds = detail.roleIds ? [...detail.roleIds] : []
formData.postIds = detail.postIds ? [...detail.postIds] : []
if (formData.supervisorUserId) {
await remoteSearchSupervisorUsers(detail.nickName || '')
@@ -744,7 +765,6 @@
status: formData.status,
orderNum: formData.orderNum,
remark: formData.remark?.trim() || undefined,
roleIds: [...formData.roleIds],
postIds: [...formData.postIds]
})
} else {
@@ -763,7 +783,6 @@
status: formData.status,
orderNum: formData.orderNum,
remark: formData.remark?.trim() || undefined,
roleIds: formData.roleIds.length ? formData.roleIds : undefined,
postIds: formData.postIds.length ? formData.postIds : undefined
})
}
@@ -882,7 +901,9 @@
value: row.status === '1' ? '正常' : '停用',
tagType: row.status === '1' ? 'success' : 'info'
},
{ label: '角色', value: formatUserRoleDisplay(row), span: true },
{ label: '有效角色', value: formatUserEffectiveRoleDisplay(row), span: true },
{ label: '直接绑定角色', value: formatUserDirectRoleDisplay(row), span: true },
{ label: '职位继承角色', value: formatUserPostInheritedRoleDisplay(row), span: true },
{ label: '职位', value: formatUserPostDisplay(row), span: true },
{ label: '创建时间', value: row.createTime },
{ label: '备注', value: row.remark, span: true }
@@ -964,9 +985,24 @@
}
&__name {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
justify-content: flex-start;
padding: 0;
height: auto;
font-size: inherit;
}
}
/* 职位 / 角色多项用顿号分隔,列宽不足时自然换行 */
.user-multi-label-cell {
display: inline-block;
max-width: 100%;
line-height: 1.5;
white-space: normal;
word-break: break-word;
}
</style>