增加邮件相关接口
This commit is contained in:
parent
446d962fd8
commit
b8f5c94960
94
doc/api.md
94
doc/api.md
@ -643,4 +643,96 @@
|
||||
geted: 0, // 是否已获得, 0: 未获得, 1: 已获得
|
||||
}
|
||||
]
|
||||
```
|
||||
```
|
||||
|
||||
### 17. 邮件列表
|
||||
|
||||
1. Method: POST
|
||||
2. <span id="215">URI: /api/:accountid/mails</span>
|
||||
|
||||
| 字段 | 说明 |
|
||||
| -------- | -------------------------------------- |
|
||||
| accountid | 帐号id |
|
||||
|
||||
> POST参数
|
||||
|
||||
|
||||
| 字段 | 说明 |
|
||||
| -------- | -------------------------------------- |
|
||||
| sid | 店铺id |
|
||||
|
||||
3. Response: JSON
|
||||
|
||||
```js
|
||||
[{
|
||||
_id: '邮件id',
|
||||
title: '邮件标题',
|
||||
content: 1: '邮件正文'
|
||||
status: 0, // 邮件状态: 0: 未读 1: 已读, 2: 已领取附件
|
||||
items: [{
|
||||
itemId: '物品的id'
|
||||
name: '物品名',
|
||||
count: 1 // 数量
|
||||
}]
|
||||
}]
|
||||
```
|
||||
|
||||
### 18. 设置邮件已读
|
||||
|
||||
1. Method: POST
|
||||
2. <span id="215">URI: /api/:accountid/mail/read</span>
|
||||
|
||||
| 字段 | 说明 |
|
||||
| -------- | -------------------------------------- |
|
||||
| accountid | 帐号id |
|
||||
|
||||
> POST参数
|
||||
|
||||
|
||||
| 字段 | 说明 |
|
||||
| -------- | -------------------------------------- |
|
||||
| ids | 邮件id数组 |
|
||||
|
||||
### 19. 领取邮件附件
|
||||
|
||||
1. Method: POST
|
||||
2. <span id="215">URI: /api/:accountid/mail/attachment</span>
|
||||
|
||||
| 字段 | 说明 |
|
||||
| -------- | -------------------------------------- |
|
||||
| accountid | 帐号id |
|
||||
|
||||
> POST参数
|
||||
|
||||
|
||||
| 字段 | 说明 |
|
||||
| -------- | -------------------------------------- |
|
||||
| ids | 邮件id数组 |
|
||||
|
||||
3. Response: JSON
|
||||
|
||||
```js
|
||||
[{ // 获得的物品列表
|
||||
coupon: '优惠券的id',
|
||||
name: '优惠券名',
|
||||
count: 1, //数量
|
||||
couponUrl: '优惠券详情图的url',
|
||||
rewardType: 0, // 0: 优惠券, 1: 抽奖券
|
||||
}]
|
||||
```
|
||||
|
||||
### 20. 删除邮件
|
||||
|
||||
1. Method: POST
|
||||
2. <span id="215">URI: /api/:accountid/mail/delete</span>
|
||||
|
||||
| 字段 | 说明 |
|
||||
| -------- | -------------------------------------- |
|
||||
| accountid | 帐号id |
|
||||
|
||||
> POST参数
|
||||
|
||||
|
||||
| 字段 | 说明 |
|
||||
| -------- | -------------------------------------- |
|
||||
| ids | 邮件id数组 |
|
||||
|
83
src/api/controllers/mail.controller.ts
Normal file
83
src/api/controllers/mail.controller.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import BaseController from '../../common/base.controller'
|
||||
import { role, router } from '../../decorators/router'
|
||||
import { UserMail } from '../../models/user/UserMail'
|
||||
import { SysMail } from '../../models/content/SysMail'
|
||||
import { ZError } from '../../common/ZError'
|
||||
import { UserReward } from '../../models/user/UserReward'
|
||||
|
||||
class MailController extends BaseController {
|
||||
@role('anon')
|
||||
@router('post /api/:accountId/mails')
|
||||
async list(req: any) {
|
||||
const { accountId, sid } = req.params
|
||||
await UserMail.updateExpire(accountId)
|
||||
let mails = await UserMail.find({ accountId, deleted: false }).sort({ status: 1, _id: -1 })
|
||||
let mailSet: Set<string> = new Set()
|
||||
for (let mail of mails) {
|
||||
mailSet.add(mail.oid)
|
||||
}
|
||||
let sysMails = await SysMail.findMail(accountId, sid, [...mailSet])
|
||||
if (sysMails?.length > 0) {
|
||||
for (let _m of sysMails) {
|
||||
let mail = await UserMail.receiveOne(accountId, _m)
|
||||
mails.push(mail)
|
||||
}
|
||||
}
|
||||
return mails.map(o => o.toJson())
|
||||
}
|
||||
|
||||
@role('anon')
|
||||
@router('post /api/:accountId/mail/delete')
|
||||
async delete(req: any) {
|
||||
const { accountId, ids } = req.params
|
||||
if (!ids || !Array.isArray(ids) || ids.length === 0) {
|
||||
throw new ZError(10, 'ids必须是一个数组')
|
||||
}
|
||||
let result = await UserMail.deleteMails(accountId, ids)
|
||||
return {}
|
||||
}
|
||||
|
||||
@role('anon')
|
||||
@router('post /api/:accountId/mail/read')
|
||||
async read(req: any) {
|
||||
const { accountId, ids } = req.params
|
||||
if (!ids || !Array.isArray(ids) || ids.length === 0) {
|
||||
throw new ZError(10, 'ids必须是一个数组')
|
||||
}
|
||||
await UserMail.updateMails(accountId, ids, 1)
|
||||
return {}
|
||||
}
|
||||
|
||||
@role('anon')
|
||||
@router('post /api/:accountId/mail/attachment')
|
||||
async attachment(req: any) {
|
||||
const { accountId, ids } = req.params
|
||||
if (!ids || !Array.isArray(ids) || ids.length === 0) {
|
||||
throw new ZError(10, 'ids必须是一个数组')
|
||||
}
|
||||
let mails = await UserMail.find({ _id: { $in: ids }, deleted: false, accountId, status: { $lt: 2 } })
|
||||
if (!mails || mails.length === 0) {
|
||||
throw new ZError(11, '未找到符合条件的邮件')
|
||||
}
|
||||
let results = []
|
||||
for (let mail of mails) {
|
||||
if (mail.items && mail.items.length > 0) {
|
||||
for (let item of mail.items) {
|
||||
let record = await UserReward.saveOneRecord({
|
||||
accountId,
|
||||
shop: mail.senderShop,
|
||||
itemId: item.itemId,
|
||||
count: item.count,
|
||||
rewardId: mail._id + '',
|
||||
activityId: mail.oid + '',
|
||||
source: 'mail',
|
||||
})
|
||||
results.push(record)
|
||||
}
|
||||
mail.status = 2
|
||||
await mail.save()
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
}
|
@ -1,18 +1,99 @@
|
||||
import { dbconn } from '../../decorators/dbconn'
|
||||
import { getModelForClass, modelOptions, prop } from '@typegoose/typegoose'
|
||||
import { getModelForClass, index, modelOptions, prop } from '@typegoose/typegoose'
|
||||
import { Severity } from '@typegoose/typegoose/lib/internal/constants'
|
||||
import { BaseModule } from '../Base'
|
||||
import { noJson } from '../../decorators/nojson'
|
||||
|
||||
export class MailItemClass {
|
||||
@prop()
|
||||
public itemId: string
|
||||
|
||||
@prop()
|
||||
public name: string
|
||||
|
||||
@prop()
|
||||
public count: number
|
||||
}
|
||||
|
||||
@dbconn()
|
||||
@index({ accounts: 1, deleted: 1, type: 1, sendTime: 1, endTime: 1 }, { unique: false })
|
||||
@index({ shops: 1, deleted: 1, type: 1, sendTime: 1, endTime: 1 }, { unique: false })
|
||||
@modelOptions({
|
||||
schemaOptions: { collection: 'sys_mail', timestamps: true },
|
||||
options: { allowMixed: Severity.ALLOW },
|
||||
})
|
||||
export class SysMailClass extends BaseModule {
|
||||
@prop()
|
||||
public sender: string
|
||||
|
||||
@prop()
|
||||
public senderShop: string
|
||||
|
||||
@prop()
|
||||
public title: string
|
||||
|
||||
@prop()
|
||||
public content: string
|
||||
|
||||
/**
|
||||
* 邮件类型
|
||||
* @type {number} 0: 普通邮件 1: 店铺群发
|
||||
*/
|
||||
@prop({ default: 0 })
|
||||
public type: number
|
||||
|
||||
@prop({ type: () => [String] })
|
||||
public accounts: string[]
|
||||
|
||||
@prop({ type: () => [String] })
|
||||
public shops: string[]
|
||||
|
||||
@prop({ type: () => [MailItemClass] })
|
||||
public items: MailItemClass[]
|
||||
|
||||
/**
|
||||
* 是否删除
|
||||
* @type {boolean}
|
||||
*/
|
||||
@noJson()
|
||||
@prop({ default: false })
|
||||
public deleted: boolean
|
||||
@noJson()
|
||||
@prop()
|
||||
public deleteTime: Date
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
* @type {string}
|
||||
*/
|
||||
@prop()
|
||||
public createdBy: string
|
||||
|
||||
@prop()
|
||||
public sendTime: number
|
||||
|
||||
@prop()
|
||||
public endTime: number
|
||||
|
||||
public static async findMail(accountId: string, shop: string, excludes: string[]) {
|
||||
let now = Date.now()
|
||||
let mails0 = await SysMail.find({
|
||||
accounts: accountId,
|
||||
type: 0,
|
||||
deleted: false,
|
||||
sendTime: { $lte: now },
|
||||
endTime: { $gte: now },
|
||||
_id: { $nin: excludes },
|
||||
})
|
||||
let mails1 = await SysMail.find({
|
||||
shops: shop,
|
||||
type: 1,
|
||||
deleted: false,
|
||||
sendTime: { $lte: now },
|
||||
endTime: { $gte: now },
|
||||
_id: { $nin: excludes },
|
||||
})
|
||||
return mails0.concat(mails1)
|
||||
}
|
||||
}
|
||||
export const SysMail = getModelForClass(SysMailClass, { existingConnection: SysMailClass.db })
|
||||
|
94
src/models/user/UserMail.ts
Normal file
94
src/models/user/UserMail.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import { dbconn } from '../../decorators/dbconn'
|
||||
import { getModelForClass, index, modelOptions, prop } from '@typegoose/typegoose'
|
||||
import { Severity } from '@typegoose/typegoose/lib/internal/constants'
|
||||
import { BaseModule } from '../Base'
|
||||
import { MailItemClass } from '../content/SysMail'
|
||||
import { noJson } from '../../decorators/nojson'
|
||||
|
||||
@dbconn()
|
||||
@index({ accountId: 1, oid: 1 }, { unique: true })
|
||||
@index({ accountId: 1, deleted: 1, status: 1 }, { unique: false })
|
||||
@modelOptions({
|
||||
schemaOptions: { collection: 'user_mail', timestamps: true },
|
||||
options: { allowMixed: Severity.ALLOW },
|
||||
})
|
||||
export class UserMailClass extends BaseModule {
|
||||
@prop()
|
||||
public oid: string
|
||||
|
||||
@prop()
|
||||
public sender: string
|
||||
|
||||
@prop()
|
||||
public senderShop: string
|
||||
|
||||
@prop()
|
||||
public title: string
|
||||
|
||||
@prop()
|
||||
public content: string
|
||||
|
||||
@prop()
|
||||
public accountId: string
|
||||
|
||||
@prop({ type: () => [MailItemClass] })
|
||||
public items: MailItemClass[]
|
||||
|
||||
/**
|
||||
* 邮件状态
|
||||
* @type {number} 0: 未读 1: 已读, 2: 已领取附件
|
||||
*/
|
||||
@prop({ default: 0 })
|
||||
public status: number
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
* @type {number}
|
||||
*/
|
||||
@prop()
|
||||
public expire: number
|
||||
|
||||
/**
|
||||
* 是否删除
|
||||
* @type {boolean}
|
||||
*/
|
||||
@noJson()
|
||||
@prop({ default: false })
|
||||
public deleted: boolean
|
||||
@noJson()
|
||||
@prop()
|
||||
public deleteTime: Date
|
||||
|
||||
public static async receiveOne(accountId: string, mail: any) {
|
||||
let record = new UserMail({})
|
||||
record.oid = mail.id
|
||||
record.title = mail.title
|
||||
record.content = mail.content
|
||||
record.accountId = accountId
|
||||
record.items = mail.items
|
||||
record.sender = mail.sender
|
||||
record.senderShop = mail.senderShop
|
||||
record.expire = Date.now() + 3600 * 24 * 15 * 1000
|
||||
await record.save()
|
||||
return record
|
||||
}
|
||||
|
||||
public static async updateExpire(accountId: string) {
|
||||
await UserMail.updateMany(
|
||||
{ accountId, deleted: false, expire: { $lt: Date.now() } },
|
||||
{ $set: { deleted: true, deleteTime: new Date() } },
|
||||
)
|
||||
}
|
||||
|
||||
public static async deleteMails(accountId: string, ids: string[]) {
|
||||
return UserMail.updateMany(
|
||||
{ accountId, deleted: false, _id: { $in: ids } },
|
||||
{ $set: { deleted: true, deleteTime: new Date() } },
|
||||
)
|
||||
}
|
||||
|
||||
public static async updateMails(accountId: string, ids: string[], status: number) {
|
||||
return UserMail.updateMany({ accountId, deleted: false, _id: { $in: ids } }, { $set: { status: status } })
|
||||
}
|
||||
}
|
||||
export const UserMail = getModelForClass(UserMailClass, { existingConnection: UserMailClass.db })
|
Loading…
x
Reference in New Issue
Block a user