feat: 任务发布类型配置控制 + 标题输入框只读

This commit is contained in:
Your Name 2026-01-05 14:01:24 +08:00
parent fc82aa0c36
commit 344d26589c
3 changed files with 222 additions and 3 deletions

View File

@ -230,6 +230,11 @@ public class SystemConfigService {
createConfigIfNotExists("navbar.action.checkin", "true", "navbar", "显示签到按钮", "是否在导航栏显示每日签到按钮", "boolean", 1);
createConfigIfNotExists("navbar.action.achievement", "true", "navbar", "显示成就按钮", "是否在导航栏显示成就中心按钮", "boolean", 1);
createConfigIfNotExists("navbar.action.settings", "true", "navbar", "显示设置按钮", "是否在导航栏显示设置按钮", "boolean", 1);
// 任务发布类型配置
createConfigIfNotExists("task.release_type.default", "true", "task", "显示默认模式按钮", "是否显示「默认模式」发布类型按钮", "boolean", 1);
createConfigIfNotExists("task.release_type.recruitment", "true", "task", "显示招募任务按钮", "是否显示「招募任务」发布类型按钮", "boolean", 1);
createConfigIfNotExists("task.release_type.assigned", "true", "task", "显示指定任务按钮", "是否显示「指定任务」发布类型按钮", "boolean", 1);
}
/**

View File

@ -25,12 +25,14 @@
:rules="formRules"
layout="vertical"
>
<!-- 任务标题(自动生成) -->
<!-- 任务标题(自动生成,不可编辑) -->
<a-form-item label="任务标题" name="title" required>
<a-input
v-model:value="formData.title"
placeholder="填写下方信息后自动生成标题"
size="large"
disabled
class="auto-generated-title"
/>
<div class="title-auto-tip">
<Icon name="info" size="xs" style="margin-right: 4px;" />
@ -329,6 +331,7 @@
<a-form-item label="任务发布类型" name="releaseType" required>
<div class="release-type-buttons">
<button
v-if="releaseTypeConfig.default"
type="button"
:class="['release-type-button', { active: formData.releaseType === 'default' }]"
@click="formData.releaseType = 'default'"
@ -345,8 +348,9 @@
</div>
</button>
<!-- 招募任务和指定任务模式 -->
<!-- 招募任务模式 -->
<button
v-if="releaseTypeConfig.recruitment"
type="button"
:class="['release-type-button', { active: formData.releaseType === 'recruitment' }]"
@click="formData.releaseType = 'recruitment'"
@ -363,7 +367,9 @@
</div>
</button>
<!-- 指定任务模式 -->
<button
v-if="releaseTypeConfig.assigned"
type="button"
:class="['release-type-button', { active: formData.releaseType === 'assigned' }]"
@click="formData.releaseType = 'assigned'"
@ -427,6 +433,7 @@ import * as userApi from '@/api/user'
import * as taskApi from '@/api/task'
import * as configApi from '@/api/config'
import * as uploadApi from '@/api/upload'
import { getSystemConfigsMapByGroup } from '@/api/system'
import { uploadFilesToS3 } from '@/api/file'
import type { FormInstance } from 'ant-design-vue'
import type { DemandType, Brand, Platform, Category, TaskSubType } from '@/api/config'
@ -471,6 +478,13 @@ const isAdmin = computed(() => {
// 任务子类型列表
const taskSubTypes = ref<TaskSubType[]>([])
// 发布类型配置(控制哪些按钮显示)
const releaseTypeConfig = ref({
default: true,
recruitment: true,
assigned: true
})
// 文件上传相关
const fileList = ref<UploadFile[]>([])
const uploadProgress = ref(0)
@ -1269,6 +1283,32 @@ const loadTaskForEdit = async (taskId: number) => {
}
}
// 加载发布类型配置
const loadReleaseTypeConfig = async () => {
try {
const res = await getSystemConfigsMapByGroup('task')
if (res.data) {
releaseTypeConfig.value = {
default: res.data['task.release_type.default'] !== 'false',
recruitment: res.data['task.release_type.recruitment'] !== 'false',
assigned: res.data['task.release_type.assigned'] !== 'false'
}
// 如果当前选择的类型被禁用,自动切换到第一个可用的类型
if (!releaseTypeConfig.value[formData.releaseType as keyof typeof releaseTypeConfig.value]) {
if (releaseTypeConfig.value.default) {
formData.releaseType = 'default'
} else if (releaseTypeConfig.value.recruitment) {
formData.releaseType = 'recruitment'
} else if (releaseTypeConfig.value.assigned) {
formData.releaseType = 'assigned'
}
}
}
} catch (error) {
console.error('加载发布类型配置失败:', error)
}
}
// 组件挂载
onMounted(async () => {
// 先刷新用户信息,确保部门信息最新
@ -1283,7 +1323,8 @@ onMounted(async () => {
await Promise.all([
loadConfigData(),
loadTeamScore(),
loadTaskSubTypes()
loadTaskSubTypes(),
loadReleaseTypeConfig()
])
// 检查是否是编辑模式
@ -1812,6 +1853,20 @@ onUnmounted(() => {
align-items: center;
}
// 自动生成的标题输入框样式
.auto-generated-title {
:deep(.ant-input-disabled) {
background: rgba(49, 240, 139, 0.05) !important;
border-color: rgba(49, 240, 139, 0.3) !important;
color: $text-primary !important;
cursor: default;
&::placeholder {
color: $text-tertiary;
}
}
}
// 预览图上传区域
.preview-upload-area {
.upload-button {

View File

@ -912,6 +912,85 @@
</div>
</a-tab-pane>
<!-- 任务发布配置 -->
<a-tab-pane key="task-release" tab="任务发布配置">
<div class="settings-section">
<div class="section-header">
<h2 class="section-title">任务发布类型配置</h2>
<p class="section-description">管理发起任务页面中可用的发布类型选项</p>
</div>
<a-form :model="taskReleaseConfig" layout="vertical" class="navbar-config-form">
<a-divider orientation="left">
<Icon name="settings" size="sm" style="margin-right: 8px;" />
发布类型按钮
</a-divider>
<div class="config-grid">
<div class="config-item">
<div class="config-item-header">
<Icon name="arrowPath" size="md" color="#31f08b" />
<span class="config-item-title">默认模式</span>
</div>
<div class="config-item-desc">系统自动分配给主管,由主管负责分配</div>
<a-switch
v-model:checked="taskReleaseConfig.default"
checked-children="显示"
un-checked-children="隐藏"
/>
</div>
<div class="config-item">
<div class="config-item-header">
<Icon name="bell" size="md" color="#31f08b" />
<span class="config-item-title">招募任务</span>
</div>
<div class="config-item-desc">发布到任务大厅,设计师可自行抢单</div>
<a-switch
v-model:checked="taskReleaseConfig.recruitment"
checked-children="显示"
un-checked-children="隐藏"
/>
</div>
<div class="config-item">
<div class="config-item-header">
<Icon name="star" size="md" color="#31f08b" />
<span class="config-item-title">指定任务</span>
</div>
<div class="config-item-desc">指定特定设计师接收任务</div>
<a-switch
v-model:checked="taskReleaseConfig.assigned"
checked-children="显示"
un-checked-children="隐藏"
/>
</div>
</div>
<a-alert
message="提示"
description="至少需要保留一个发布类型。如果全部关闭,系统将自动启用默认模式。"
type="info"
show-icon
style="margin-top: 16px; margin-bottom: 16px;"
/>
<a-form-item style="margin-top: 32px;">
<a-space>
<a-button type="primary" @click="handleSaveTaskReleaseConfig" :loading="savingTaskReleaseConfig">
<template #icon><Icon name="check" size="sm" /></template>
保存配置
</a-button>
<a-button @click="handleResetTaskReleaseConfig">
<template #icon><Icon name="refresh" size="sm" /></template>
恢复默认
</a-button>
</a-space>
</a-form-item>
</a-form>
</div>
</a-tab-pane>
<!-- S3存储配置 -->
<a-tab-pane key="s3-config" tab="S3存储配置">
<div class="settings-section">
@ -2780,6 +2859,74 @@ const handleResetNavbarConfig = () => {
})
}
// ==================== 任务发布类型配置 ====================
const taskReleaseConfig = ref({
default: true,
recruitment: true,
assigned: true
})
const savingTaskReleaseConfig = ref(false)
// 加载任务发布类型配置
const loadTaskReleaseConfig = async () => {
try {
const response = await getSystemConfigsByGroup('task')
const configs = response.data || []
const defaultConfig = configs.find((c: any) => c.configKey === 'task.release_type.default')
const recruitmentConfig = configs.find((c: any) => c.configKey === 'task.release_type.recruitment')
const assignedConfig = configs.find((c: any) => c.configKey === 'task.release_type.assigned')
taskReleaseConfig.value = {
default: defaultConfig?.configValue !== 'false',
recruitment: recruitmentConfig?.configValue !== 'false',
assigned: assignedConfig?.configValue !== 'false'
}
} catch (error) {
console.error('加载任务发布类型配置失败:', error)
}
}
// 保存任务发布类型配置
const handleSaveTaskReleaseConfig = async () => {
// 检查至少保留一个选项
if (!taskReleaseConfig.value.default && !taskReleaseConfig.value.recruitment && !taskReleaseConfig.value.assigned) {
message.warning('至少需要保留一个发布类型,已自动启用默认模式')
taskReleaseConfig.value.default = true
}
savingTaskReleaseConfig.value = true
try {
await batchUpdateSystemConfigs({
'task.release_type.default': taskReleaseConfig.value.default.toString(),
'task.release_type.recruitment': taskReleaseConfig.value.recruitment.toString(),
'task.release_type.assigned': taskReleaseConfig.value.assigned.toString()
})
message.success('任务发布类型配置保存成功')
} catch (error: any) {
message.error(error.message || '保存失败')
} finally {
savingTaskReleaseConfig.value = false
}
}
// 恢复默认任务发布类型配置
const handleResetTaskReleaseConfig = () => {
Modal.confirm({
title: '确认恢复默认配置?',
content: '此操作将显示所有发布类型选项',
onOk: async () => {
taskReleaseConfig.value = {
default: true,
recruitment: true,
assigned: true
}
await handleSaveTaskReleaseConfig()
}
})
}
// 加载网站设置
const loadSiteSettings = async () => {
loadingSiteSettings.value = true
@ -2948,6 +3095,8 @@ onMounted(() => {
loadSiteSettings()
// 加载钉钉配置
loadDingTalkConfig()
// 加载任务发布类型配置
loadTaskReleaseConfig()
})
// S3配置相关方法
@ -3820,6 +3969,8 @@ watch(activeTab, (value) => {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 8px;
padding: 16px 20px;
background: $bg-tertiary;
border: 1px solid $border-primary;
@ -3842,6 +3993,14 @@ watch(activeTab, (value) => {
font-weight: 500;
}
}
.config-item-desc {
width: 100%;
color: $text-secondary;
font-size: 12px;
margin-top: -4px;
padding-left: 36px;
}
}
.section-description {