You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
929 lines
25 KiB
929 lines
25 KiB
const app = getApp<IAppOption>() |
|
|
|
const DRAFT_KEY = 'actAdd:draft' |
|
|
|
interface ILevelItem { |
|
id: number |
|
name: string |
|
code: string |
|
sort: number |
|
} |
|
|
|
interface ICategoryItem { |
|
id: number |
|
name: string |
|
code: string |
|
icon: string |
|
sort: number |
|
isEnabled: number |
|
} |
|
|
|
interface ITagItem { |
|
id: number |
|
name: string |
|
sort: number |
|
activityCount: number |
|
} |
|
|
|
interface AgendaItem { |
|
agendaTime: string |
|
title: string |
|
description: string |
|
sort: number |
|
} |
|
|
|
Page({ |
|
data: { |
|
currentStep: 1, |
|
steps: [ |
|
{ label: '基本信息', field: 'basic' }, |
|
{ label: '报名签到设置', field: 'signup' }, |
|
{ label: '活动议程', field: 'agenda' }, |
|
], |
|
|
|
// 步骤1 基本信息 |
|
coverImageList: [] as Array<{ uid: string; url: string; type: string; name: string; size: number }>, |
|
title: '', |
|
type: 1, |
|
typeOptions: [ |
|
{ id: 1, name: '讲座' }, |
|
{ id: 2, name: '比赛' }, |
|
{ id: 3, name: '社团' }, |
|
{ id: 4, name: '志愿' }, |
|
{ id: 5, name: '文体' }, |
|
{ id: 6, name: '其他' }, |
|
], |
|
typeOther: '', |
|
summary: '', |
|
startTime: '', |
|
endTime: '', |
|
detail: '', |
|
detailImages: [] as string[], |
|
location: '', |
|
organizer: '', |
|
contactName: '', |
|
contactPhone: '', |
|
|
|
// 活动等级 |
|
levelList: [] as ILevelItem[], |
|
levelId: 0, |
|
|
|
// 活动分类 |
|
categoryList: [] as ICategoryItem[], |
|
selectedCategoryIds: [] as number[], |
|
categoryTags: [] as Array<{ id: number; name: string; isSelected: boolean }>, // 用于显示选中状态 |
|
|
|
// 活动标签 |
|
tagList: [] as ITagItem[], |
|
selectedTagIds: [] as number[], |
|
tagTags: [] as Array<{ id: number; name: string; isSelected: boolean }>, // 用于显示选中状态 |
|
|
|
// 步骤2 报名签到设置 |
|
needRegister: true, |
|
registerStartTime: '', |
|
registerEndTime: '', |
|
registerLimit: 'unlimited', |
|
registerLimitCount: '', |
|
registerCondition: '', |
|
|
|
checkinWay: 'dynamic', |
|
checkinStartTime: '', |
|
checkinEndTime: '', |
|
|
|
// datetime-picker 相关 |
|
showDatePicker: false, |
|
datePickerField: '', // 当前选择的时间字段 |
|
datePickerValue: new Date().getTime(), // 当前选择的日期时间戳 |
|
datePickerMinDate: new Date(2020, 0, 1).getTime(), // 最小日期 |
|
datePickerMaxDate: new Date(2030, 11, 31).getTime(), // 最大日期 |
|
|
|
// 步骤3 活动议程 |
|
agendas: [{ agendaTime: '', title: '', description: '', sort: 0 }] as AgendaItem[], |
|
nextAgendaId: 2, |
|
|
|
// 议程时间选择器相关 |
|
showAgendaDatePicker: false, |
|
agendaDatePickerIndex: -1, // 当前编辑的议程索引 |
|
agendaDatePickerValue: new Date().getTime(), |
|
|
|
// 提交状态 |
|
submitting: false, |
|
|
|
// 编辑模式:传入的活动ID |
|
editId: 0, |
|
isEdit: false, |
|
}, |
|
|
|
async onLoad(options: any) { |
|
await app.waitLogin({ type: 1 }) |
|
|
|
// 判断是否为编辑模式 |
|
const editId = options?.id ? Number(options.id) : 0 |
|
const isEdit = editId > 0 |
|
this.setData({ editId, isEdit }) |
|
|
|
// 设置导航栏标题 |
|
wx.setNavigationBarTitle({ title: isEdit ? '编辑活动' : '创建活动' }) |
|
|
|
try { |
|
await Promise.all([this.fetchLevelList(), this.fetchCategoryList(), this.fetchTagList()]) |
|
} catch (err) { |
|
console.error('初始化数据失败:', err) |
|
} |
|
|
|
// 编辑模式:从接口回显数据,忽略本地草稿 |
|
if (isEdit) { |
|
await this.fetchActivityDetail(editId) |
|
return |
|
} |
|
|
|
// 新建模式:检查是否有本地草稿 |
|
try { |
|
const draft = wx.getStorageSync(DRAFT_KEY) as any |
|
if (draft && Object.keys(draft).length) { |
|
wx.showModal({ |
|
title: '检测到未完成的活动', |
|
content: '上次未完成的表单已保存,是否继续编辑?', |
|
confirmText: '继续编辑', |
|
cancelText: '重新开始', |
|
success: (res) => { |
|
if (res.confirm) { |
|
this.restoreDraft(draft) |
|
} else { |
|
this.clearDraft() |
|
} |
|
}, |
|
}) |
|
} |
|
} catch (err) { |
|
console.error('读取本地草稿失败:', err) |
|
} |
|
}, |
|
|
|
// 获取活动详情并回显到表单 |
|
async fetchActivityDetail(id: number) { |
|
wx.showLoading({ title: '加载中...' }) |
|
try { |
|
const res = await wx.ajax({ |
|
url: `/activity/detail?id=${id}`, |
|
method: 'GET', |
|
data: {}, |
|
}) |
|
if (!res) return |
|
|
|
// 签到方式映射 |
|
const checkinWayMap: Record<number, string> = { 1: 'dynamic', 2: 'fixed', 3: 'none' } |
|
|
|
// 封面图片转为本地上传格式 |
|
const coverImageList = (res.mainImages || []).map((url: string, index: number) => ({ |
|
uid: `cover_${index}`, |
|
url, |
|
type: 'image', |
|
name: url.split('/').pop() || '', |
|
size: 0, |
|
status: 'success', |
|
progress: 100, |
|
})) |
|
|
|
// 议程数据 |
|
const agendas = (res.agendas || []).map((item: any, index: number) => ({ |
|
agendaTime: item.agendaTime || `${item.agendaDate || ''} ${item.agendaTime || ''}`, |
|
title: item.title || '', |
|
description: item.description || '', |
|
sort: index, |
|
})) |
|
|
|
// 如果没有议程,提供一个空行 |
|
if (agendas.length === 0) { |
|
agendas.push({ agendaTime: '', title: '', description: '', sort: 0 }) |
|
} |
|
|
|
// 分类和标签 |
|
const selectedCategoryIds = res.categoryIds || [] |
|
const selectedTagIds = (res.tags || []).map((t: any) => (typeof t === 'object' ? t.id : t)) |
|
|
|
// 报名设置 |
|
const needRegister = res.regType === 1 |
|
const registerLimit = res.quota > 0 ? 'limited' : 'unlimited' |
|
const registerLimitCount = res.quota > 0 ? String(res.quota) : '' |
|
|
|
this.setData({ |
|
coverImageList, |
|
title: res.name || '', |
|
type: res.type || 1, |
|
typeOther: res.typeOther || '', |
|
summary: res.summary || '', |
|
startTime: res.startAt || '', |
|
endTime: res.endAt || '', |
|
detail: res.description || '', |
|
detailImages: res.detailImages || [], |
|
location: res.location || '', |
|
organizer: res.organizer || '', |
|
contactName: res.contactName || '', |
|
contactPhone: res.contactPhone || '', |
|
levelId: res.levelId || 0, |
|
selectedCategoryIds, |
|
selectedTagIds, |
|
needRegister, |
|
registerStartTime: res.regStartAt || '', |
|
registerEndTime: res.regEndAt || '', |
|
registerLimit, |
|
registerLimitCount, |
|
registerCondition: res.regCondition || '', |
|
checkinWay: checkinWayMap[res.checkinType] || 'dynamic', |
|
checkinStartTime: res.checkinStartTime || '', |
|
checkinEndTime: res.checkinEndTime || '', |
|
agendas, |
|
}) |
|
|
|
// 重建标签选中状态 |
|
const categoryTags = (this.data.categoryList || []).map((item: ICategoryItem) => ({ |
|
id: item.id, |
|
name: item.name, |
|
isSelected: selectedCategoryIds.includes(item.id), |
|
})) |
|
const tagTags = (this.data.tagList || []).map((item: ITagItem) => ({ |
|
id: item.id, |
|
name: item.name, |
|
isSelected: selectedTagIds.includes(item.id), |
|
})) |
|
this.setData({ categoryTags, tagTags }) |
|
} catch (err) { |
|
console.error('获取活动详情失败:', err) |
|
wx.showToast({ title: '加载失败', icon: 'none' }) |
|
} finally { |
|
wx.hideLoading() |
|
} |
|
}, |
|
|
|
// ========== 草稿管理 ========== |
|
buildDraft(partial: Record<string, any> = {}) { |
|
const keys = [ |
|
'currentStep', |
|
'coverImageList', |
|
'title', |
|
'type', |
|
'typeOther', |
|
'summary', |
|
'startTime', |
|
'endTime', |
|
'detail', |
|
'detailImages', |
|
'location', |
|
'organizer', |
|
'contactName', |
|
'contactPhone', |
|
'levelId', |
|
'selectedCategoryIds', |
|
'selectedTagIds', |
|
'needRegister', |
|
'registerStartTime', |
|
'registerEndTime', |
|
'registerLimit', |
|
'registerLimitCount', |
|
'registerCondition', |
|
'checkinWay', |
|
'checkinStartTime', |
|
'checkinEndTime', |
|
'agendas', |
|
] |
|
|
|
const draft: Record<string, any> = {} |
|
keys.forEach((k) => { |
|
if (Object.prototype.hasOwnProperty.call(partial, k)) { |
|
draft[k] = partial[k] |
|
} else { |
|
draft[k] = (this.data as any)[k] |
|
} |
|
}) |
|
return draft |
|
}, |
|
|
|
saveDraft(partial: Record<string, any> = {}) { |
|
try { |
|
const draft = this.buildDraft(partial) |
|
wx.setStorageSync(DRAFT_KEY, draft) |
|
} catch (err) { |
|
console.error('保存草稿失败:', err) |
|
} |
|
}, |
|
|
|
clearDraft() { |
|
try { |
|
wx.removeStorageSync(DRAFT_KEY) |
|
} catch { |
|
/* ignore */ |
|
} |
|
}, |
|
|
|
restoreDraft(draft: Record<string, any>) { |
|
if (!draft) return |
|
const safeDraft = { ...draft } |
|
safeDraft.coverImageList = safeDraft.coverImageList || [] |
|
safeDraft.detailImages = safeDraft.detailImages || [] |
|
safeDraft.agendas = safeDraft.agendas || [] |
|
safeDraft.selectedCategoryIds = safeDraft.selectedCategoryIds || [] |
|
safeDraft.selectedTagIds = safeDraft.selectedTagIds || [] |
|
|
|
this.setData(safeDraft) |
|
|
|
// 重建标签选中状态显示 |
|
const categoryTags = (this.data.categoryList || []).map((item: ICategoryItem) => ({ |
|
id: item.id, |
|
name: item.name, |
|
isSelected: safeDraft.selectedCategoryIds.includes(item.id), |
|
})) |
|
const tagTags = (this.data.tagList || []).map((item: ITagItem) => ({ |
|
id: item.id, |
|
name: item.name, |
|
isSelected: safeDraft.selectedTagIds.includes(item.id), |
|
})) |
|
this.setData({ categoryTags, tagTags }) |
|
}, |
|
|
|
setAndSave(patch: Record<string, any>) { |
|
this.setData(patch) |
|
// 编辑模式下不保存本地草稿缓存 |
|
if (!this.data.isEdit) { |
|
this.saveDraft(patch) |
|
} |
|
}, |
|
|
|
// 获取活动等级列表 |
|
async fetchLevelList() { |
|
try { |
|
const res = await wx.ajax({ |
|
url: '/activity-level/list', |
|
method: 'GET', |
|
data: {}, |
|
}) |
|
if (res && res.list) { |
|
this.setData({ levelList: res.list }) |
|
} |
|
} catch (err) { |
|
console.error('获取活动等级列表失败:', err) |
|
} |
|
}, |
|
|
|
// 获取活动分类列表 |
|
async fetchCategoryList() { |
|
try { |
|
const res = await wx.ajax({ |
|
url: '/activity-category/list', |
|
method: 'GET', |
|
data: {}, |
|
}) |
|
if (res && res.list) { |
|
const { selectedCategoryIds } = this.data |
|
const categoryTags = res.list.map((item: ICategoryItem) => ({ |
|
id: item.id, |
|
name: item.name, |
|
isSelected: selectedCategoryIds.includes(item.id), |
|
})) |
|
this.setData({ |
|
categoryList: res.list, |
|
categoryTags, |
|
}) |
|
} |
|
} catch (err) { |
|
console.error('获取活动分类列表失败:', err) |
|
} |
|
}, |
|
|
|
// 获取活动标签列表 |
|
async fetchTagList() { |
|
try { |
|
const res = await wx.ajax({ |
|
url: '/activity-tag/list', |
|
method: 'GET', |
|
data: {}, |
|
}) |
|
if (res && res.list) { |
|
const { selectedTagIds } = this.data |
|
const tagTags = res.list.map((item: ITagItem) => ({ |
|
id: item.id, |
|
name: item.name, |
|
isSelected: selectedTagIds.includes(item.id), |
|
})) |
|
this.setData({ |
|
tagList: res.list, |
|
tagTags, |
|
}) |
|
} |
|
} catch (err) { |
|
console.error('获取活动标签列表失败:', err) |
|
} |
|
}, |
|
|
|
// ========== 步骤切换 ========== |
|
goStep(step: number) { |
|
if (step < 1 || step > 4) return |
|
this.setAndSave({ currentStep: step }) |
|
}, |
|
|
|
// 验证当前步骤的必填项 |
|
validateCurrentStep(): boolean { |
|
const { |
|
currentStep, |
|
coverImageList, |
|
title, |
|
startTime, |
|
endTime, |
|
location, |
|
needRegister, |
|
registerStartTime, |
|
registerEndTime, |
|
checkinWay, |
|
checkinStartTime, |
|
checkinEndTime, |
|
} = this.data |
|
|
|
// 步骤1:基本信息 |
|
if (currentStep === 1) { |
|
if (!coverImageList.length) { |
|
wx.showToast({ title: '请上传活动头图', icon: 'none' }) |
|
return false |
|
} |
|
if (!title.trim()) { |
|
wx.showToast({ title: '请输入活动标题', icon: 'none' }) |
|
return false |
|
} |
|
if (!startTime) { |
|
wx.showToast({ title: '请选择活动开始时间', icon: 'none' }) |
|
return false |
|
} |
|
if (!endTime) { |
|
wx.showToast({ title: '请选择活动结束时间', icon: 'none' }) |
|
return false |
|
} |
|
if (!location.trim()) { |
|
wx.showToast({ title: '请输入活动地点', icon: 'none' }) |
|
return false |
|
} |
|
} |
|
|
|
// 步骤2:报名签到设置 |
|
if (currentStep === 2) { |
|
if (needRegister) { |
|
if (!registerStartTime) { |
|
wx.showToast({ title: '请选择报名开始时间', icon: 'none' }) |
|
return false |
|
} |
|
if (!registerEndTime) { |
|
wx.showToast({ title: '请选择报名截止时间', icon: 'none' }) |
|
return false |
|
} |
|
} |
|
|
|
// 签到时间校验(动态二维码或固定二维码时必填) |
|
if (checkinWay !== 'none') { |
|
if (!checkinStartTime) { |
|
wx.showToast({ title: '请选择签到开始时间', icon: 'none' }) |
|
return false |
|
} |
|
if (!checkinEndTime) { |
|
wx.showToast({ title: '请选择签到结束时间', icon: 'none' }) |
|
return false |
|
} |
|
} |
|
} |
|
|
|
// 步骤3:活动议程(可选,不做必填验证) |
|
if (currentStep === 3) { |
|
// 议程可选,不做验证 |
|
} |
|
|
|
return true |
|
}, |
|
|
|
onNextStep() { |
|
// 先验证当前步骤 |
|
if (!this.validateCurrentStep()) { |
|
return |
|
} |
|
|
|
const next = this.data.currentStep + 1 |
|
if (next <= 4) this.setAndSave({ currentStep: next }) |
|
}, |
|
|
|
onPrevStep() { |
|
const prev = this.data.currentStep - 1 |
|
if (prev >= 1) this.setAndSave({ currentStep: prev }) |
|
}, |
|
|
|
// ========== 图片上传 ========== |
|
// 上传成功后,直接添加到列表(maxCount=1,只保留一个) |
|
onCoverSuccess(e: WechatMiniprogram.CustomEvent) { |
|
const { file } = e.detail |
|
this.setAndSave({ coverImageList: [file] }) |
|
}, |
|
|
|
// 上传失败后,显示错误 |
|
onCoverError(_e: WechatMiniprogram.CustomEvent) { |
|
wx.showToast({ title: '上传失败,请重试', icon: 'none' }) |
|
}, |
|
|
|
// 删除封面图片 |
|
handleDelCover() { |
|
this.setAndSave({ coverImageList: [] }) |
|
}, |
|
|
|
onDetailImageSuccess(e: WechatMiniprogram.CustomEvent) { |
|
const { urls } = e.detail |
|
this.setAndSave({ detailImages: urls }) |
|
}, |
|
|
|
// ========== 输入绑定 ========== |
|
onInputChange(e: WechatMiniprogram.Input) { |
|
const { field } = e.currentTarget.dataset |
|
this.setAndSave({ [field]: e.detail.value }) |
|
}, |
|
|
|
onTextareaChange(e: WechatMiniprogram.TextareaInput) { |
|
const { field } = e.currentTarget.dataset |
|
this.setAndSave({ [field]: e.detail.value }) |
|
}, |
|
|
|
// ========== 时间选择 ========== |
|
// 格式化日期时间 |
|
formatDateTime(timestamp: number): string { |
|
const date = new Date(timestamp) |
|
const year = date.getFullYear() |
|
const month = String(date.getMonth() + 1).padStart(2, '0') |
|
const day = String(date.getDate()).padStart(2, '0') |
|
const hours = String(date.getHours()).padStart(2, '0') |
|
const minutes = String(date.getMinutes()).padStart(2, '0') |
|
return `${year}-${month}-${day} ${hours}:${minutes}` |
|
}, |
|
|
|
// 打开时间选择器 |
|
onOpenDatePicker(e: WechatMiniprogram.TouchEvent) { |
|
const { field } = e.currentTarget.dataset |
|
const currentValue = (this.data as any)[field] || '' |
|
|
|
// 根据当前值设置 picker 的初始值 |
|
let pickerValue = new Date().getTime() |
|
if (currentValue) { |
|
const parsedDate = new Date(currentValue.replace(/-/g, '/')) |
|
if (!Number.isNaN(parsedDate.getTime())) { |
|
pickerValue = parsedDate.getTime() |
|
} |
|
} |
|
|
|
this.setData({ |
|
showDatePicker: true, |
|
datePickerField: field, |
|
datePickerValue: pickerValue, |
|
}) |
|
}, |
|
|
|
// 关闭时间选择器 |
|
onCloseDatePicker() { |
|
this.setData({ showDatePicker: false }) |
|
}, |
|
|
|
// 确认时间选择 |
|
onConfirmDatePicker(e: WechatMiniprogram.CustomEvent) { |
|
const { datePickerField } = this.data |
|
const timestamp = e.detail |
|
const formattedTime = this.formatDateTime(timestamp) |
|
|
|
this.setAndSave({ |
|
showDatePicker: false, |
|
[datePickerField]: formattedTime, |
|
}) |
|
}, |
|
|
|
// ========== 活动类型选择 ========== |
|
onSelectType(e: WechatMiniprogram.TouchEvent) { |
|
const { value } = e.currentTarget.dataset |
|
this.setAndSave({ type: value }) |
|
}, |
|
|
|
// ========== 活动等级选择 ========== |
|
onSelectLevel(e: WechatMiniprogram.TouchEvent) { |
|
const { id } = e.currentTarget.dataset |
|
this.setAndSave({ levelId: id }) |
|
}, |
|
|
|
// ========== 活动分类选择(多选) ========== |
|
onSelectCategory(e: WechatMiniprogram.TouchEvent) { |
|
const { id } = e.currentTarget.dataset |
|
let { selectedCategoryIds, categoryTags } = this.data |
|
|
|
const index = selectedCategoryIds.indexOf(id) |
|
if (index > -1) { |
|
selectedCategoryIds = selectedCategoryIds.filter((item) => item !== id) |
|
} else { |
|
selectedCategoryIds = [...selectedCategoryIds, id] |
|
} |
|
|
|
categoryTags = categoryTags.map((item) => ({ |
|
...item, |
|
isSelected: selectedCategoryIds.includes(item.id), |
|
})) |
|
|
|
this.setAndSave({ selectedCategoryIds, categoryTags }) |
|
}, |
|
|
|
// ========== 活动标签选择(多选) ========== |
|
onSelectTag(e: WechatMiniprogram.TouchEvent) { |
|
const { id } = e.currentTarget.dataset |
|
let { selectedTagIds, tagTags } = this.data |
|
|
|
const index = selectedTagIds.indexOf(id) |
|
if (index > -1) { |
|
selectedTagIds = selectedTagIds.filter((item) => item !== id) |
|
} else { |
|
selectedTagIds = [...selectedTagIds, id] |
|
} |
|
|
|
tagTags = tagTags.map((item) => ({ |
|
...item, |
|
isSelected: selectedTagIds.includes(item.id), |
|
})) |
|
|
|
this.setAndSave({ selectedTagIds, tagTags }) |
|
}, |
|
|
|
// ========== 议程管理 ========== |
|
onAddAgenda() { |
|
const agendas = this.data.agendas |
|
agendas.push({ |
|
agendaTime: '', |
|
title: '', |
|
description: '', |
|
sort: agendas.length, |
|
}) |
|
this.setAndSave({ agendas }) |
|
}, |
|
|
|
onRemoveAgenda(e: WechatMiniprogram.TouchEvent) { |
|
const { index } = e.currentTarget.dataset |
|
const agendas = this.data.agendas.filter((_, i) => i !== index) |
|
this.setAndSave({ agendas }) |
|
}, |
|
|
|
onAgendaInput(e: WechatMiniprogram.Input | WechatMiniprogram.TextareaInput) { |
|
const { index, field } = e.currentTarget.dataset |
|
const agendas = this.data.agendas |
|
agendas[index][field] = e.detail.value |
|
this.setAndSave({ agendas }) |
|
}, |
|
|
|
// 打开议程时间选择器 |
|
onOpenAgendaDatePicker(e: WechatMiniprogram.TouchEvent) { |
|
const { index } = e.currentTarget.dataset |
|
const agenda = this.data.agendas[index] |
|
const currentValue = agenda.agendaTime || '' |
|
|
|
let pickerValue = new Date().getTime() |
|
if (currentValue) { |
|
const parsedDate = new Date(currentValue.replace(/-/g, '/')) |
|
if (!Number.isNaN(parsedDate.getTime())) { |
|
pickerValue = parsedDate.getTime() |
|
} |
|
} |
|
|
|
this.setData({ |
|
showAgendaDatePicker: true, |
|
agendaDatePickerIndex: index, |
|
agendaDatePickerValue: pickerValue, |
|
}) |
|
}, |
|
|
|
// 关闭议程时间选择器 |
|
onCloseAgendaDatePicker() { |
|
this.setData({ showAgendaDatePicker: false }) |
|
}, |
|
|
|
// 确认议程时间选择 |
|
onConfirmAgendaDatePicker(e: WechatMiniprogram.CustomEvent) { |
|
const { agendaDatePickerIndex } = this.data |
|
const timestamp = e.detail |
|
const formattedTime = this.formatDateTime(timestamp) |
|
|
|
const agendas = this.data.agendas |
|
agendas[agendaDatePickerIndex].agendaTime = formattedTime |
|
|
|
this.setAndSave({ |
|
showAgendaDatePicker: false, |
|
agendas, |
|
}) |
|
}, |
|
|
|
// ========== 报名签到设置 ========== |
|
onToggleRegister(e: WechatMiniprogram.TouchEvent) { |
|
const { value } = e.currentTarget.dataset |
|
this.setAndSave({ needRegister: value === 'yes' }) |
|
}, |
|
|
|
onToggleRegisterLimit(e: WechatMiniprogram.TouchEvent) { |
|
const { value } = e.currentTarget.dataset |
|
this.setAndSave({ registerLimit: value }) |
|
}, |
|
|
|
onSelectCheckinWay(e: WechatMiniprogram.TouchEvent) { |
|
const { value } = e.currentTarget.dataset |
|
this.setAndSave({ checkinWay: value }) |
|
}, |
|
|
|
// ========== 底部操作 ========== |
|
onSaveDraft() { |
|
this.submitActivity(1) // activityStatus = 1 (草稿) |
|
}, |
|
|
|
onSubmit() { |
|
wx.showModal({ |
|
title: '确认提交', |
|
content: '提交后将进入审核流程,是否继续?', |
|
success: (res) => { |
|
if (res.confirm) { |
|
this.submitActivity(2) // activityStatus = 2 (待审核) |
|
} |
|
}, |
|
}) |
|
}, |
|
|
|
// 提交活动申请 |
|
async submitActivity(activityStatus: number) { |
|
const { |
|
coverImageList, |
|
title, |
|
type, |
|
typeOther, |
|
summary, |
|
detail, |
|
startTime, |
|
endTime, |
|
location, |
|
organizer, |
|
contactName, |
|
contactPhone, |
|
levelId, |
|
selectedCategoryIds, |
|
selectedTagIds, |
|
needRegister, |
|
registerStartTime, |
|
registerEndTime, |
|
registerLimit, |
|
registerLimitCount, |
|
registerCondition, |
|
checkinWay, |
|
checkinStartTime, |
|
checkinEndTime, |
|
agendas, |
|
detailImages, |
|
submitting, |
|
} = this.data |
|
|
|
if (submitting) return |
|
|
|
// 草稿模式不做严格校验,仅提交已填内容 |
|
// 正式提交(activityStatus=2)才校验必填字段 |
|
if (activityStatus === 2) { |
|
// 校验必填字段 |
|
if (!coverImageList.length) { |
|
wx.showToast({ title: '请上传活动头图', icon: 'error' }) |
|
return |
|
} |
|
if (!title.trim()) { |
|
wx.showToast({ title: '请输入活动标题', icon: 'error' }) |
|
return |
|
} |
|
if (!startTime) { |
|
wx.showToast({ title: '请选择活动开始时间', icon: 'error' }) |
|
return |
|
} |
|
if (!endTime) { |
|
wx.showToast({ title: '请选择活动结束时间', icon: 'error' }) |
|
return |
|
} |
|
if (!location.trim()) { |
|
wx.showToast({ title: '请输入活动地点', icon: 'error' }) |
|
return |
|
} |
|
|
|
// 校验报名设置 |
|
if (needRegister) { |
|
if (!registerStartTime) { |
|
wx.showToast({ title: '请选择报名开始时间', icon: 'error' }) |
|
return |
|
} |
|
if (!registerEndTime) { |
|
wx.showToast({ title: '请选择报名截止时间', icon: 'error' }) |
|
return |
|
} |
|
} |
|
|
|
// 校验签到设置 |
|
if (checkinWay !== 'none') { |
|
if (!checkinStartTime) { |
|
wx.showToast({ title: '请选择签到开始时间', icon: 'error' }) |
|
return |
|
} |
|
if (!checkinEndTime) { |
|
wx.showToast({ title: '请选择签到结束时间', icon: 'error' }) |
|
return |
|
} |
|
} |
|
|
|
// 议程可选,不做必填验证 |
|
} |
|
|
|
this.setData({ submitting: true }) |
|
wx.showLoading({ title: activityStatus === 1 ? '保存中...' : '提交中...' }) |
|
|
|
try { |
|
const checkinTypeMap: Record<string, number> = { |
|
dynamic: 1, |
|
fixed: 2, |
|
none: 3, |
|
} |
|
|
|
const params: Record<string, any> = { |
|
mainImages: coverImageList.map((item) => item.url), |
|
name: title, |
|
type, |
|
typeOther: type === 6 ? typeOther : '', |
|
summary, |
|
detailImages, |
|
description: detail, |
|
checkinType: checkinTypeMap[checkinWay], |
|
regType: needRegister ? 1 : 2, |
|
regCondition: registerCondition, |
|
quota: registerLimit === 'limited' ? Number(registerLimitCount) : 0, |
|
regStartAt: needRegister ? registerStartTime : '', |
|
regEndAt: needRegister ? registerEndTime : '', |
|
startAt: startTime, |
|
endAt: endTime, |
|
location, |
|
organizer, |
|
contactName, |
|
contactPhone, |
|
tagIds: selectedTagIds, |
|
categoryIds: selectedCategoryIds, |
|
levelId, |
|
checkinStartAt: checkinWay !== 'none' ? checkinStartTime : '', |
|
checkinEndAt: checkinWay !== 'none' ? checkinEndTime : '', |
|
// 过滤掉空的议程(没有标题的议程不提交) |
|
agendas: agendas |
|
.filter((item) => item.title.trim()) |
|
.map((item, index) => ({ |
|
agendaTime: item.agendaTime, |
|
title: item.title, |
|
description: item.description, |
|
sort: index, |
|
})), |
|
activityStatus, |
|
} |
|
|
|
// 编辑模式传入 id,统一使用 /activity/apply 接口 |
|
if (this.data.isEdit) { |
|
params.id = this.data.editId |
|
} |
|
|
|
const res = await wx.ajax({ |
|
url: '/activity/apply', |
|
method: 'POST', |
|
data: params, |
|
}) |
|
|
|
wx.hideLoading() |
|
|
|
if (res) { |
|
wx.showToast({ |
|
title: activityStatus === 1 ? '已保存草稿' : '提交成功', |
|
icon: 'success', |
|
}) |
|
|
|
// 清理本地草稿 |
|
this.clearDraft() |
|
|
|
// 跳转到结果页面(编辑模式使用 editId) |
|
const activityId = this.data.isEdit ? this.data.editId : res.activityId |
|
wx.redirectTo({ |
|
url: `/pages/actAddResult/index?id=${activityId}&status=${res.status || ''}`, |
|
}) |
|
} |
|
} catch (err: any) { |
|
wx.hideLoading() |
|
const message = err?.message || '提交失败' |
|
wx.showToast({ title: message, icon: 'error' }) |
|
} finally { |
|
this.setData({ submitting: false }) |
|
} |
|
}, |
|
|
|
onGoHome() { |
|
this.clearDraft() |
|
wx.switchTab({ url: '/pages/index/index' }) |
|
}, |
|
handleAiAdd() { |
|
wx.navigateTo({ |
|
url: '/pages/chat/index', |
|
}) |
|
}, |
|
}) |
|
|
|
export {}
|
|
|