feat: 邀请函邮件发送 + 首次设密/密码为空 + 姓名单一可信源

邀请发送 (菜单暂隐藏, 待确认参数见 发送邀请-待确认参数.md):
- 后端: BizInvite / BizInviteRecipient + Controller/Service/Mapper/XML
- 邮件: InviteMailSender (spring-boot-starter-mail SMTP) + application*.yml 邮件配置
- 上传进度: UploadProgressRegistry + UploadProgressController
- 前端: InviteList / InviteNew / InviteDetail / InviteView + api/business/invite.js
- 原型: proto/html/components/invite-detail / new-invitation / send-invitation

登录/账号:
- 首次设密: /getInfo 返回 isPasswordEmpty, SysProfileController 密码为空时跳过旧密码校验, ForcePasswordDialog 强制弹窗
- 姓名单一可信源 resolveDisplayName: doctor→biz_expert.name, sponsor/executor→biz_person.name, 其余回退 nick_name
- OA compliance 门禁改为按手机号查 ecology 视图 (不再限定 manager/leader)

其它:
- OSS zip 在线查看 (列清单+取单文件, 公开只读) + SecurityConfig permitAll
- doctor 项目详情 ProjectDetail.vue
- 数据库/测试/设计文档 (md) 入库
This commit is contained in:
郭庆泰
2026-09-10 20:40:49 +08:00
parent 56615f9806
commit 5a0a892574
171 changed files with 11032 additions and 876 deletions
@@ -11,7 +11,7 @@
</div>
<!-- ========== 筛选区 ========== -->
<el-form inline :model="q" class="filter-form">
<el-form inline :model="q" class="filter-form" @keyup.enter="load">
<el-form-item label="姓名">
<el-input v-model="q.name" placeholder="姓名" clearable style="width:140px" />
</el-form-item>
@@ -77,6 +77,8 @@
<el-dropdown-item :command="isDisabled(row) ? 'enable' : 'disable'">
{{ isDisabled(row) ? '启用' : '禁用' }}
</el-dropdown-item>
<!-- 删除 (软删除): 软删关联登录账号 sys_user.del_flag, 机构管理员(MAIN)需先更换管理员 -->
<el-dropdown-item command="delete" divided>删除</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
@@ -128,7 +130,7 @@
<script setup>
import { ref, reactive, onMounted, computed, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { bizList, bizUpdate, importPerson, downloadImportTemplate, changePersonAdmin, resetPersonPassword } from '@/api/public'
import { bizList, bizUpdate, bizDelete, importPerson, downloadImportTemplate, changePersonAdmin, resetPersonPassword } from '@/api/public'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Upload, ArrowDown } from '@element-plus/icons-vue'
import ImportResultDialog from '@/components/ImportResultDialog.vue'
@@ -269,11 +271,32 @@ function goView(row) {
})
}
// 操作列 "更多" 下拉: 分发编辑/重置密码/启用/禁用
// 操作列 "更多" 下拉: 分发编辑/重置密码/启用/禁用/删除
function onMoreAction(cmd, row) {
if (cmd === 'edit') return goEdit(row)
if (cmd === 'resetPwd') return onResetPwd(row)
if (cmd === 'enable' || cmd === 'disable') return onToggleStatus(row)
if (cmd === 'delete') return onDelete(row)
}
// ========== 删除 (软删除) ==========
async function onDelete(row) {
// 机构管理员 (MAIN) 不能直接删除: 删了会导致机构无主账号, 需先更换管理员
if (row.accountType === 'MAIN') { ElMessage.warning('机构管理员不能删除,请先更换管理员'); return }
try {
await ElMessageBox.confirm(
`确定删除「${row.name}」吗?删除后其登录账号将一并停用`,
'删除确认',
{ type: 'warning' }
)
} catch { return }
try {
await bizDelete('person', row.personId)
ElMessage.success('已删除')
load()
} catch (e) {
ElMessage.error(e?.msg || e?.message || '删除失败')
}
}
// ========== 批量导入 ==========