v4.2 冲刺版+每日推送+支付修复+全量代码评审
## 新增功能 - 冲刺版 ¥49.9/月:完整支付→激活→权益扣减链路 - 每日一题定时推送(@nestjs/schedule,早8点微信订阅消息) - miniprogram-ci 编译上传脚本(scripts/upload-mp.js) ## Bug修复 - 套餐值统一:vip→growth/sprint(interview轮次限制、analyze次数检查) - member/pay 移除开发绕过:改为订单校验后激活 - progress→report 参数名不匹配:id→interviewId - result.vue resume.create() 参数传错(对象→独立参数) - resume.vue analyze请求缺少Authorization header - bank.vue contribution请求缺少Authorization header - member.vue startPay() 缺少try/catch导致网络错误崩溃 - login.vue 调试面板 v-if="true" 生产泄漏 ## 配置 - 微信支付生产证书就位(商户号1113760598) - .env 清理冗余文件(删除.example/.production) - WX_NOTIFY_URL 更新为 zhiyinwx.yzrcloud.cn ## 文档 - PROJECT-STATUS.md v4.1→v4.2,状态全面更新 - DEPLOYMENT.md 新增小程序编译上传章节、清理检查清单
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
import { Injectable, Logger } from '@nestjs/common'
|
||||
import { Cron } from '@nestjs/schedule'
|
||||
import { InjectModel } from '@nestjs/mongoose'
|
||||
import { Model } from 'mongoose'
|
||||
import { WechatTokenService } from './wechat-token.service'
|
||||
import { DailyQuestion, DailyQuestionDocument } from '../schemas/daily-question.schema'
|
||||
import { User, UserDocument } from '../user/user.schema'
|
||||
|
||||
const DAILY_QUESTION_TEMPLATE_ID = process.env.WX_DAILY_QUESTION_TMPL || ''
|
||||
|
||||
@Injectable()
|
||||
export class DailyQuestionPushService {
|
||||
private readonly logger = new Logger(DailyQuestionPushService.name)
|
||||
|
||||
constructor(
|
||||
@InjectModel(DailyQuestion.name) private dailyQuestionModel: Model<DailyQuestionDocument>,
|
||||
@InjectModel(User.name) private userModel: Model<UserDocument>,
|
||||
private wechatToken: WechatTokenService,
|
||||
) {}
|
||||
|
||||
@Cron('0 8 * * *')
|
||||
async pushDailyQuestion() {
|
||||
this.logger.log('开始每日一题推送任务')
|
||||
|
||||
if (!DAILY_QUESTION_TEMPLATE_ID) {
|
||||
this.logger.warn('未配置 WX_DAILY_QUESTION_TMPL,跳过每日推送')
|
||||
return
|
||||
}
|
||||
|
||||
const today = new Date()
|
||||
today.setHours(0, 0, 0, 0)
|
||||
|
||||
const question = await this.dailyQuestionModel.findOne({ pushed: false }).sort({ date: -1 }).exec()
|
||||
if (!question) {
|
||||
this.logger.warn('没有未推送的题目')
|
||||
return
|
||||
}
|
||||
|
||||
const users = await this.userModel.find({ wxOpenid: { $ne: '', $exists: true } }).exec()
|
||||
this.logger.log(`找到 ${users.length} 个用户待推送`)
|
||||
|
||||
let successCount = 0
|
||||
for (const user of users) {
|
||||
if (!user.wxOpenid) continue
|
||||
const ok = await this.wechatToken.sendSubscribeMessage(
|
||||
user.wxOpenid,
|
||||
DAILY_QUESTION_TEMPLATE_ID,
|
||||
{
|
||||
thing1: { value: question.question.slice(0, 20) + (question.question.length > 20 ? '...' : '') },
|
||||
thing2: { value: question.position || '通用' },
|
||||
thing3: { value: question.referenceAnswer.slice(0, 20) + (question.referenceAnswer.length > 20 ? '...' : '') },
|
||||
},
|
||||
'pages/interview/interview',
|
||||
)
|
||||
if (ok) successCount++
|
||||
}
|
||||
|
||||
question.pushed = true
|
||||
await question.save()
|
||||
|
||||
this.logger.log(`每日一题推送完成:成功 ${successCount}/${users.length}`)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user