fix: support demand identity selection on task creation

This commit is contained in:
Your Name 2026-03-30 10:12:24 +08:00
parent eb6f0c28b1
commit a727cc0622
7 changed files with 261 additions and 62 deletions

View File

@ -38,6 +38,7 @@ public class PipelineTaskDTO {
private Long brandId; private Long brandId;
private Long categoryId; private Long categoryId;
private Long platformId; private Long platformId;
private Long publisherDeptId;
private String spuInfo; private String spuInfo;
private String taskSubType; private String taskSubType;
private String attachmentUrl; private String attachmentUrl;

View File

@ -89,29 +89,9 @@ public class TaskService {
// 检查是否是管理员(管理员可以同时拥有需求部门和接单部门权限) // 检查是否是管理员(管理员可以同时拥有需求部门和接单部门权限)
boolean isAdmin = isAdminUser(user.getId()); boolean isAdmin = isAdminUser(user.getId());
if (!isAdmin) { Department publisherDept = resolvePublishingDepartment(user, task.getPublisherDeptId(), isAdmin);
if (user.getDeptId() == null) { isPrimaryTask = "primary_demand".equals(publisherDept.getDeptType());
throw new BusinessException(ResultCode.FORBIDDEN, "用户部门信息不完整"); task.setPublisherDeptId(publisherDept.getId());
}
var department = departmentService.getDepartmentById(user.getDeptId());
if (department == null) {
throw new BusinessException(ResultCode.FORBIDDEN, "用户部门不存在");
}
String deptType = department.getDeptType();
if (!"demand".equals(deptType) && !"primary_demand".equals(deptType)) {
throw new BusinessException(ResultCode.FORBIDDEN, "只有需求部门或一级需求部门可以发起任务,您所在的部门是接单部门");
}
// 判断是否为一级需求部门发起的任务
isPrimaryTask = "primary_demand".equals(deptType);
}
// 设置发布人部门ID
if (task.getPublisherDeptId() == null && user.getDeptId() != null) {
task.setPublisherDeptId(user.getDeptId());
}
} }
// 如果是一级需求部门发起的任务,设置相关字段 // 如果是一级需求部门发起的任务,设置相关字段
@ -289,26 +269,8 @@ public class TaskService {
// 检查是否是管理员 // 检查是否是管理员
boolean isAdmin = isAdminUser(user.getId()); boolean isAdmin = isAdminUser(user.getId());
boolean isPrimaryTask = false; Department publisherDept = resolvePublishingDepartment(user, dto.getPublisherDeptId(), isAdmin);
boolean isPrimaryTask = "primary_demand".equals(publisherDept.getDeptType());
if (!isAdmin) {
if (user.getDeptId() == null) {
throw new BusinessException(ResultCode.FORBIDDEN, "用户部门信息不完整");
}
var department = departmentService.getDepartmentById(user.getDeptId());
if (department == null) {
throw new BusinessException(ResultCode.FORBIDDEN, "用户部门不存在");
}
String deptType = department.getDeptType();
if (!"demand".equals(deptType) && !"primary_demand".equals(deptType)) {
throw new BusinessException(ResultCode.FORBIDDEN, "只有需求部门或一级需求部门可以发起任务");
}
// 判断是否为一级需求部门发起的任务
isPrimaryTask = "primary_demand".equals(deptType);
}
// 验证流水线模式 // 验证流水线模式
if (!"sequential".equals(dto.getPipelineMode()) && !"parallel".equals(dto.getPipelineMode())) { if (!"sequential".equals(dto.getPipelineMode()) && !"parallel".equals(dto.getPipelineMode())) {
@ -358,12 +320,12 @@ public class TaskService {
int totalScoreInt = totalScoreDecimal.intValue(); // 用于积分检查 int totalScoreInt = totalScoreDecimal.intValue(); // 用于积分检查
// 检查部门积分是否充足(管理员跳过积分检查) // 检查部门积分是否充足(管理员跳过积分检查)
if (!isAdmin && user.getDeptId() != null) { if (!isAdmin && publisherDept.getId() != null) {
if (!teamScorePoolService.checkBalance(user.getDeptId(), totalScoreInt)) { if (!teamScorePoolService.checkBalance(publisherDept.getId(), totalScoreInt)) {
throw new BusinessException(ResultCode.INSUFFICIENT_SCORE, "部门积分余额不足"); throw new BusinessException(ResultCode.INSUFFICIENT_SCORE, "部门积分余额不足");
} }
if (!teamScorePoolService.checkPeriodLimit(user.getDeptId(), totalScoreInt)) { if (!teamScorePoolService.checkPeriodLimit(publisherDept.getId(), totalScoreInt)) {
throw new BusinessException(ResultCode.SCORE_LIMIT_EXCEEDED, "超过本周期积分消耗限制"); throw new BusinessException(ResultCode.SCORE_LIMIT_EXCEEDED, "超过本周期积分消耗限制");
} }
} }
@ -378,7 +340,7 @@ public class TaskService {
task.setThirdPartyTaskNo(generateThirdPartyTaskNo()); task.setThirdPartyTaskNo(generateThirdPartyTaskNo());
task.setTitle(dto.getTitle()); task.setTitle(dto.getTitle());
task.setPublisherId(publisherId); task.setPublisherId(publisherId);
task.setPublisherDeptId(user.getDeptId()); task.setPublisherDeptId(publisherDept.getId());
task.setIsPipeline(1); task.setIsPipeline(1);
task.setPipelineMode(dto.getPipelineMode()); task.setPipelineMode(dto.getPipelineMode());
task.setScore(totalScoreDecimal); task.setScore(totalScoreDecimal);
@ -428,9 +390,9 @@ public class TaskService {
if (isPrimaryTask) { if (isPrimaryTask) {
task.setIsPrimaryTask(1); task.setIsPrimaryTask(1);
task.setPrimaryPublisherId(publisherId); task.setPrimaryPublisherId(publisherId);
task.setPrimaryPublisherDeptId(user.getDeptId()); task.setPrimaryPublisherDeptId(publisherDept.getId());
task.setDetailCompleted(0); // 明细未完善 task.setDetailCompleted(0); // 明细未完善
log.info("一级需求部门发起流水线任务: publisherId={}, deptId={}", publisherId, user.getDeptId()); log.info("一级需求部门发起流水线任务: publisherId={}, deptId={}", publisherId, publisherDept.getId());
} else { } else {
task.setIsPrimaryTask(0); task.setIsPrimaryTask(0);
task.setDetailCompleted(1); // 普通任务明细已完善 task.setDetailCompleted(1); // 普通任务明细已完善
@ -1318,6 +1280,62 @@ public class TaskService {
return user != null ? user.getDeptId() : null; return user != null ? user.getDeptId() : null;
} }
private Department resolvePublishingDepartment(User user, Long requestedDeptId, boolean isAdmin) {
if (user == null) {
throw new BusinessException(ResultCode.FORBIDDEN, "用户不存在");
}
List<Department> userDepartments = new java.util.ArrayList<>(userService.getUserDepartments(user.getId()));
if (user.getDeptId() != null && userDepartments.stream().noneMatch(dept -> user.getDeptId().equals(dept.getId()))) {
Department primaryDept = departmentService.getDepartmentById(user.getDeptId());
if (primaryDept != null) {
userDepartments.add(primaryDept);
}
}
List<Department> publishingDepartments = userDepartments.stream()
.filter(java.util.Objects::nonNull)
.filter(dept -> dept.getStatus() != null && dept.getStatus() == 1)
.filter(dept -> dept.getDeleted() == null || dept.getDeleted() == 0)
.filter(dept -> "demand".equals(dept.getDeptType()) || "primary_demand".equals(dept.getDeptType()))
.distinct()
.collect(Collectors.toList());
if (requestedDeptId != null) {
Department requestedDept = departmentService.getDepartmentById(requestedDeptId);
if (requestedDept == null) {
throw new BusinessException(ResultCode.PARAM_ERROR, "发起部门不存在");
}
if (!"demand".equals(requestedDept.getDeptType()) && !"primary_demand".equals(requestedDept.getDeptType())) {
throw new BusinessException(ResultCode.PARAM_ERROR, "发起部门必须是需求部门或一级需求部门");
}
if (!isAdmin && publishingDepartments.stream().noneMatch(dept -> requestedDeptId.equals(dept.getId()))) {
throw new BusinessException(ResultCode.FORBIDDEN, "您不属于所选发起部门");
}
return requestedDept;
}
if (user.getDeptId() != null) {
Department currentDept = departmentService.getDepartmentById(user.getDeptId());
if (currentDept != null && ("demand".equals(currentDept.getDeptType()) || "primary_demand".equals(currentDept.getDeptType()))) {
return currentDept;
}
if (isAdmin && currentDept != null) {
return currentDept;
}
}
if (publishingDepartments.size() == 1) {
return publishingDepartments.get(0);
}
if (publishingDepartments.isEmpty()) {
throw new BusinessException(ResultCode.FORBIDDEN, "只有需求部门或一级需求部门可以发起任务");
}
throw new BusinessException(ResultCode.PARAM_ERROR, "请先选择发起部门");
}
/** /**
* 获取我发布的任务(支持多维度筛选) * 获取我发布的任务(支持多维度筛选)
*/ */
@ -1823,7 +1841,7 @@ public class TaskService {
.filter(java.util.Objects::nonNull) .filter(java.util.Objects::nonNull)
.anyMatch(dept -> "demand".equals(dept.getDeptType()) .anyMatch(dept -> "demand".equals(dept.getDeptType())
&& dept.getStatus() != null && dept.getStatus() == 1 && dept.getStatus() != null && dept.getStatus() == 1
&& dept.getDeleted() != null && dept.getDeleted() == 0); && (dept.getDeleted() == null || dept.getDeleted() == 0));
if (isDemandDeptMemberForPrimaryTask) { if (isDemandDeptMemberForPrimaryTask) {
log.info("需求部门成员 {} 编辑一级需求任务 {}", userId, id); log.info("需求部门成员 {} 编辑一级需求任务 {}", userId, id);
} }
@ -1909,12 +1927,13 @@ public class TaskService {
// 检查部门积分是否充足(管理员跳过积分检查,一级需求部门无明细提交场景跳过) // 检查部门积分是否充足(管理员跳过积分检查,一级需求部门无明细提交场景跳过)
User user = userService.getUserById(userId); User user = userService.getUserById(userId);
if (!isAdmin && !allowPrimaryTaskWithoutItems && user.getDeptId() != null) { Department publisherDept = resolvePublishingDepartment(user, existTask.getPublisherDeptId(), isAdmin);
if (!teamScorePoolService.checkBalance(user.getDeptId(), totalScoreInt)) { if (!isAdmin && !allowPrimaryTaskWithoutItems && publisherDept.getId() != null) {
if (!teamScorePoolService.checkBalance(publisherDept.getId(), totalScoreInt)) {
throw new BusinessException(ResultCode.INSUFFICIENT_SCORE, "部门积分余额不足"); throw new BusinessException(ResultCode.INSUFFICIENT_SCORE, "部门积分余额不足");
} }
if (!teamScorePoolService.checkPeriodLimit(user.getDeptId(), totalScoreInt)) { if (!teamScorePoolService.checkPeriodLimit(publisherDept.getId(), totalScoreInt)) {
throw new BusinessException(ResultCode.SCORE_LIMIT_EXCEEDED, "超过本周期积分消耗限制"); throw new BusinessException(ResultCode.SCORE_LIMIT_EXCEEDED, "超过本周期积分消耗限制");
} }
} }

View File

@ -1190,6 +1190,7 @@ public class UserService {
return UserDepartmentVO.builder() return UserDepartmentVO.builder()
.deptId(dept.getId()) .deptId(dept.getId())
.deptName(dept.getDeptName()) .deptName(dept.getDeptName())
.deptType(dept.getDeptType())
.isPrimary(ud.getIsPrimary()) .isPrimary(ud.getIsPrimary())
.build(); .build();
} }
@ -1328,9 +1329,16 @@ public class UserService {
new LambdaQueryWrapper<UserDepartment>() new LambdaQueryWrapper<UserDepartment>()
.eq(UserDepartment::getUserId, userId) .eq(UserDepartment::getUserId, userId)
); );
return userDepts.stream() LinkedHashSet<Long> deptIds = userDepts.stream()
.map(UserDepartment::getDeptId) .map(UserDepartment::getDeptId)
.collect(Collectors.toList()); .collect(Collectors.toCollection(LinkedHashSet::new));
User user = userMapper.selectById(userId);
if (user != null && user.getDeptId() != null) {
deptIds.add(user.getDeptId());
}
return new ArrayList<>(deptIds);
} }
/** /**

View File

@ -19,6 +19,11 @@ public class UserDepartmentVO {
*/ */
private String deptName; private String deptName;
/**
* 部门类型:demand / receiving / primary_demand
*/
private String deptType;
/** /**
* 是否为主部门:0-否,1-是 * 是否为主部门:0-否,1-是
*/ */

View File

@ -43,9 +43,27 @@ export interface UserInfo {
avatar: string avatar: string
deptId: number deptId: number
deptName: string deptName: string
deptType?: string
departments?: UserDepartment[]
roleIds?: string // 角色ID列表(逗号分隔) roleIds?: string // 角色ID列表(逗号分隔)
roles: string[] roles: string[]
permissions: string[] permissions: string[]
isDepartmentLeader?: number | boolean
isAdmin?: number | boolean
managedDepartments?: ManagedDepartment[]
}
export interface UserDepartment {
deptId: number
deptName: string
deptType?: string
isPrimary?: number
}
export interface ManagedDepartment {
deptId: number
deptName: string
deptType: string
} }
/** /**
@ -94,4 +112,3 @@ export const refreshToken = () => {
`/auth/refresh` `/auth/refresh`
) )
} }

View File

@ -129,11 +129,13 @@ export interface PipelineTaskRequest {
title: string title: string
isPipeline: boolean isPipeline: boolean
pipelineMode: 'sequential' | 'parallel' pipelineMode: 'sequential' | 'parallel'
publisherDeptId?: number
items: Array<{ items: Array<{
taskTypeId: number taskTypeId: number
quantity: number quantity: number
sortOrder: number sortOrder: number
receiverId?: number // 指定接收人 receiverId?: number // 指定接收人
selectedDeptId?: number
}> }>
brandId?: number brandId?: number
categoryId?: number categoryId?: number

View File

@ -8,6 +8,25 @@
<div class="balance-label">团队积分余额</div> <div class="balance-label">团队积分余额</div>
<div class="balance-value">{{ teamScore }} 分</div> <div class="balance-value">{{ teamScore }} 分</div>
</div> </div>
<div v-if="availablePublishingDepartments.length > 0" class="publisher-dept-card">
<div class="publisher-dept-label">发起部门</div>
<a-select
v-model:value="selectedPublishingDeptId"
size="large"
class="publisher-dept-select"
:disabled="editMode || formData.isPrimaryTaskEdit || availablePublishingDepartments.length === 1"
:placeholder="availablePublishingDepartments.length > 1 ? '请选择发起部门' : '当前发起部门'"
>
<a-select-option
v-for="dept in availablePublishingDepartments"
:key="dept.deptId"
:value="dept.deptId"
>
{{ dept.deptName }}{{ dept.deptType === 'primary_demand' ? '(一级需求)' : '' }}
</a-select-option>
</a-select>
<div class="publisher-dept-tip">任务积分和审批流按当前发起部门计算</div>
</div>
<div class="balance-tip"> <div class="balance-tip">
<span class="tip-icon"> <span class="tip-icon">
<Icon name="info" size="sm" color="#31f08b" /> <Icon name="info" size="sm" color="#31f08b" />
@ -644,6 +663,7 @@ const loading = ref(false)
// 团队积分余额 // 团队积分余额
const teamScore = ref(0) const teamScore = ref(0)
const selectedPublishingDeptId = ref<number | undefined>(undefined)
// 判断是否是管理员(管理员跳过积分检查) // 判断是否是管理员(管理员跳过积分检查)
const isAdmin = computed(() => { const isAdmin = computed(() => {
@ -659,6 +679,54 @@ const isAdmin = computed(() => {
return false return false
}) })
interface PublishingDepartmentOption {
deptId: number
deptName: string
deptType: string
isPrimary?: number
}
const availablePublishingDepartments = computed<PublishingDepartmentOption[]>(() => {
const userInfo = authStore.userInfo
if (!userInfo) return []
const result: PublishingDepartmentOption[] = []
const seen = new Set<number>()
const departments = Array.isArray(userInfo.departments) ? userInfo.departments : []
departments.forEach((dept) => {
if (!dept?.deptId || seen.has(dept.deptId)) return
if (dept.deptType !== 'demand' && dept.deptType !== 'primary_demand') return
result.push({
deptId: dept.deptId,
deptName: dept.deptName,
deptType: dept.deptType,
isPrimary: dept.isPrimary
})
seen.add(dept.deptId)
})
if (
userInfo.deptId &&
!seen.has(userInfo.deptId) &&
(userInfo.deptType === 'demand' || userInfo.deptType === 'primary_demand')
) {
result.unshift({
deptId: userInfo.deptId,
deptName: userInfo.deptName,
deptType: userInfo.deptType,
isPrimary: 1
})
seen.add(userInfo.deptId)
}
return result
})
const activePublishingDept = computed(() => {
return availablePublishingDepartments.value.find(dept => dept.deptId === selectedPublishingDeptId.value)
})
// 任务子类型列表 // 任务子类型列表
const taskSubTypes = ref<TaskSubType[]>([]) const taskSubTypes = ref<TaskSubType[]>([])
@ -676,9 +744,7 @@ const primaryDeptConfig = ref({
// 判断当前用户是否是一级需求部门用户 // 判断当前用户是否是一级需求部门用户
const isPrimaryDeptUser = computed(() => { const isPrimaryDeptUser = computed(() => {
const userInfo = authStore.userInfo as any return activePublishingDept.value?.deptType === 'primary_demand'
if (!userInfo) return false
return userInfo.deptType === 'primary_demand'
}) })
// 判断是否应该显示任务明细区域 // 判断是否应该显示任务明细区域
@ -759,6 +825,37 @@ const formData = reactive({
timeLimit: undefined as number | undefined // 时效要求 timeLimit: undefined as number | undefined // 时效要求
}) })
const initializePublishingDept = (preferredDeptId?: number) => {
const departments = availablePublishingDepartments.value
if (!departments.length) {
selectedPublishingDeptId.value = undefined
return
}
if (preferredDeptId && departments.some(dept => dept.deptId === preferredDeptId)) {
selectedPublishingDeptId.value = preferredDeptId
return
}
if (selectedPublishingDeptId.value && departments.some(dept => dept.deptId === selectedPublishingDeptId.value)) {
return
}
const currentDeptId = authStore.userInfo?.deptId
const currentDeptType = authStore.userInfo?.deptType
if (
currentDeptId &&
(currentDeptType === 'demand' || currentDeptType === 'primary_demand') &&
departments.some(dept => dept.deptId === currentDeptId)
) {
selectedPublishingDeptId.value = currentDeptId
return
}
const primaryPublishingDept = departments.find(dept => dept.isPrimary === 1)
selectedPublishingDeptId.value = primaryPublishingDept?.deptId || departments[0].deptId
}
// 新条码输入框 // 新条码输入框
const newBarcodeInput = ref('') const newBarcodeInput = ref('')
@ -1503,6 +1600,7 @@ const handleSaveDraft = async () => {
title: formData.title, title: formData.title,
isPipeline: true, isPipeline: true,
pipelineMode: 'sequential', pipelineMode: 'sequential',
publisherDeptId: selectedPublishingDeptId.value,
items: validTaskTypes.map((item, index) => ({ items: validTaskTypes.map((item, index) => ({
taskTypeId: item.taskTypeId!, taskTypeId: item.taskTypeId!,
quantity: item.quantity || 1, quantity: item.quantity || 1,
@ -1558,6 +1656,11 @@ const handleSubmit = async () => {
// 验证表单 // 验证表单
await formRef.value.validate() await formRef.value.validate()
if (!isAdmin.value && !selectedPublishingDeptId.value) {
message.error('请选择发起部门')
return
}
// 一级需求部门用户必须上传预览图 // 一级需求部门用户必须上传预览图
if (isPrimaryDeptUser.value && !formData.previewImage) { if (isPrimaryDeptUser.value && !formData.previewImage) {
message.error('一级需求部门发起任务必须上传预览图') message.error('一级需求部门发起任务必须上传预览图')
@ -1646,6 +1749,7 @@ const handleSubmit = async () => {
title: formData.title, title: formData.title,
isPipeline: !isPrimaryDeptWithoutDetail, // 一级需求部门不填明细时,不标记为流水线任务 isPipeline: !isPrimaryDeptWithoutDetail, // 一级需求部门不填明细时,不标记为流水线任务
pipelineMode: 'sequential', // 固定为顺序流水线 pipelineMode: 'sequential', // 固定为顺序流水线
publisherDeptId: selectedPublishingDeptId.value,
items: validTaskTypes.map((item, index) => ({ items: validTaskTypes.map((item, index) => ({
taskTypeId: item.taskTypeId!, taskTypeId: item.taskTypeId!,
quantity: item.quantity, quantity: item.quantity,
@ -1675,6 +1779,7 @@ const handleSubmit = async () => {
// 一级需求部门不填写任务明细时,需要设置 isPipeline=true 来触发审核流程 // 一级需求部门不填写任务明细时,需要设置 isPipeline=true 来触发审核流程
const taskData = { const taskData = {
title: formData.title, title: formData.title,
publisherDeptId: selectedPublishingDeptId.value,
brandId: formData.brandId, brandId: formData.brandId,
platformId: formData.platformId, platformId: formData.platformId,
categoryId: formData.categoryId, categoryId: formData.categoryId,
@ -1714,6 +1819,7 @@ const handleSubmit = async () => {
// 任务明细将由需求部门在审核时填写 // 任务明细将由需求部门在审核时填写
const taskData = { const taskData = {
title: formData.title, title: formData.title,
publisherDeptId: selectedPublishingDeptId.value,
brandId: formData.brandId, brandId: formData.brandId,
platformId: formData.platformId, platformId: formData.platformId,
categoryId: formData.categoryId, categoryId: formData.categoryId,
@ -1800,13 +1906,13 @@ const loadTeamScore = async () => {
console.log('[loadTeamScore] 当前用户信息:', authStore.userInfo) console.log('[loadTeamScore] 当前用户信息:', authStore.userInfo)
// 确保用户信息是最新的 // 确保用户信息是最新的
if (!authStore.userInfo || !authStore.userInfo.deptId) { if (!authStore.userInfo) {
console.log('[loadTeamScore] 用户信息缺失或无部门ID,重新获取用户信息') console.log('[loadTeamScore] 用户信息缺失或无部门ID,重新获取用户信息')
await authStore.fetchUserInfo() await authStore.fetchUserInfo()
console.log('[loadTeamScore] 重新获取后的用户信息:', authStore.userInfo) console.log('[loadTeamScore] 重新获取后的用户信息:', authStore.userInfo)
} }
const deptId = authStore.userInfo?.deptId const deptId = selectedPublishingDeptId.value
console.log('[loadTeamScore] 部门ID:', deptId) console.log('[loadTeamScore] 部门ID:', deptId)
if (!deptId) { if (!deptId) {
@ -2190,6 +2296,7 @@ const loadTaskForEdit = async (taskId: number) => {
if (task) { if (task) {
console.log('加载任务数据:', task) console.log('加载任务数据:', task)
initializePublishingDept(task.publisherDeptId || task.primaryPublisherDeptId)
// 填充基本表单数据 // 填充基本表单数据
formData.title = task.title || '' formData.title = task.title || ''
@ -2314,6 +2421,7 @@ const loadTaskForEdit = async (taskId: number) => {
} }
console.log('任务数据加载成功,formData.taskTypes:', formData.taskTypes) console.log('任务数据加载成功,formData.taskTypes:', formData.taskTypes)
await loadTeamScore()
} }
} catch (error) { } catch (error) {
console.error('加载任务数据失败:', error) console.error('加载任务数据失败:', error)
@ -2403,6 +2511,7 @@ const loadPrimaryTaskForEdit = async () => {
} }
console.log('加载一级需求任务数据:', task) console.log('加载一级需求任务数据:', task)
initializePublishingDept(task.publisherDeptId || task.primaryPublisherDeptId)
// 设置编辑模式 // 设置编辑模式
editMode.value = true editMode.value = true
@ -2513,6 +2622,7 @@ const loadPrimaryTaskForEdit = async () => {
formData.primaryPublisherDeptId = task.primaryPublisherDeptId formData.primaryPublisherDeptId = task.primaryPublisherDeptId
message.info('请完善任务明细后提交') message.info('请完善任务明细后提交')
await loadTeamScore()
} catch (error) { } catch (error) {
console.error('加载一级需求任务失败:', error) console.error('加载一级需求任务失败:', error)
@ -2530,6 +2640,7 @@ onMounted(async () => {
try { try {
await authStore.fetchUserInfo() await authStore.fetchUserInfo()
console.log('用户信息已刷新:', authStore.userInfo) console.log('用户信息已刷新:', authStore.userInfo)
initializePublishingDept()
} catch (error) { } catch (error) {
console.error('刷新用户信息失败:', error) console.error('刷新用户信息失败:', error)
} }
@ -2561,6 +2672,22 @@ onMounted(async () => {
window.addEventListener('configUpdated', handleConfigUpdate as EventListener) window.addEventListener('configUpdated', handleConfigUpdate as EventListener)
}) })
watch(availablePublishingDepartments, (departments) => {
if (!departments.length) {
selectedPublishingDeptId.value = undefined
return
}
if (!selectedPublishingDeptId.value || !departments.some(dept => dept.deptId === selectedPublishingDeptId.value)) {
initializePublishingDept()
}
}, { immediate: true })
watch(selectedPublishingDeptId, async (deptId, oldDeptId) => {
if (deptId === oldDeptId) return
await loadTeamScore()
})
// 组件卸载 // 组件卸载
onUnmounted(() => { onUnmounted(() => {
window.removeEventListener('configUpdated', handleConfigUpdate as EventListener) window.removeEventListener('configUpdated', handleConfigUpdate as EventListener)
@ -2643,6 +2770,26 @@ onUnmounted(() => {
} }
} }
.publisher-dept-card {
margin-bottom: $space-md;
}
.publisher-dept-label {
margin-bottom: $space-xs;
font-size: $font-size-sm;
color: $text-secondary;
}
.publisher-dept-select {
width: 100%;
}
.publisher-dept-tip {
margin-top: $space-xs;
font-size: $font-size-xs;
color: $text-tertiary;
}
.time-estimate { .time-estimate {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;