✨ 新功能: - 添加Telegram Bot通知支持 - 账目记录自动推送到Telegram - 支持多个Bot配置管理 - 支持群组和个人通知 📊 数据库: - 新增telegram_notification_configs表 - 存储Bot配置和通知类型 🔧 后端API: - GET /api/telegram/notifications - 获取所有配置 - POST /api/telegram/notifications - 创建配置 - PUT /api/telegram/notifications/:id - 更新配置 - DELETE /api/telegram/notifications/:id - 删除配置 - POST /api/telegram/test - 测试Bot配置 💬 通知功能: - 自动发送账目记录通知 - 包含交易类型、金额、分类、账户等信息 - 支持格式化显示(类型图标、状态标识) - 配置创建时自动测试有效性 📝 文档: - 添加完整的使用说明文档 - API接口说明和示例 - 常见问题解答
102 lines
3.0 KiB
TypeScript
102 lines
3.0 KiB
TypeScript
import { readBody } from 'h3';
|
||
import {
|
||
createTransaction,
|
||
type TransactionStatus,
|
||
} from '~/utils/finance-repository';
|
||
import { useResponseError, useResponseSuccess } from '~/utils/response';
|
||
import { notifyTransactionWebhook } from '~/utils/telegram-webhook';
|
||
import { notifyTransaction } from '~/utils/telegram-bot';
|
||
import db from '~/utils/sqlite';
|
||
|
||
const DEFAULT_CURRENCY = 'CNY';
|
||
const ALLOWED_STATUSES: TransactionStatus[] = [
|
||
'draft',
|
||
'pending',
|
||
'approved',
|
||
'rejected',
|
||
'paid',
|
||
];
|
||
|
||
export default defineEventHandler(async (event) => {
|
||
const body = await readBody(event);
|
||
|
||
if (!body?.type || !body?.amount || !body?.transactionDate) {
|
||
return useResponseError('缺少必填字段', -1);
|
||
}
|
||
|
||
const amount = Number(body.amount);
|
||
if (Number.isNaN(amount)) {
|
||
return useResponseError('金额格式不正确', -1);
|
||
}
|
||
|
||
const status =
|
||
(body.status as TransactionStatus | undefined) ?? 'approved';
|
||
if (!ALLOWED_STATUSES.includes(status)) {
|
||
return useResponseError('状态值不合法', -1);
|
||
}
|
||
|
||
const transaction = createTransaction({
|
||
type: body.type,
|
||
amount,
|
||
currency: body.currency ?? DEFAULT_CURRENCY,
|
||
categoryId: body.categoryId ?? null,
|
||
accountId: body.accountId ?? null,
|
||
transactionDate: body.transactionDate,
|
||
description: body.description ?? '',
|
||
project: body.project ?? null,
|
||
memo: body.memo ?? null,
|
||
status,
|
||
reimbursementBatch: body.reimbursementBatch ?? null,
|
||
reviewNotes: body.reviewNotes ?? null,
|
||
submittedBy: body.submittedBy ?? null,
|
||
approvedBy: body.approvedBy ?? null,
|
||
statusUpdatedAt: body.statusUpdatedAt ?? undefined,
|
||
approvedAt: body.approvedAt ?? undefined,
|
||
});
|
||
|
||
// 发送Webhook通知(保留原有功能)
|
||
notifyTransactionWebhook(transaction, { action: 'created' }).catch((error) =>
|
||
console.error('[finance][transactions.post] webhook notify failed', error),
|
||
);
|
||
|
||
// 发送Telegram通知(新功能)
|
||
try {
|
||
// 获取分类和账户名称
|
||
let categoryName: string | undefined;
|
||
let accountName: string | undefined;
|
||
|
||
if (transaction.categoryId) {
|
||
const category = db
|
||
.prepare<{ name: string }>('SELECT name FROM finance_categories WHERE id = ?')
|
||
.get(transaction.categoryId);
|
||
categoryName = category?.name;
|
||
}
|
||
|
||
if (transaction.accountId) {
|
||
const account = db
|
||
.prepare<{ name: string }>('SELECT name FROM finance_accounts WHERE id = ?')
|
||
.get(transaction.accountId);
|
||
accountName = account?.name;
|
||
}
|
||
|
||
await notifyTransaction(
|
||
{
|
||
id: transaction.id,
|
||
type: transaction.type,
|
||
amount: transaction.amount,
|
||
currency: transaction.currency,
|
||
categoryName,
|
||
accountName,
|
||
transactionDate: transaction.transactionDate,
|
||
description: transaction.description || undefined,
|
||
status: transaction.status,
|
||
},
|
||
'created',
|
||
);
|
||
} catch (error) {
|
||
console.error('[finance][transactions.post] telegram notify failed', error);
|
||
}
|
||
|
||
return useResponseSuccess(transaction);
|
||
});
|