|
|
@@ -206,7 +206,7 @@
|
|
|
</div>
|
|
|
|
|
|
<div class="profile-actions">
|
|
|
- <el-button type="success" size="large">邀请评审</el-button>
|
|
|
+ <el-button type="success" size="large" @click="handleJoinTeam">加入团队</el-button>
|
|
|
<el-button size="large" plain>维护档案</el-button>
|
|
|
<el-button size="large" plain>下载履历</el-button>
|
|
|
</div>
|
|
|
@@ -493,7 +493,13 @@
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
import { computed, nextTick, onMounted, reactive, ref } from 'vue'
|
|
|
-import { createExpert, getExpertDetail, getExpertList, getTeamList } from '@/api/expert'
|
|
|
+import {
|
|
|
+ createExpert,
|
|
|
+ getExpertDetail,
|
|
|
+ getExpertList,
|
|
|
+ getTeamList,
|
|
|
+ updateExpert
|
|
|
+} from '@/api/expert'
|
|
|
import * as DeptApi from '@/api/system/dept'
|
|
|
import { defaultProps } from '@/utils/tree'
|
|
|
import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
|
|
|
@@ -529,6 +535,7 @@ const dialogVisible = ref(false)
|
|
|
const dialogTitle = ref('')
|
|
|
const isEdit = ref(false)
|
|
|
const teamDialogVisible = ref(false)
|
|
|
+const teamDialogMode = ref<'form' | 'drawer'>('form')
|
|
|
|
|
|
// 表单相关
|
|
|
const formRef = ref()
|
|
|
@@ -538,6 +545,7 @@ const teamList = ref<any[]>([])
|
|
|
const teamTotal = ref(0)
|
|
|
const tempSelectedTeams = ref<any[]>([])
|
|
|
const selectedTeams = ref<any[]>([])
|
|
|
+const currentExpertDetail = ref<any>(null)
|
|
|
|
|
|
const formRules = {
|
|
|
expertName: [{ required: true, message: '请输入专家名称', trigger: 'blur' }],
|
|
|
@@ -612,6 +620,7 @@ type ExpertProfile = {
|
|
|
direction: string[]
|
|
|
softwareSkills: string[]
|
|
|
teamNames: string[]
|
|
|
+ teamIds: number[]
|
|
|
school: string
|
|
|
birthdayText: string
|
|
|
formerPost: string
|
|
|
@@ -639,6 +648,7 @@ type ExpertItem = {
|
|
|
specialDirection: number[]
|
|
|
achievement: string
|
|
|
softwareSkills: number[]
|
|
|
+ teams?: Array<{ id: number; teamName?: string }>
|
|
|
}
|
|
|
|
|
|
type ExpertGroup = {
|
|
|
@@ -719,8 +729,14 @@ const deptNameMap = computed(() => {
|
|
|
return map
|
|
|
})
|
|
|
|
|
|
-const getTeamNames = (teamIds: number[] = []) =>
|
|
|
- teamIds.map((id) => teamNameMap.value.get(id)).filter(Boolean) as string[]
|
|
|
+const getTeamNames = (teamIds: number[] = [], teams?: Array<{ id: number; teamName?: string }>) => {
|
|
|
+ if (teams?.length) {
|
|
|
+ return teams
|
|
|
+ .map((team) => team.teamName || teamNameMap.value.get(team.id))
|
|
|
+ .filter(Boolean) as string[]
|
|
|
+ }
|
|
|
+ return teamIds.map((id) => teamNameMap.value.get(id)).filter(Boolean) as string[]
|
|
|
+}
|
|
|
|
|
|
const getDeptName = (deptId?: number) => {
|
|
|
if (deptId === undefined || deptId === null) return ''
|
|
|
@@ -753,7 +769,8 @@ const buildExpertProfile = (expert: ExpertItem, groupLabel?: string): ExpertProf
|
|
|
const rankLabels = getDictLabels(DICT_TYPE.RD_EXPERT_RANK, expert.expertRank)
|
|
|
const directionLabels = getDictLabels(DICT_TYPE.RD_EXPERT_TECHNICAL, expert.specialDirection)
|
|
|
const softwareSkillLabels = getDictLabels(DICT_TYPE.RD_EXPERT_SOFTWARE, expert.softwareSkills)
|
|
|
- const teamNames = getTeamNames(expert.teamIds)
|
|
|
+ const teamIds = expert.teams?.length ? expert.teams.map((team) => team.id) : expert.teamIds || []
|
|
|
+ const teamNames = getTeamNames(teamIds, expert.teams)
|
|
|
return {
|
|
|
id: expert.id,
|
|
|
name: expert.expertName,
|
|
|
@@ -766,6 +783,7 @@ const buildExpertProfile = (expert: ExpertItem, groupLabel?: string): ExpertProf
|
|
|
direction: directionLabels.length ? directionLabels : ['暂无'],
|
|
|
softwareSkills: softwareSkillLabels,
|
|
|
teamNames,
|
|
|
+ teamIds,
|
|
|
school: expert.school || '',
|
|
|
birthdayText: formatBirthday(expert.birthday),
|
|
|
formerPost: expert.formerPost || '',
|
|
|
@@ -860,6 +878,7 @@ const handleMemberClick = async (member: ExpertItem) => {
|
|
|
drawerLoading.value = true
|
|
|
try {
|
|
|
const detail = await getExpertDetail(member.id)
|
|
|
+ currentExpertDetail.value = detail
|
|
|
activeExpert.value = buildExpertProfile(detail)
|
|
|
} finally {
|
|
|
drawerLoading.value = false
|
|
|
@@ -912,14 +931,73 @@ const resetTeamQuery = async () => {
|
|
|
}
|
|
|
|
|
|
const openTeamDialog = async () => {
|
|
|
+ teamDialogMode.value = 'form'
|
|
|
teamDialogVisible.value = true
|
|
|
tempSelectedTeams.value = [...selectedTeams.value]
|
|
|
await getTeamOptionsList()
|
|
|
}
|
|
|
|
|
|
-const confirmTeamSelection = () => {
|
|
|
+const ensureSelectedTeams = async (teamIds: number[]) => {
|
|
|
+ if (!teamIds?.length) {
|
|
|
+ selectedTeams.value = []
|
|
|
+ tempSelectedTeams.value = []
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const teamMap = new Map<number, any>()
|
|
|
+ ;[...selectedTeams.value, ...teamList.value].forEach((team) => {
|
|
|
+ teamMap.set(team.id, team)
|
|
|
+ })
|
|
|
+
|
|
|
+ const missingIds = teamIds.filter((id) => !teamMap.has(id))
|
|
|
+ if (missingIds.length) {
|
|
|
+ const res = await getTeamList({ pageNo: 1, pageSize: 10 })
|
|
|
+ ;(res.list || []).forEach((team) => {
|
|
|
+ teamMap.set(team.id, team)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ selectedTeams.value = teamIds.map((id) => teamMap.get(id)).filter(Boolean)
|
|
|
+ tempSelectedTeams.value = [...selectedTeams.value]
|
|
|
+}
|
|
|
+
|
|
|
+const handleJoinTeam = async () => {
|
|
|
+ if (!activeExpert.value) return
|
|
|
+
|
|
|
+ teamDialogMode.value = 'drawer'
|
|
|
+ const currentTeamIds =
|
|
|
+ currentExpertDetail.value?.teams?.map((team) => team.id) || activeExpert.value.teamIds || []
|
|
|
+ await ensureSelectedTeams(currentTeamIds)
|
|
|
+ teamDialogVisible.value = true
|
|
|
+ await getTeamOptionsList()
|
|
|
+}
|
|
|
+
|
|
|
+const confirmTeamSelection = async () => {
|
|
|
selectedTeams.value = [...tempSelectedTeams.value]
|
|
|
- formData.value.teamIds = selectedTeams.value.map((team) => team.id)
|
|
|
+ const teamIds = selectedTeams.value.map((team) => team.id)
|
|
|
+
|
|
|
+ if (teamDialogMode.value === 'drawer') {
|
|
|
+ if (!currentExpertDetail.value || !activeExpert.value) return
|
|
|
+
|
|
|
+ await updateExpert({
|
|
|
+ ...currentExpertDetail.value,
|
|
|
+ teams: selectedTeams.value,
|
|
|
+ teamIds
|
|
|
+ })
|
|
|
+
|
|
|
+ currentExpertDetail.value = {
|
|
|
+ ...currentExpertDetail.value,
|
|
|
+ teams: selectedTeams.value,
|
|
|
+ teamIds
|
|
|
+ }
|
|
|
+ activeExpert.value = buildExpertProfile(currentExpertDetail.value)
|
|
|
+ teamDialogVisible.value = false
|
|
|
+ ElMessage.success('加入团队成功')
|
|
|
+ await getList()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ formData.value.teamIds = teamIds
|
|
|
teamDialogVisible.value = false
|
|
|
}
|
|
|
|