feat: note字段改为{text,images}对象结构,新增/api/upload/image接口
This commit is contained in:
+3
-1
@@ -20,6 +20,7 @@ const equityDetailRoutes = require('./routes/equityDetail');
|
||||
const membershipRoutes = require('./routes/membership');
|
||||
const settingsRoutes = require('./routes/settings');
|
||||
const subscribeRoutes = require('./routes/subscribe');
|
||||
const uploadRoutes = require('./routes/upload');
|
||||
const wechatMessageRoutes = require('./routes/wechatMessage');
|
||||
|
||||
const cron = require('node-cron');
|
||||
@@ -69,6 +70,7 @@ app.use('/api/equity-detail', equityDetailRoutes);
|
||||
app.use('/api/membership', membershipRoutes);
|
||||
app.use('/api/settings', settingsRoutes);
|
||||
app.use('/api/subscribe', subscribeRoutes);
|
||||
app.use('/api/upload', uploadRoutes);
|
||||
|
||||
app.use('/wechat-message', wechatMessageRoutes);
|
||||
|
||||
@@ -76,7 +78,7 @@ const adminRoutes = require('./routes/admin');
|
||||
app.use('/api/admin', adminRoutes);
|
||||
|
||||
const { sendExpiryReminders } = require('./routes/subscribe');
|
||||
cron.schedule('30 21 * * *', async () => {
|
||||
cron.schedule('40 9 * * *', async () => {
|
||||
console.log(`[${new Date().toISOString()}] ⏰ 到期提醒定时任务开始执行...`);
|
||||
try {
|
||||
const results = await sendExpiryReminders();
|
||||
|
||||
@@ -120,8 +120,8 @@ const userEquitySchema = new mongoose.Schema({
|
||||
default: 'active'
|
||||
},
|
||||
note: {
|
||||
type: String,
|
||||
default: ''
|
||||
text: { type: String, default: '' },
|
||||
images: [{ type: String }]
|
||||
},
|
||||
hasUsedBenefit: {
|
||||
type: Boolean,
|
||||
|
||||
+35
-3
@@ -177,17 +177,49 @@ async function sendExpiryReminders() {
|
||||
try {
|
||||
const equities = await UserEquity.find({
|
||||
owner: sub.userId,
|
||||
status: 'active',
|
||||
expireDate: targetDateStr
|
||||
status: 'active'
|
||||
});
|
||||
|
||||
for (const equity of equities) {
|
||||
const dayLabel = daysBefore === 0 ? '今天' : `${daysBefore}天`;
|
||||
let shouldSend = false;
|
||||
let reminderTarget = null;
|
||||
|
||||
if (equity.expireDate === targetDateStr) {
|
||||
shouldSend = true;
|
||||
reminderTarget = {
|
||||
name: `${equity.platform}${equity.type}`,
|
||||
type: 'platform'
|
||||
};
|
||||
}
|
||||
|
||||
if (!shouldSend && equity.benefits && equity.benefits.length > 0) {
|
||||
for (const benefit of equity.benefits) {
|
||||
if (benefit.expireDate === targetDateStr) {
|
||||
shouldSend = true;
|
||||
reminderTarget = {
|
||||
name: benefit.name,
|
||||
type: 'benefit'
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldSend) continue;
|
||||
|
||||
let thing2;
|
||||
if (reminderTarget.type === 'platform') {
|
||||
thing2 = `您的${reminderTarget.name}将在${dayLabel}到期`;
|
||||
} else {
|
||||
thing2 = `您的${equity.platform}权益「${reminderTarget.name}」将在${dayLabel}到期`;
|
||||
}
|
||||
|
||||
const result = await WechatSubscribeService.sendExpiryReminderMessage({
|
||||
openid: sub.openid,
|
||||
templateId: sub.templateId,
|
||||
thing1: equity.platform,
|
||||
thing2: `您的${equity.platform}${equity.type}将在${dayLabel}到期`,
|
||||
thing2: thing2,
|
||||
phrase3: daysBefore === 0 ? '已到期' : '即将到期'
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const multer = require('multer');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const { auth } = require('../middleware/auth');
|
||||
|
||||
const uploadDir = path.join(__dirname, '../../public/uploads/equity-notes');
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, { recursive: true });
|
||||
}
|
||||
|
||||
const storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => {
|
||||
cb(null, uploadDir);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
|
||||
const ext = path.extname(file.originalname || '') || '.jpg';
|
||||
cb(null, 'note-' + uniqueSuffix + ext);
|
||||
}
|
||||
});
|
||||
|
||||
const upload = multer({
|
||||
storage,
|
||||
limits: { fileSize: 10 * 1024 * 1024 },
|
||||
fileFilter: (req, file, cb) => {
|
||||
const allowedTypes = /jpeg|jpg|png|gif|webp/;
|
||||
const extname = allowedTypes.test(path.extname(file.originalname || '').toLowerCase());
|
||||
const mimetype = allowedTypes.test(file.mimetype || '');
|
||||
if (extname || mimetype) {
|
||||
cb(null, true);
|
||||
} else {
|
||||
cb(new Error('只允许上传图片文件'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/image', auth, upload.single('file'), async (req, res, next) => {
|
||||
try {
|
||||
if (!req.file) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: '请选择要上传的图片'
|
||||
});
|
||||
}
|
||||
|
||||
const filename = req.file.filename;
|
||||
const baseUrl = process.env.SERVER_URL || 'https://api-miniapp.dxz99wyr.cn';
|
||||
const url = `${baseUrl}/uploads/equity-notes/${filename}`;
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
url
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
@@ -158,7 +158,10 @@ router.post('/', auth, requireVip, async (req, res, next) => {
|
||||
benefits: benefits || [],
|
||||
owner: req.user._id,
|
||||
status: status || 'active',
|
||||
note: note || '',
|
||||
note: {
|
||||
text: (note && note.text) || '',
|
||||
images: (note && note.images) || []
|
||||
},
|
||||
syncedAt: new Date().toISOString()
|
||||
};
|
||||
|
||||
@@ -227,7 +230,10 @@ router.post('/batch', auth, requireVip, async (req, res, next) => {
|
||||
benefits: benefits || [],
|
||||
owner: req.user._id,
|
||||
status: status || 'active',
|
||||
note: note || '',
|
||||
note: {
|
||||
text: (note && note.text) || '',
|
||||
images: (note && note.images) || []
|
||||
},
|
||||
syncedAt: new Date().toISOString()
|
||||
};
|
||||
|
||||
@@ -287,7 +293,10 @@ router.put('/:id', auth, requireVip, async (req, res, next) => {
|
||||
if (price !== undefined) updates.price = parseFloat(price) || 0;
|
||||
if (benefits !== undefined) updates.benefits = benefits;
|
||||
if (status !== undefined) updates.status = status;
|
||||
if (note !== undefined) updates.note = note;
|
||||
if (note !== undefined) updates.note = {
|
||||
text: (note && note.text) || '',
|
||||
images: (note && note.images) || []
|
||||
};
|
||||
if (platformType !== undefined) updates.platformType = platformType;
|
||||
if (brandIcon !== undefined) updates.brandIcon = brandIcon;
|
||||
if (brandIconImage !== undefined) updates.brandIconImage = brandIconImage;
|
||||
|
||||
Reference in New Issue
Block a user