新增邮件群发和数据可视化

This commit is contained in:
eoao
2025-06-17 09:20:00 +08:00
parent ea309f9171
commit 605829f180
65 changed files with 2352 additions and 900 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -6,8 +6,8 @@
<title></title>
<link rel="icon" href="/assets/favicon-C5dAZutX.svg" type="image/svg+xml">
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<script type="module" crossorigin src="/assets/index-CWszkgaK.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-ii38gjPC.css">
<script type="module" crossorigin src="/assets/index-74wu16JB.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-iIoGrcM-.css">
</head>
<body>
<div id="loading-first">

View File

@@ -18,3 +18,7 @@ app.post('/account/add', async (c) => {
return c.json(result.ok(account));
});
app.put('/account/setName', async (c) => {
await accountService.setName(c, await c.req.json(), userContext.getUserId(c));
return c.json(result.ok());
});

View File

@@ -0,0 +1,8 @@
import app from '../hono/hono';
import analysisService from '../service/analysis-service';
import result from '../model/result';
app.get('/analysis/echarts', async (c) => {
const data = await analysisService.echarts(c);
return c.json(result.ok(data));
})

View File

@@ -1,5 +1,5 @@
import app from '../hono/hono';
import initService from '../service/init-service';
import initService from '../init/init';
app.get('/init/:secret', (c) => {
return initService.init(c);

View File

@@ -1,6 +1,7 @@
const KvConst = {
AUTH_INFO: 'auth-uid:',
SETTING: 'setting:',
SEND_DAY_COUNT: 'send_day_count:'
}
export default KvConst;

View File

@@ -0,0 +1,104 @@
const analysisDao = {
async numberCount(c) {
const { results } = await c.env.db.prepare(`
SELECT
e.receiveTotal,
e.sendTotal,
e.delReceiveTotal,
e.delSendTotal,
e.normalReceiveTotal,
e.normalSendTotal,
u.userTotal,
u.normalUserTotal,
u.delUserTotal,
a.accountTotal,
a.normalAccountTotal,
a.delAccountTotal
FROM
(
SELECT
SUM(CASE WHEN type = 0 THEN 1 ELSE 0 END) AS receiveTotal,
SUM(CASE WHEN type = 1 THEN 1 ELSE 0 END) AS sendTotal,
SUM(CASE WHEN type = 0 AND is_del = 1 THEN 1 ELSE 0 END) AS delReceiveTotal,
SUM(CASE WHEN type = 1 AND is_del = 1 THEN 1 ELSE 0 END) AS delSendTotal,
SUM(CASE WHEN type = 0 AND is_del = 0 THEN 1 ELSE 0 END) AS normalReceiveTotal,
SUM(CASE WHEN type = 1 AND is_del = 0 THEN 1 ELSE 0 END) AS normalSendTotal
FROM
email
) e
CROSS JOIN (
SELECT
COUNT(*) AS userTotal,
SUM(CASE WHEN is_del = 1 THEN 1 ELSE 0 END) AS delUserTotal,
SUM(CASE WHEN is_del = 0 THEN 1 ELSE 0 END) AS normalUserTotal
FROM
user
) u
CROSS JOIN (
SELECT
COUNT(*) AS accountTotal,
SUM(CASE WHEN is_del = 1 THEN 1 ELSE 0 END) AS delAccountTotal,
SUM(CASE WHEN is_del = 0 THEN 1 ELSE 0 END) AS normalAccountTotal
FROM
account
) a
`).all();
return results[0];
},
async userDayCount(c) {
const { results } = await c.env.db.prepare(`
SELECT
DATE(create_time,'+8 hours') AS date,
COUNT(*) AS total
FROM
user
WHERE
DATE(create_time,'+8 hours') BETWEEN DATE('now', '-14 days', '+8 hours') AND DATE('now','-1 day','+8 hours')
GROUP BY
DATE(create_time,'+8 hours')
ORDER BY
date ASC
`).all();
return results;
},
async receiveDayCount(c) {
const { results } = await c.env.db.prepare(`
SELECT
DATE(create_time,'+8 hours') AS date,
COUNT(*) AS total
FROM
email
WHERE
DATE(create_time,'+8 hours') BETWEEN DATE('now', '-14 days', '+8 hours') AND DATE('now','-1 day','+8 hours')
AND type = 0
GROUP BY
DATE(create_time,'+8 hours')
ORDER BY
date ASC
`).all();
return results;
},
async sendDayCount(c) {
const { results } = await c.env.db.prepare(`
SELECT
DATE(create_time,'+8 hours') AS date,
COUNT(*) AS total
FROM
email
WHERE
DATE(create_time,'+8 hours') BETWEEN DATE('now', '-14 days', '+8 hours') AND DATE('now','-1 day','+8 hours')
AND type = 1
GROUP BY
DATE(create_time,'+8 hours')
ORDER BY
date ASC
`).all();
return results;
}
};
export default analysisDao;

View File

@@ -28,13 +28,20 @@ export async function email(message, env, ctx) {
const email = await PostalMime.parse(content);
console.warn(email)
const params = {
sendEmail: email.from.address,
name: email.from.name,
receiveEmail: message.to,
subject: email.subject,
content: email.html,
text: email.text,
cc: email.cc ? JSON.stringify(email.cc) : '[]',
bcc:email.bcc ? JSON.stringify(email.bcc) : '[]',
recipient: JSON.stringify(email.to),
inReplyTo: email.inReplyTo,
relation: email.references,
messageId: email.messageId,
userId: account.userId,
accountId: account.accountId,
isDel: isDel.DELETE,

View File

@@ -3,6 +3,7 @@ import { sql } from 'drizzle-orm';
export const account = sqliteTable('account', {
accountId: integer('account_id').primaryKey({ autoIncrement: true }),
email: text('email').notNull(),
name: text('name').notNull().default(''),
status: integer('status').default(0).notNull(),
latestEmailTime: text('latest_email_time'),
createTime: text('create_time').default(sql`CURRENT_TIMESTAMP`),

View File

@@ -4,12 +4,17 @@ export const email = sqliteTable('email', {
emailId: integer('email_id').primaryKey({ autoIncrement: true }),
sendEmail: text('send_email'),
name: text('name'),
receiveEmail: text('receive_email').notNull(),
accountId: integer('account_id').notNull(),
userId: integer('user_id').notNull(),
subject: text('subject'),
text: text('text'),
content: text('content'),
cc: text('cc').default('[]'),
bcc: text('bcc').default('[]'),
recipient: text('recipient'),
inReplyTo: text('in_reply_to').default(''),
relation: text('relation').default(''),
messageId: text('message_id').default(''),
type: integer('type').default(0).notNull(),
status: integer('status').default(0).notNull(),
resendEmailId: text('resend_email_id'),

View File

@@ -15,4 +15,5 @@ import '../api/my-api';
import '../api/role-api'
import '../api/sys-email-api'
import '../api/init-api'
import '../api/analysis-api'
export default app;

View File

@@ -1,6 +1,6 @@
import settingService from './setting-service';
const initService = {
import settingService from '../service/setting-service';
import emailUtils from '../utils/email-utils';
const init = {
async init(c) {
const secret = c.req.param('secret');
@@ -10,12 +10,53 @@ const initService = {
}
await this.intDB(c);
await this.v1DB(c);
await this.v1_1DB(c);
await this.v1_2DB(c);
await settingService.refresh(c);
return c.text('初始化成功');
},
async v1DB(c) {
async v1_2DB(c){
const ADD_COLUMN_SQL_LIST = [
`ALTER TABLE email ADD COLUMN recipient TEXT NOT NULL DEFAULT '[]';`,
`ALTER TABLE email ADD COLUMN cc TEXT NOT NULL DEFAULT '[]';`,
`ALTER TABLE email ADD COLUMN bcc TEXT NOT NULL DEFAULT '[]';`,
`ALTER TABLE email ADD COLUMN message_id TEXT NOT NULL DEFAULT '';`,
`ALTER TABLE email ADD COLUMN in_reply_to TEXT NOT NULL DEFAULT '';`,
`ALTER TABLE email ADD COLUMN relation TEXT NOT NULL DEFAULT '';`
];
for (let sql of ADD_COLUMN_SQL_LIST) {
try {
await c.env.db.prepare(sql).run();
} catch (e) {
console.warn(`跳过字段添加,原因:${e.message}`);
}
}
await this.receiveEmailToRecipient(c);
await this.initAccountName(c);
try {
await c.env.db.prepare(`
INSERT INTO perm (perm_id, name, perm_key, pid, type, sort) VALUES
(31,'分析页', NULL, 0, 1, 2.1),
(32,'数据查看', 'analysis:query', 31, 2, 1)`).run();
} catch (e) {
console.warn(`跳过数据,原因:${e.message}`);
}
try {
await c.env.db.prepare(`CREATE UNIQUE INDEX IF NOT EXISTS idx_account_email ON account (email)`).run();
await c.env.db.prepare(`CREATE UNIQUE INDEX IF NOT EXISTS idx_user_email ON user (email)`).run();
} catch (e) {
console.warn(`跳过添加唯一邮箱索引,原因:${e.message}`);
}
},
async v1_1DB(c) {
// 添加字段
const ADD_COLUMN_SQL_LIST = [
`ALTER TABLE email ADD COLUMN type INTEGER NOT NULL DEFAULT 0;`,
@@ -81,7 +122,6 @@ const initService = {
(11, '用户删除', 'user:delete', 6, 2, 7),
(12, '用户收藏', 'user:star', 6, 2, 5),
(13, '权限控制', '', 0, 1, 5),
(30, '身份添加', 'role:add', 13, 2, -1),
(14, '身份查看', 'role:query', 13, 2, 0),
(15, '身份修改', 'role:set', 13, 2, 1),
(16, '身份删除', 'role:delete', 13, 2, 2),
@@ -97,7 +137,8 @@ const initService = {
(26, '发件重置', 'user:reset-send', 6, 2, 6),
(27, '邮件列表', '', 0, 1, 4),
(28, '邮件查看', 'sys-email:query', 27, 2, 0),
(29, '邮件删除', 'sys-email:delete', 27, 2, 0)
(29, '邮件删除', 'sys-email:delete', 27, 2, 0),
(30, '身份添加', 'role:add', 13, 2, -1)
`).run();
}
@@ -163,7 +204,6 @@ const initService = {
email_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
send_email TEXT,
name TEXT,
receive_email TEXT NOT NULL,
account_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
subject TEXT,
@@ -247,7 +287,55 @@ const initService = {
SELECT 0, 0, 0, 1, 'Cloud 邮箱', 0, 1, 1
WHERE NOT EXISTS (SELECT 1 FROM setting)
`).run();
},
async receiveEmailToRecipient(c) {
const receiveEmailColumn = await c.env.db.prepare(`SELECT * FROM pragma_table_info('email') WHERE name = 'receive_email' limit 1`).first();
if (!receiveEmailColumn) {
return
}
const queryList = []
const {results} = await c.env.db.prepare('SELECT receive_email,email_id FROM email').all();
results.forEach(emailRow => {
const recipient = {}
recipient.address = emailRow.receive_email
recipient.name = ''
const recipientStr = JSON.stringify([recipient]);
const sql = c.env.db.prepare('UPDATE email SET recipient = ? WHERE email_id = ?').bind(recipientStr,emailRow.email_id);
queryList.push(sql)
})
queryList.push(c.env.db.prepare("ALTER TABLE email DROP COLUMN receive_email"));
await c.env.db.batch(queryList);
},
async initAccountName(c) {
const nameColumn = await c.env.db.prepare(`SELECT * FROM pragma_table_info('account') WHERE name = 'name' limit 1`).first();
if (nameColumn) {
return
}
const queryList = []
queryList.push(c.env.db.prepare(`ALTER TABLE account ADD COLUMN name TEXT NOT NULL DEFAULT ''`));
const {results} = await c.env.db.prepare(`SELECT account_id, email FROM account`).all();
results.forEach(accountRow => {
const name = emailUtils.getName(accountRow.email);
const sql = c.env.db.prepare('UPDATE account SET name = ? WHERE account_id = ?').bind(name,accountRow.account_id);
queryList.push(sql)
})
await c.env.db.batch(queryList);
}
};
export default initService;
export default init;

View File

@@ -65,7 +65,8 @@ const premKey = {
'sys-email:delete': ['/sys-email/delete'],
'setting:query': [],
'setting:set': ['/setting/set', '/setting/setBackground'],
'setting:clean': ['/setting/physicsDeleteAll']
'setting:clean': ['/setting/physicsDeleteAll'],
'analysis:query': ['/analysis/echarts']
};
app.use('*', async (c, next) => {

View File

@@ -5,7 +5,7 @@ import userService from './user-service';
import emailService from './email-service';
import orm from '../entity/orm';
import account from '../entity/account';
import { and, asc, eq, gt, inArray, count, like } from 'drizzle-orm';
import { and, asc, eq, gt, inArray, count, sql } from 'drizzle-orm';
import { isDel } from '../const/entity-const';
import settingService from './setting-service';
import turnstileService from './turnstile-service';
@@ -33,7 +33,7 @@ const accountService = {
throw new BizError('不存在的邮箱域名');
}
const accountRow = await this.selectByEmailIncludeDel(c, email);
const accountRow = await this.selectByEmailIncludeDelNoCase(c, email);
if (accountRow && accountRow.isDel === isDel.DELETE) {
throw new BizError('该邮箱已被注销');
@@ -55,9 +55,16 @@ const accountService = {
await turnstileService.verify(c, token);
}
return orm(c).insert(account).values({ email: email, userId: userId }).returning().get();
return orm(c).insert(account).values({ email: email, userId: userId, name: emailUtils.getName(email) }).returning().get();
},
selectByEmailIncludeDelNoCase(c, email) {
return orm(c)
.select()
.from(account)
.where(sql`${account.email} COLLATE NOCASE = ${email}`)
.get();
},
selectByEmailIncludeDel(c, email) {
return orm(c).select().from(account).where(eq(account.email, email)).get();
},
@@ -170,6 +177,11 @@ const accountService = {
async restoreByUserId(c, userId) {
await orm(c).update(account).set({isDel: isDel.NORMAL}).where(eq(account.userId, userId)).run();
},
async setName(c, params, userId) {
const { name, accountId } = params
await orm(c).update(account).set({name}).where(and(eq(account.userId, userId),eq(account.accountId, accountId))).run();
}
};

View File

@@ -0,0 +1,88 @@
import analysisDao from '../dao/analysis-dao';
import orm from '../entity/orm';
import email from '../entity/email';
import { desc, count, eq } from 'drizzle-orm';
import { emailConst } from '../const/entity-const';
import kvConst from '../const/kv-const';
import dayjs from 'dayjs';
import timezone from 'dayjs/plugin/timezone'
import utc from 'dayjs/plugin/utc'
dayjs.extend(utc)
dayjs.extend(timezone)
const analysisService = {
async echarts(c) {
const [
numberCount,
nameRatio,
sendEmailRatio,
userDayCountRaw,
receiveDayCountRaw,
sendDayCountRaw,
daySendTotalRaw
] = await Promise.all([
analysisDao.numberCount(c),
orm(c)
.select({ name: email.name, total: count() })
.from(email)
.where(eq(email.type, emailConst.type.RECEIVE))
.groupBy(email.name)
.orderBy(desc(count()))
.limit(6),
orm(c)
.select({ email: email.sendEmail, total: count() })
.from(email)
.where(eq(email.type, emailConst.type.RECEIVE))
.groupBy(email.sendEmail)
.orderBy(desc(count()))
.limit(6),
analysisDao.userDayCount(c),
analysisDao.receiveDayCount(c),
analysisDao.sendDayCount(c),
c.env.kv.get(kvConst.SEND_DAY_COUNT + dayjs().format('YYYY-MM-DD')),
]);
const userDayCount = this.filterEmptyDay(userDayCountRaw);
const receiveDayCount = this.filterEmptyDay(receiveDayCountRaw);
const sendDayCount = this.filterEmptyDay(sendDayCountRaw);
const daySendTotal = daySendTotalRaw || 0;
return {
numberCount,
userDayCount,
receiveRatio: {
nameRatio,
sendEmailRatio
},
emailDayCount: {
receiveDayCount,
sendDayCount
},
daySendTotal: Number(daySendTotal)
};
},
filterEmptyDay(data) {
const today = dayjs().tz('Asia/Shanghai').subtract(1, 'day');
const previousDays = Array.from({ length: 15 }, (_, i) => {
return today.subtract(i, 'day').format('YYYY-MM-DD');
}).reverse();
return previousDays.map(day => {
const index = data.findIndex(item => item.date === day)
const total = index > - 1 ? data[index].total : 0
return {date: day,total}
})
}
}
export default analysisService

View File

@@ -15,6 +15,9 @@ import roleService from './role-service';
import user from '../entity/user';
import account from '../entity/account';
import starService from './star-service';
import dayjs from 'dayjs';
import kvConst from '../const/kv-const';
import constant from '../const/constant';
const emailService = {
@@ -146,11 +149,10 @@ const emailService = {
async send(c, params, userId) {
let { accountId, name, receiveEmail, text, content, subject, attachments } = params;
let { accountId, name, sendType, emailId, receiveEmail, manyType, text, content, subject, attachments } = params;
const { resendTokens, r2Domain, send } = await settingService.query(c);
const { attDataList, html } = await attService.toImageUrlHtml(c, content, r2Domain);
if (attDataList.length > 0 && !r2Domain) {
@@ -173,13 +175,26 @@ const emailService = {
throw new BizError('邮箱发送功能已停用', 403);
}
if (attachments.length > 0 && manyType === 'divide') {
throw new BizError('分别发送暂时不支持附件');
}
const userRow = await userService.selectById(c, userId);
const roleRow = await roleService.selectById(c, userRow.type);
if (userRow.sendCount >= roleRow.sendCount && c.env.admin !== userRow.email) {
if (roleRow.sendType === 'day') throw new BizError('已到达每日发送数量限制', 403);
if (roleRow.sendType === 'count') throw new BizError('已到达发送数量限制', 403);
if (c.env.admin !== userRow.email && roleRow.sendCount) {
if (userRow.sendCount >= roleRow.sendCount) {
if (roleRow.sendType === 'day') throw new BizError('已到达每日发送次数限制', 403);
if (roleRow.sendType === 'count') throw new BizError('已到达发送次数限制', 403);
}
if (userRow.sendCount + receiveEmail.length > roleRow.sendCount) {
if (roleRow.sendType === 'day') throw new BizError('剩余每日发送次数不足', 403);
if (roleRow.sendType === 'count') throw new BizError('剩余发送次数不足', 403);
}
}
@@ -203,53 +218,161 @@ const emailService = {
name = emailUtils.getName(accountRow.email);
}
let emailRow = {
messageId: null
};
if (sendType === 'reply') {
emailRow = await this.selectById(c, emailId);
if (!emailRow) {
throw new BizError('邮件不存在无法回复');
}
}
let resendResult = null;
const resend = new Resend(resendToken);
const { data, error } = await resend.emails.send({
from: `${name} <${accountRow.email}>`,
to: [receiveEmail],
subject: subject,
text: text,
html: html,
attachments: attachments
});
if (manyType === 'divide') {
let sendFormList = [];
receiveEmail.forEach(email => {
const sendForm = {
from: `${name} <${accountRow.email}>`,
to: [email],
subject: subject,
text: text,
html: html
};
if (sendType === 'reply') {
sendForm.headers = {
'in-reply-to': emailRow.messageId,
'references': emailRow.messageId
};
}
sendFormList.push(sendForm);
});
resendResult = await resend.batch.send(sendFormList);
} else {
const sendForm = {
from: `${name} <${accountRow.email}>`,
to: [...receiveEmail],
subject: subject,
text: text,
html: html,
attachments: attachments
};
if (sendType === 'reply') {
sendForm.headers = {
'in-reply-to': emailRow.messageId,
'references': emailRow.messageId
};
}
resendResult = await resend.emails.send(sendForm);
}
const { data, error } = resendResult;
if (error) {
console.error(error);
throw new BizError(error.message);
}
const emailData = {};
emailData.sendEmail = accountRow.email;
emailData.name = name;
emailData.subject = subject;
emailData.receiveEmail = receiveEmail;
emailData.content = html;
emailData.text = text;
emailData.accountId = accountId;
emailData.type = emailConst.type.SEND;
emailData.userId = userId;
emailData.status = emailConst.status.SENT;
emailData.resendEmailId = data.id;
const emailRow = await orm(c).insert(email).values(emailData).returning().get();
const emailDataList = [];
if (attDataList.length > 0) {
await attService.saveArticleAtt(c, attDataList, userId, accountId, emailRow.emailId);
if (manyType === 'divide') {
receiveEmail.forEach((item, index) => {
const emailDataItem = { ...emailData };
emailDataItem.resendEmailId = data.data[index].id;
emailDataItem.recipient = JSON.stringify([{ address: item, name: '' }]);
emailDataList.push(emailDataItem);
});
} else {
emailData.resendEmailId = data.id;
const recipient = [];
receiveEmail.forEach(item => {
recipient.push({ address: item, name: '' });
});
emailData.recipient = JSON.stringify(recipient);
emailDataList.push(emailData);
}
if (sendType === 'reply') {
emailDataList.forEach(emailData => {
emailData.inReplyTo = emailRow.messageId;
emailData.relation = emailRow.messageId;
});
}
if (roleRow.sendCount) {
await userService.incrUserService(c, 1, userId);
await userService.incrUserSendCount(c, receiveEmail.length, userId);
}
if (attachments?.length > 0 && c.env.r2) {
await attService.saveSendAtt(c, attachments, userId, accountId, emailRow.emailId);
const emailRowList = await Promise.all(
emailDataList.map(async (emailData) => {
const emailRow = await orm(c).insert(email).values(emailData).returning().get();
if (attDataList.length > 0) {
await attService.saveArticleAtt(c, attDataList, userId, accountId, emailRow.emailId);
}
if (attachments?.length > 0 && c.env.r2) {
await attService.saveSendAtt(c, attachments, userId, accountId, emailRow.emailId);
}
const attsList = await attService.selectByEmailIds(c, [emailRow.emailId]);
emailRow.attList = attsList;
return emailRow;
})
);
const dateStr = dayjs().format('YYYY-MM-DD');
let daySendTotal = await c.env.kv.get(kvConst.SEND_DAY_COUNT + dateStr);
if (!daySendTotal) {
await c.env.kv.put(kvConst.SEND_DAY_COUNT + dateStr, JSON.stringify(receiveEmail.length), { expirationTtl: 60 * 60 * 24 });
} else {
daySendTotal = Number(daySendTotal) + receiveEmail.length
await c.env.kv.put(kvConst.SEND_DAY_COUNT + dateStr, JSON.stringify(daySendTotal), { expirationTtl: 60 * 60 * 24 });
}
const attsList = await attService.selectByEmailIds(c, [emailRow.emailId]);
emailRow.attList = attsList;
return emailRow;
return emailRowList;
},
selectById(c, emailId) {
@@ -398,7 +521,7 @@ const emailService = {
conditions.push(like(email.subject, `${subject}%`));
}
conditions.push(ne(email.status, emailConst.status.SAVING))
conditions.push(ne(email.status, emailConst.status.SAVING));
const countConditions = [...conditions];
@@ -447,7 +570,10 @@ const emailService = {
},
async completeReceive(c, emailId) {
await orm(c).update(email).set({ isDel: isDel.NORMAL, status: emailConst.status.RECEIVE }).where(eq(email.emailId, emailId)).run();
await orm(c).update(email).set({
isDel: isDel.NORMAL,
status: emailConst.status.RECEIVE
}).where(eq(email.emailId, emailId)).run();
}
};

View File

@@ -38,7 +38,7 @@ const loginService = {
throw new BizError('非法邮箱域名');
}
const accountRow = await accountService.selectByEmailIncludeDel(c, email);
const accountRow = await accountService.selectByEmailIncludeDelNoCase(c, email);
if (accountRow && accountRow.isDel === isDel.DELETE) {
throw new BizError('该邮箱已被注销');
@@ -60,7 +60,7 @@ const loginService = {
await userService.updateUserInfo(c, userId, true);
await accountService.insert(c, { userId: userId, email });
await accountService.insert(c, { userId: userId, email, name: emailUtils.getName(email) });
},
async login(c, params) {
@@ -110,7 +110,6 @@ const loginService = {
}
await userService.updateUserInfo(c, userRow.userId);
await c.env.kv.put(KvConst.AUTH_INFO + userRow.userId, JSON.stringify(authInfo), { expirationTtl: constant.TOKEN_EXPIRE });

View File

@@ -33,6 +33,7 @@ const userService = {
user.sendCount = userRow.sendCount;
user.email = userRow.email;
user.accountId = account.accountId;
user.name = account.name;
user.permKeys = permKeys;
user.role = roleRow
@@ -304,7 +305,7 @@ const userService = {
},
async incrUserService(c, quantity, userId) {
async incrUserSendCount(c, quantity, userId) {
await orm(c).update(user).set({
sendCount: sql`${user.sendCount}
+
@@ -352,7 +353,7 @@ const userService = {
const userId = await userService.insert(c, { email, password: hash, salt, type });
await accountService.insert(c, { userId: userId, email, type });
await accountService.insert(c, { userId: userId, email, type, name: emailUtils.getName(email) });
},
async resetDaySendCount(c) {