fix: 修复奖品图片和赞助商logo删除bug
- 修复编辑奖品时删除图片后保存,图片仍存在的问题 - 修复编辑赞助商时删除logo后保存,logo仍存在的问题 - 前端添加删除检测逻辑,传递removeImage/removeLogo标记 - 后端处理删除标记,将对应字段设为null
This commit is contained in:
parent
4920620d2c
commit
2530ceb6b4
|
|
@ -3,6 +3,7 @@ const router = express.Router();
|
|||
const bcrypt = require('bcryptjs');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const auth = require('../middleware/auth');
|
||||
const authSuper = require('../middleware/authSuper');
|
||||
const { upload, getFileUrls } = require('../middleware/upload');
|
||||
const { Admin, Activity, Registration, Expense, Photo, Sponsor, Prize } = require('../models');
|
||||
const fs = require('fs');
|
||||
|
|
@ -17,7 +18,132 @@ router.post('/login', async (req, res) => {
|
|||
return res.status(401).json({ error: '用户名或密码错误' });
|
||||
}
|
||||
const token = jwt.sign({ id: admin.id }, process.env.JWT_SECRET, { expiresIn: '7d' });
|
||||
res.json({ token, admin: { id: admin.id, username: admin.username, name: admin.name } });
|
||||
res.json({
|
||||
token,
|
||||
admin: {
|
||||
id: admin.id,
|
||||
username: admin.username,
|
||||
name: admin.name,
|
||||
role: admin.role
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// ========== 管理员管理API(仅超级管理员) ==========
|
||||
|
||||
// 获取管理员列表
|
||||
router.get('/admins', authSuper, async (req, res) => {
|
||||
try {
|
||||
const admins = await Admin.findAll({
|
||||
attributes: ['id', 'username', 'name', 'role', 'createdAt'],
|
||||
order: [['createdAt', 'ASC']],
|
||||
raw: true
|
||||
});
|
||||
res.json(admins);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 创建管理员
|
||||
router.post('/admins', authSuper, async (req, res) => {
|
||||
try {
|
||||
const { username, password, name, role } = req.body;
|
||||
|
||||
if (!username || !password) {
|
||||
return res.status(400).json({ error: '用户名和密码不能为空' });
|
||||
}
|
||||
|
||||
const existing = await Admin.findOne({ where: { username } });
|
||||
if (existing) {
|
||||
return res.status(400).json({ error: '用户名已存在' });
|
||||
}
|
||||
|
||||
const hashedPassword = bcrypt.hashSync(password, 10);
|
||||
const admin = await Admin.create({
|
||||
username,
|
||||
password: hashedPassword,
|
||||
name: name || username,
|
||||
role: role || 'admin'
|
||||
});
|
||||
|
||||
res.json({
|
||||
id: admin.id,
|
||||
username: admin.username,
|
||||
name: admin.name,
|
||||
role: admin.role
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 修改管理员信息
|
||||
router.put('/admins/:id', authSuper, async (req, res) => {
|
||||
try {
|
||||
const { name, role } = req.body;
|
||||
const admin = await Admin.findByPk(req.params.id);
|
||||
|
||||
if (!admin) {
|
||||
return res.status(404).json({ error: '管理员不存在' });
|
||||
}
|
||||
|
||||
const updateData = {};
|
||||
if (name !== undefined) updateData.name = name;
|
||||
if (role !== undefined) updateData.role = role;
|
||||
|
||||
await Admin.update(updateData, { where: { id: req.params.id } });
|
||||
const updated = await Admin.findByPk(req.params.id, {
|
||||
attributes: ['id', 'username', 'name', 'role']
|
||||
});
|
||||
|
||||
res.json(updated);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 修改管理员密码
|
||||
router.put('/admins/:id/password', authSuper, async (req, res) => {
|
||||
try {
|
||||
const { newPassword } = req.body;
|
||||
|
||||
if (!newPassword) {
|
||||
return res.status(400).json({ error: '新密码不能为空' });
|
||||
}
|
||||
|
||||
const admin = await Admin.findByPk(req.params.id);
|
||||
if (!admin) {
|
||||
return res.status(404).json({ error: '管理员不存在' });
|
||||
}
|
||||
|
||||
const hashedPassword = bcrypt.hashSync(newPassword, 10);
|
||||
await Admin.update({ password: hashedPassword }, { where: { id: req.params.id } });
|
||||
|
||||
res.json({ message: '密码修改成功' });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 删除管理员
|
||||
router.delete('/admins/:id', authSuper, async (req, res) => {
|
||||
try {
|
||||
const admin = await Admin.findByPk(req.params.id);
|
||||
if (!admin) {
|
||||
return res.status(404).json({ error: '管理员不存在' });
|
||||
}
|
||||
|
||||
// 防止删除超级管理员
|
||||
if (admin.role === 'super') {
|
||||
return res.status(403).json({ error: '不能删除超级管理员' });
|
||||
}
|
||||
|
||||
await Admin.destroy({ where: { id: req.params.id } });
|
||||
res.json({ message: '删除成功' });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
|
|
@ -93,6 +219,16 @@ router.get('/registrations', auth, async (req, res) => {
|
|||
}
|
||||
});
|
||||
|
||||
// 删除报名
|
||||
router.delete('/registrations/:id', auth, async (req, res) => {
|
||||
try {
|
||||
await Registration.destroy({ where: { id: req.params.id } });
|
||||
res.json({ message: '删除成功' });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 上传经费明细
|
||||
router.post('/expenses', auth, upload.array('media', 5), async (req, res) => {
|
||||
try {
|
||||
|
|
@ -274,7 +410,7 @@ router.post('/sponsors', auth, upload.single('logo'), async (req, res) => {
|
|||
// 更新赞助商
|
||||
router.put('/sponsors/:id', auth, upload.single('logo'), async (req, res) => {
|
||||
try {
|
||||
const { name, type, link, sortOrder } = req.body;
|
||||
const { name, type, link, sortOrder, removeLogo } = req.body;
|
||||
const updateData = { name, type, link };
|
||||
|
||||
if (sortOrder !== undefined) {
|
||||
|
|
@ -284,6 +420,8 @@ router.put('/sponsors/:id', auth, upload.single('logo'), async (req, res) => {
|
|||
if (req.file) {
|
||||
const [uploaded] = getFileUrls(req.file);
|
||||
updateData.logo = uploaded.url;
|
||||
} else if (removeLogo === 'true') {
|
||||
updateData.logo = null;
|
||||
}
|
||||
|
||||
await Sponsor.update(updateData, { where: { id: req.params.id } });
|
||||
|
|
@ -307,7 +445,7 @@ router.delete('/sponsors/:id', auth, async (req, res) => {
|
|||
// 添加奖品
|
||||
router.post('/prizes', auth, upload.single('image'), async (req, res) => {
|
||||
try {
|
||||
const { activityId, name, level, description, quantity, sortOrder } = req.body;
|
||||
const { activityId, name, level, description, quantity, sortOrder, source, sponsor } = req.body;
|
||||
let image = null;
|
||||
if (req.file) {
|
||||
const [uploaded] = getFileUrls([req.file]);
|
||||
|
|
@ -320,7 +458,9 @@ router.post('/prizes', auth, upload.single('image'), async (req, res) => {
|
|||
description,
|
||||
image,
|
||||
quantity: quantity || 1,
|
||||
sortOrder: sortOrder || 0
|
||||
sortOrder: sortOrder || 0,
|
||||
source: source || 'purchase',
|
||||
sponsor: sponsor || null
|
||||
});
|
||||
res.json(prize);
|
||||
} catch (error) {
|
||||
|
|
@ -331,12 +471,14 @@ router.post('/prizes', auth, upload.single('image'), async (req, res) => {
|
|||
// 更新奖品
|
||||
router.put('/prizes/:id', auth, upload.single('image'), async (req, res) => {
|
||||
try {
|
||||
const { name, level, description, quantity, sortOrder } = req.body;
|
||||
const updateData = { name, level, description, quantity, sortOrder };
|
||||
const { name, level, description, quantity, sortOrder, source, sponsor, removeImage } = req.body;
|
||||
const updateData = { name, level, description, quantity, sortOrder, source, sponsor };
|
||||
|
||||
if (req.file) {
|
||||
const [uploaded] = getFileUrls([req.file]);
|
||||
updateData.image = uploaded.url;
|
||||
} else if (removeImage === 'true') {
|
||||
updateData.image = null;
|
||||
}
|
||||
|
||||
await Prize.update(updateData, { where: { id: req.params.id } });
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@
|
|||
</div>
|
||||
|
||||
<!-- 悬浮添加按钮 -->
|
||||
<div class="float-add-btn" @click="showExpenseForm = true">
|
||||
<div class="float-add-btn" @click="addNewExpense">
|
||||
<van-icon name="plus" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -178,7 +178,7 @@
|
|||
<van-empty v-if="!sponsors.length" description="暂无赞助商" />
|
||||
|
||||
<!-- 悬浮添加按钮 -->
|
||||
<div class="float-add-btn" @click="showSponsorForm = true">
|
||||
<div class="float-add-btn" @click="addNewSponsor">
|
||||
<van-icon name="plus" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -214,7 +214,7 @@
|
|||
<van-empty v-if="!prizes.length" description="暂无奖品" />
|
||||
|
||||
<!-- 悬浮添加按钮 -->
|
||||
<div class="float-add-btn" @click="showPrizeForm = true">
|
||||
<div class="float-add-btn" @click="addNewPrize">
|
||||
<van-icon name="plus" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -732,6 +732,22 @@
|
|||
required
|
||||
/>
|
||||
<van-field v-model="prizeForm.description" label="描述" type="textarea" placeholder="奖品描述(选填)" rows="2" autosize />
|
||||
<van-field
|
||||
v-model="prizeForm.source"
|
||||
label="来源"
|
||||
placeholder="选择来源"
|
||||
is-link
|
||||
readonly
|
||||
@click="showSourcePicker = true"
|
||||
required
|
||||
/>
|
||||
<van-field
|
||||
v-if="prizeForm.source !== 'purchase'"
|
||||
v-model="prizeForm.sponsor"
|
||||
label="赞助者"
|
||||
placeholder="请输入赞助者名称"
|
||||
required
|
||||
/>
|
||||
<van-field
|
||||
v-model.number="prizeForm.quantity"
|
||||
type="number"
|
||||
|
|
@ -779,7 +795,31 @@
|
|||
class="level-item"
|
||||
@click="selectLevel(level)"
|
||||
>
|
||||
<span class="level-badge" :class="`level-${level}`">{{ level }}</span>
|
||||
<span class="prize-level-badge" :class="`level-${level}`">{{ level }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
|
||||
<!-- 来源选择器 -->
|
||||
<van-popup v-model:show="showSourcePicker" position="bottom" round>
|
||||
<div class="level-picker">
|
||||
<div class="picker-header">
|
||||
<h3>选择来源</h3>
|
||||
<van-icon name="cross" @click="showSourcePicker = false" />
|
||||
</div>
|
||||
<div class="level-list">
|
||||
<div class="level-item" @click="selectSource('member')">
|
||||
<van-icon name="friends-o" color="#FF6700" />
|
||||
<span>群友赞助</span>
|
||||
</div>
|
||||
<div class="level-item" @click="selectSource('sponsor')">
|
||||
<van-icon name="shop-o" color="#FF6700" />
|
||||
<span>赞助商提供</span>
|
||||
</div>
|
||||
<div class="level-item" @click="selectSource('purchase')">
|
||||
<van-icon name="shopping-cart-o" color="#999" />
|
||||
<span>采购</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -880,6 +920,16 @@
|
|||
<van-button size="large" type="success" @click="approveFromDetail('approved')">通过</van-button>
|
||||
<van-button size="large" type="danger" @click="approveFromDetail('rejected')">拒绝</van-button>
|
||||
</div>
|
||||
<van-button
|
||||
block
|
||||
size="large"
|
||||
type="danger"
|
||||
plain
|
||||
@click="deleteRegistration"
|
||||
style="margin-top: 12px;"
|
||||
>
|
||||
删除报名
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
|
|
@ -935,6 +985,7 @@ const {
|
|||
prizes,
|
||||
showPrizeForm,
|
||||
showLevelPicker,
|
||||
showSourcePicker,
|
||||
prizeImage,
|
||||
prizeForm,
|
||||
prizeLevels,
|
||||
|
|
@ -942,6 +993,7 @@ const {
|
|||
editPrize,
|
||||
onPrizeImageRead,
|
||||
selectLevel,
|
||||
selectSource,
|
||||
submitPrize,
|
||||
deletePrizeItem,
|
||||
resetPrizeForm
|
||||
|
|
@ -1084,14 +1136,29 @@ const formatDateTime = (dateTime) => {
|
|||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||
};
|
||||
|
||||
// 安全解析datetime-local格式,确保以本地时区创建Date对象
|
||||
const parseDateTimeLocal = (dateTimeStr) => {
|
||||
console.log('[时区转换] 输入的datetime-local字符串:', dateTimeStr);
|
||||
const [datePart, timePart] = dateTimeStr.split('T');
|
||||
const [year, month, day] = datePart.split('-').map(Number);
|
||||
const [hours, minutes] = timePart.split(':').map(Number);
|
||||
const localDate = new Date(year, month - 1, day, hours, minutes);
|
||||
console.log('[时区转换] 创建的本地Date对象:', localDate.toString());
|
||||
console.log('[时区转换] 转换为UTC (ISO):', localDate.toISOString());
|
||||
console.log('[时区转换] 时区偏移(分钟):', localDate.getTimezoneOffset());
|
||||
return localDate;
|
||||
};
|
||||
|
||||
// 开始时间确认
|
||||
const confirmStartTime = () => {
|
||||
if (!startTimeInput.value) {
|
||||
showToast('请选择开始时间');
|
||||
return;
|
||||
}
|
||||
const selectedDate = new Date(startTimeInput.value);
|
||||
console.log('[开始时间] 用户选择的时间:', startTimeInput.value);
|
||||
const selectedDate = parseDateTimeLocal(startTimeInput.value);
|
||||
activityForm.value.startTime = selectedDate.toISOString();
|
||||
console.log('[开始时间] 保存到表单的UTC时间:', activityForm.value.startTime);
|
||||
showStartTimePicker.value = false;
|
||||
};
|
||||
|
||||
|
|
@ -1101,12 +1168,14 @@ const confirmDeadline = () => {
|
|||
showToast('请选择报名截止时间');
|
||||
return;
|
||||
}
|
||||
const selectedDate = new Date(deadlineInput.value);
|
||||
console.log('[截止时间] 用户选择的时间:', deadlineInput.value);
|
||||
const selectedDate = parseDateTimeLocal(deadlineInput.value);
|
||||
if (activityForm.value.startTime && selectedDate > new Date(activityForm.value.startTime)) {
|
||||
showToast('报名截止时间不能晚于活动开始时间');
|
||||
return;
|
||||
}
|
||||
activityForm.value.registrationDeadline = selectedDate.toISOString();
|
||||
console.log('[截止时间] 保存到表单的UTC时间:', activityForm.value.registrationDeadline);
|
||||
showDeadlinePicker.value = false;
|
||||
};
|
||||
|
||||
|
|
@ -1162,17 +1231,31 @@ const loadData = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
// 添加新奖品
|
||||
const addNewPrize = () => {
|
||||
resetPrizeForm();
|
||||
showPrizeForm.value = true;
|
||||
};
|
||||
|
||||
const editActivity = () => {
|
||||
activityForm.value = { ...activity.value };
|
||||
|
||||
console.log('[编辑活动] 原始活动数据:', activity.value);
|
||||
|
||||
// 设置日期时间选择器的值
|
||||
if (activity.value.startTime) {
|
||||
console.log('[编辑活动] 数据库的开始时间(UTC):', activity.value.startTime);
|
||||
const startDate = new Date(activity.value.startTime);
|
||||
console.log('[编辑活动] 转换为本地Date对象:', startDate.toString());
|
||||
startTimeInput.value = formatDateTimeLocal(startDate);
|
||||
console.log('[编辑活动] 显示在选择器的时间:', startTimeInput.value);
|
||||
}
|
||||
if (activity.value.registrationDeadline) {
|
||||
console.log('[编辑活动] 数据库的截止时间(UTC):', activity.value.registrationDeadline);
|
||||
const deadlineDate = new Date(activity.value.registrationDeadline);
|
||||
console.log('[编辑活动] 转换为本地Date对象:', deadlineDate.toString());
|
||||
deadlineInput.value = formatDateTimeLocal(deadlineDate);
|
||||
console.log('[编辑活动] 显示在选择器的时间:', deadlineInput.value);
|
||||
}
|
||||
|
||||
showActivityForm.value = true;
|
||||
|
|
@ -1283,6 +1366,13 @@ const editExpense = (expense) => {
|
|||
showExpenseForm.value = true;
|
||||
};
|
||||
|
||||
// 添加新经费
|
||||
const addNewExpense = () => {
|
||||
expenseForm.value = { id: null, item: '', amount: '', category: '', note: '', media: [] };
|
||||
expenseMediaFiles.value = [];
|
||||
showExpenseForm.value = true;
|
||||
};
|
||||
|
||||
const onExpenseMediaRead = (file) => {
|
||||
// 文件读取后的处理,Vant会自动处理
|
||||
};
|
||||
|
|
@ -1344,6 +1434,16 @@ const submitSponsor = async () => {
|
|||
duration: 0
|
||||
});
|
||||
formData.append('logo', sponsorLogo.value[0].file);
|
||||
} else if (sponsorLogo.value.length === 0 && sponsorForm.value.logo) {
|
||||
// 用户删除了logo
|
||||
formData.append('removeLogo', 'true');
|
||||
console.log('用户删除了 Logo');
|
||||
loadingToast = showToast({
|
||||
type: 'loading',
|
||||
message: '正在保存...',
|
||||
forbidClick: true,
|
||||
duration: 0
|
||||
});
|
||||
} else {
|
||||
console.log('没有 Logo,仅保存数据');
|
||||
loadingToast = showToast({
|
||||
|
|
@ -1411,6 +1511,13 @@ const editSponsor = (sponsor) => {
|
|||
showSponsorForm.value = true;
|
||||
};
|
||||
|
||||
// 添加新赞助商
|
||||
const addNewSponsor = () => {
|
||||
sponsorForm.value = { id: null, name: '', type: 'sponsor', link: '', sortOrder: 0 };
|
||||
sponsorLogo.value = [];
|
||||
showSponsorForm.value = true;
|
||||
};
|
||||
|
||||
const onLogoRead = (file) => {
|
||||
// 文件选择后的回调,显示文件已选择
|
||||
if (file.file) {
|
||||
|
|
@ -1515,6 +1622,24 @@ const approveFromDetail = async (status) => {
|
|||
}
|
||||
};
|
||||
|
||||
// 删除报名
|
||||
const deleteRegistration = async () => {
|
||||
try {
|
||||
await showConfirmDialog({
|
||||
title: '确认删除',
|
||||
message: '删除后用户可以重新报名,确定要删除这条报名信息吗?'
|
||||
});
|
||||
await api.deleteRegistration(currentReg.value.id);
|
||||
showToast('删除成功');
|
||||
showRegDetailDialog.value = false;
|
||||
loadData();
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
showToast('删除失败');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 媒体管理相关方法
|
||||
const uploadPhotos = async (files) => {
|
||||
const fileArray = Array.isArray(files) ? files : [files];
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ export function usePrizeManage(activityId) {
|
|||
const prizes = ref([]);
|
||||
const showPrizeForm = ref(false);
|
||||
const showLevelPicker = ref(false);
|
||||
const showSourcePicker = ref(false);
|
||||
const prizeImage = ref([]);
|
||||
const prizeForm = ref({
|
||||
id: null,
|
||||
|
|
@ -15,10 +16,12 @@ export function usePrizeManage(activityId) {
|
|||
description: '',
|
||||
quantity: 1,
|
||||
sortOrder: 0,
|
||||
source: 'purchase',
|
||||
sponsor: '',
|
||||
image: null
|
||||
});
|
||||
|
||||
const prizeLevels = ['一等奖', '二等奖', '三等奖', '参与奖', '伴手礼'];
|
||||
const prizeLevels = ['特等奖', '一等奖', '二等奖', '三等奖', '四等奖', '参与奖', '伴手礼'];
|
||||
|
||||
const loadPrizes = async () => {
|
||||
try {
|
||||
|
|
@ -38,6 +41,8 @@ export function usePrizeManage(activityId) {
|
|||
description: prize.description || '',
|
||||
quantity: prize.quantity,
|
||||
sortOrder: prize.sortOrder || 0,
|
||||
source: prize.source || 'purchase',
|
||||
sponsor: prize.sponsor || '',
|
||||
image: prize.image
|
||||
};
|
||||
// 回显图片 - 需要使用完整URL
|
||||
|
|
@ -60,12 +65,25 @@ export function usePrizeManage(activityId) {
|
|||
showLevelPicker.value = false;
|
||||
};
|
||||
|
||||
const selectSource = (source) => {
|
||||
prizeForm.value.source = source;
|
||||
if (source === 'purchase') {
|
||||
prizeForm.value.sponsor = '';
|
||||
}
|
||||
showSourcePicker.value = false;
|
||||
};
|
||||
|
||||
const submitPrize = async () => {
|
||||
if (!prizeForm.value.name || !prizeForm.value.level) {
|
||||
if (!prizeForm.value.name || !prizeForm.value.level || !prizeForm.value.source) {
|
||||
showToast('请填写必填项');
|
||||
return;
|
||||
}
|
||||
|
||||
if (prizeForm.value.source !== 'purchase' && !prizeForm.value.sponsor) {
|
||||
showToast('请填写赞助者名称');
|
||||
return;
|
||||
}
|
||||
|
||||
const loadingToast = showToast({
|
||||
type: 'loading',
|
||||
message: '保存中...',
|
||||
|
|
@ -81,9 +99,16 @@ export function usePrizeManage(activityId) {
|
|||
formData.append('description', prizeForm.value.description);
|
||||
formData.append('quantity', prizeForm.value.quantity);
|
||||
formData.append('sortOrder', prizeForm.value.sortOrder);
|
||||
formData.append('source', prizeForm.value.source);
|
||||
if (prizeForm.value.sponsor) {
|
||||
formData.append('sponsor', prizeForm.value.sponsor);
|
||||
}
|
||||
|
||||
if (prizeForm.value.imageFile) {
|
||||
formData.append('image', prizeForm.value.imageFile);
|
||||
} else if (prizeImage.value.length === 0 && prizeForm.value.image) {
|
||||
// 用户删除了图片
|
||||
formData.append('removeImage', 'true');
|
||||
}
|
||||
|
||||
if (prizeForm.value.id) {
|
||||
|
|
@ -130,6 +155,8 @@ export function usePrizeManage(activityId) {
|
|||
description: '',
|
||||
quantity: 1,
|
||||
sortOrder: 0,
|
||||
source: 'purchase',
|
||||
sponsor: '',
|
||||
image: null
|
||||
};
|
||||
prizeImage.value = [];
|
||||
|
|
@ -139,6 +166,7 @@ export function usePrizeManage(activityId) {
|
|||
prizes,
|
||||
showPrizeForm,
|
||||
showLevelPicker,
|
||||
showSourcePicker,
|
||||
prizeImage,
|
||||
prizeForm,
|
||||
prizeLevels,
|
||||
|
|
@ -146,6 +174,7 @@ export function usePrizeManage(activityId) {
|
|||
editPrize,
|
||||
onPrizeImageRead,
|
||||
selectLevel,
|
||||
selectSource,
|
||||
submitPrize,
|
||||
deletePrizeItem,
|
||||
resetPrizeForm
|
||||
|
|
|
|||
Loading…
Reference in New Issue