优化
This commit is contained in:
49
server/plugins/com.msgbyte.saleschat/models/accesslog.ts
Normal file
49
server/plugins/com.msgbyte.saleschat/models/accesslog.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 访问日志模型
|
||||
* TypeGoose 定义,符合 Tailchat 插件标准模式
|
||||
*/
|
||||
|
||||
import { db } from 'tailchat-server-sdk';
|
||||
const { getModelForClass, prop, modelOptions, TimeStamps, index } = db;
|
||||
|
||||
@modelOptions({ options: { customName: 'p_saleschat_accesslog' } })
|
||||
@index({ inviteCode: 1 })
|
||||
@index({ timestamp: 1 })
|
||||
@index({ inviteCode: 1, timestamp: -1 })
|
||||
export class AccessLog extends TimeStamps implements db.Base {
|
||||
_id: db.Types.ObjectId;
|
||||
id: string;
|
||||
|
||||
/** 邀请码 */
|
||||
@prop({ required: true })
|
||||
inviteCode: string;
|
||||
|
||||
/** 访客 ID */
|
||||
@prop()
|
||||
visitorId?: string;
|
||||
|
||||
/** 访问类型:click / scan / join */
|
||||
@prop({ required: true })
|
||||
accessType: 'click' | 'scan' | 'join';
|
||||
|
||||
/** 访问时间 */
|
||||
@prop({ default: () => new Date() })
|
||||
timestamp: Date;
|
||||
|
||||
/** IP 地址 */
|
||||
@prop()
|
||||
ipAddress?: string;
|
||||
|
||||
/** User-Agent */
|
||||
@prop()
|
||||
userAgent?: string;
|
||||
|
||||
/** 来源 */
|
||||
@prop()
|
||||
referrer?: string;
|
||||
}
|
||||
|
||||
export type AccessLogDocument = db.DocumentType<AccessLog>;
|
||||
const model = getModelForClass(AccessLog);
|
||||
export type AccessLogModel = typeof model;
|
||||
export default model;
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 删除记录模型
|
||||
* TypeGoose 定义,符合 Tailchat 插件标准模式
|
||||
*/
|
||||
|
||||
import { db } from 'tailchat-server-sdk';
|
||||
const { getModelForClass, prop, modelOptions, TimeStamps } = db;
|
||||
|
||||
@modelOptions({ options: { customName: 'p_saleschat_deletionrecord' } })
|
||||
export class DeletionRecord extends TimeStamps implements db.Base {
|
||||
_id: db.Types.ObjectId;
|
||||
id: string;
|
||||
|
||||
/** 被删除用户 ID(关联用户) */
|
||||
@prop({ required: true, ref: 'User' })
|
||||
userId: db.Types.ObjectId;
|
||||
|
||||
/** 用户名 */
|
||||
@prop()
|
||||
username?: string;
|
||||
|
||||
/** 操作人 ID(关联用户) */
|
||||
@prop({ required: true, ref: 'User' })
|
||||
deletedBy: db.Types.ObjectId;
|
||||
|
||||
/** 删除类型:soft / hard */
|
||||
@prop({ default: 'soft' })
|
||||
type: 'soft' | 'hard';
|
||||
|
||||
/** 原因 */
|
||||
@prop({ default: '无' })
|
||||
reason: string;
|
||||
|
||||
/** 删除时间 */
|
||||
@prop({ default: () => new Date() })
|
||||
deletedAt: Date;
|
||||
}
|
||||
|
||||
export type DeletionRecordDocument = db.DocumentType<DeletionRecord>;
|
||||
const model = getModelForClass(DeletionRecord);
|
||||
export type DeletionRecordModel = typeof model;
|
||||
export default model;
|
||||
30
server/plugins/com.msgbyte.saleschat/models/index.ts
Normal file
30
server/plugins/com.msgbyte.saleschat/models/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 数据模型统一导出
|
||||
* 所有模型均采用 TypeGoose + TimeStamps 模式,符合 Tailchat 插件标准
|
||||
*/
|
||||
|
||||
export {
|
||||
default as InviteModel,
|
||||
type InviteDocument,
|
||||
type InviteModel as InviteModelType,
|
||||
} from './invite';
|
||||
export {
|
||||
default as StatsModel,
|
||||
type StatsDocument,
|
||||
type StatsModel as StatsModelType,
|
||||
} from './stats';
|
||||
export {
|
||||
default as AccessLogModel,
|
||||
type AccessLogDocument,
|
||||
type AccessLogModel as AccessLogModelType,
|
||||
} from './accesslog';
|
||||
export {
|
||||
default as KickRecordModel,
|
||||
type KickRecordDocument,
|
||||
type KickRecordModel as KickRecordModelType,
|
||||
} from './kickrecord';
|
||||
export {
|
||||
default as DeletionRecordModel,
|
||||
type DeletionRecordDocument,
|
||||
type DeletionRecordModel as DeletionRecordModelType,
|
||||
} from './deletionrecord';
|
||||
62
server/plugins/com.msgbyte.saleschat/models/invite.ts
Normal file
62
server/plugins/com.msgbyte.saleschat/models/invite.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 邀请模型
|
||||
* TypeGoose 定义,符合 Tailchat 插件标准模式
|
||||
*/
|
||||
|
||||
import { db } from 'tailchat-server-sdk';
|
||||
const { getModelForClass, prop, modelOptions, TimeStamps, index } = db;
|
||||
|
||||
@modelOptions({ options: { customName: 'p_saleschat_invite' } })
|
||||
@index({ code: 1 }, { unique: true })
|
||||
@index({ salesId: 1 })
|
||||
@index({ expiresAt: 1 })
|
||||
@index({ status: 1 })
|
||||
export class Invite extends TimeStamps implements db.Base {
|
||||
_id: db.Types.ObjectId;
|
||||
id: string;
|
||||
|
||||
/** 邀请码 */
|
||||
@prop({ required: true, unique: true })
|
||||
code: string;
|
||||
|
||||
/** 销售 ID(关联用户) */
|
||||
@prop({ required: true, ref: 'User' })
|
||||
salesId: db.Types.ObjectId;
|
||||
|
||||
/** 群组 ID(关联群组) */
|
||||
@prop({ required: true, ref: 'Group' })
|
||||
groupId: db.Types.ObjectId;
|
||||
|
||||
/** 邀请链接 */
|
||||
@prop()
|
||||
link?: string;
|
||||
|
||||
/** 二维码 URL */
|
||||
@prop()
|
||||
qrCodeUrl?: string;
|
||||
|
||||
/** 过期时间 */
|
||||
@prop()
|
||||
expiresAt?: Date;
|
||||
|
||||
/** 点击次数 */
|
||||
@prop({ default: 0 })
|
||||
clickCount: number;
|
||||
|
||||
/** 扫码次数 */
|
||||
@prop({ default: 0 })
|
||||
scanCount: number;
|
||||
|
||||
/** 加入次数 */
|
||||
@prop({ default: 0 })
|
||||
joinCount: number;
|
||||
|
||||
/** 状态:active / inactive */
|
||||
@prop({ default: 'active' })
|
||||
status: 'active' | 'inactive';
|
||||
}
|
||||
|
||||
export type InviteDocument = db.DocumentType<Invite>;
|
||||
const model = getModelForClass(Invite);
|
||||
export type InviteModel = typeof model;
|
||||
export default model;
|
||||
40
server/plugins/com.msgbyte.saleschat/models/kickrecord.ts
Normal file
40
server/plugins/com.msgbyte.saleschat/models/kickrecord.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 踢人记录模型
|
||||
* TypeGoose 定义,符合 Tailchat 插件标准模式
|
||||
*/
|
||||
|
||||
import { db } from 'tailchat-server-sdk';
|
||||
const { getModelForClass, prop, modelOptions, TimeStamps, index } = db;
|
||||
|
||||
@modelOptions({ options: { customName: 'p_saleschat_kickrecord' } })
|
||||
@index({ groupId: 1, kickedAt: -1 })
|
||||
@index({ userId: 1, kickedAt: -1 })
|
||||
export class KickRecord extends TimeStamps implements db.Base {
|
||||
_id: db.Types.ObjectId;
|
||||
id: string;
|
||||
|
||||
/** 群组 ID(关联群组) */
|
||||
@prop({ required: true, ref: 'Group' })
|
||||
groupId: db.Types.ObjectId;
|
||||
|
||||
/** 被踢用户 ID(关联用户) */
|
||||
@prop({ required: true, ref: 'User' })
|
||||
userId: db.Types.ObjectId;
|
||||
|
||||
/** 操作人 ID(关联用户) */
|
||||
@prop({ required: true, ref: 'User' })
|
||||
kickedBy: db.Types.ObjectId;
|
||||
|
||||
/** 原因 */
|
||||
@prop({ default: '无' })
|
||||
reason: string;
|
||||
|
||||
/** 踢出时间 */
|
||||
@prop({ default: () => new Date() })
|
||||
kickedAt: Date;
|
||||
}
|
||||
|
||||
export type KickRecordDocument = db.DocumentType<KickRecord>;
|
||||
const model = getModelForClass(KickRecord);
|
||||
export type KickRecordModel = typeof model;
|
||||
export default model;
|
||||
47
server/plugins/com.msgbyte.saleschat/models/stats.ts
Normal file
47
server/plugins/com.msgbyte.saleschat/models/stats.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* 统计模型
|
||||
* TypeGoose 定义,符合 Tailchat 插件标准模式
|
||||
*/
|
||||
|
||||
import { db } from 'tailchat-server-sdk';
|
||||
const { getModelForClass, prop, modelOptions, TimeStamps, index } = db;
|
||||
|
||||
@modelOptions({ options: { customName: 'p_saleschat_stats' } })
|
||||
@index({ salesId: 1, date: 1, period: 1 }, { unique: true })
|
||||
export class Stats extends TimeStamps implements db.Base {
|
||||
_id: db.Types.ObjectId;
|
||||
id: string;
|
||||
|
||||
/** 销售 ID(关联用户) */
|
||||
@prop({ required: true, ref: 'User' })
|
||||
salesId: db.Types.ObjectId;
|
||||
|
||||
/** 统计日期 */
|
||||
@prop({ required: true })
|
||||
date: Date;
|
||||
|
||||
/** 统计周期:daily / weekly / monthly */
|
||||
@prop({ required: true })
|
||||
period: 'daily' | 'weekly' | 'monthly';
|
||||
|
||||
/** 创建的邀请数 */
|
||||
@prop({ default: 0 })
|
||||
invitesCreated: number;
|
||||
|
||||
/** 加入人数 */
|
||||
@prop({ default: 0 })
|
||||
joins: number;
|
||||
|
||||
/** 转化次数 */
|
||||
@prop({ default: 0 })
|
||||
conversions: number;
|
||||
|
||||
/** 收入 */
|
||||
@prop({ default: 0 })
|
||||
revenue: number;
|
||||
}
|
||||
|
||||
export type StatsDocument = db.DocumentType<Stats>;
|
||||
const model = getModelForClass(Stats);
|
||||
export type StatsModel = typeof model;
|
||||
export default model;
|
||||
Reference in New Issue
Block a user