refactor: 重构项目模块结构与代码细节优化

1.  调整后端模块路由与插件文件结构,迁移部分模块代码至api/v1目录
2.  优化代码注释格式与文档字符串,简化冗余代码
3.  添加监控仪表盘、工单评论等新模块功能
4.  修复前端部分组件交互逻辑与类型定义
5.  清理冗余的初始化数据与废弃配置文件
6.  新增租户注册表单字段与国际化支持
7.  优化HTTP请求拦截器与快捷键功能
This commit is contained in:
zhangtao
2026-07-10 00:18:11 +08:00
parent 349ab7b525
commit 5ff72b086f
323 changed files with 7633 additions and 15306 deletions
@@ -0,0 +1,35 @@
import { request } from "@utils";
const API_PATH = "/monitor/dashboard";
export interface RecentLoginItem {
username: string;
status: number; // 1:成功 2:失败
login_time: string;
login_ip?: string;
login_location?: string;
}
export interface DashboardStats {
online_users: number;
total_users: number;
total_tenants: number;
total_orders: number;
today_login_count: number;
today_unique_users: number;
week_user_created: number;
week_tenant_created: number;
paid_orders: number;
recent_logins: RecentLoginItem[];
}
const DashboardAPI = {
getStats() {
return request<ApiResponse<DashboardStats>>({
url: `${API_PATH}/stats`,
method: "get",
});
},
};
export default DashboardAPI;
@@ -1,238 +0,0 @@
import { request } from "@utils";
const API_PATH = "/platform/email";
const EmailAPI = {
// ─── SMTP 配置 ────────────────────────────────────────────
listConfig(query?: EmailConfigPageQuery) {
return request<ApiResponse<PageResult<EmailConfigTable>>>({
url: `${API_PATH}/config/list`,
method: "get",
params: query,
});
},
detailConfig(id: number) {
return request<ApiResponse<EmailConfigTable>>({
url: `${API_PATH}/config/detail/${id}`,
method: "get",
});
},
createConfig(body: EmailConfigCreateForm) {
return request<ApiResponse>({
url: `${API_PATH}/config/create`,
method: "post",
data: body,
});
},
updateConfig(id: number, body: EmailConfigUpdateForm) {
return request<ApiResponse>({
url: `${API_PATH}/config/update/${id}`,
method: "put",
data: body,
});
},
deleteConfig(ids: number[]) {
return request<ApiResponse>({
url: `${API_PATH}/config/delete`,
method: "delete",
data: ids,
});
},
testConfig(body: EmailTestForm) {
return request<ApiResponse>({
url: `${API_PATH}/config/test`,
method: "post",
data: body,
});
},
// ─── 邮件模板 ────────────────────────────────────────────
listTemplate(query?: EmailTemplatePageQuery) {
return request<ApiResponse<PageResult<EmailTemplateTable>>>({
url: `${API_PATH}/template/list`,
method: "get",
params: query,
});
},
detailTemplate(id: number) {
return request<ApiResponse<EmailTemplateTable>>({
url: `${API_PATH}/template/detail/${id}`,
method: "get",
});
},
createTemplate(body: EmailTemplateCreateForm) {
return request<ApiResponse>({
url: `${API_PATH}/template/create`,
method: "post",
data: body,
});
},
updateTemplate(id: number, body: EmailTemplateUpdateForm) {
return request<ApiResponse>({
url: `${API_PATH}/template/update/${id}`,
method: "put",
data: body,
});
},
deleteTemplate(ids: number[]) {
return request<ApiResponse>({
url: `${API_PATH}/template/delete`,
method: "delete",
data: ids,
});
},
// ─── 手动发送 ────────────────────────────────────────────
sendEmail(body: EmailSendForm) {
return request<ApiResponse>({
url: `${API_PATH}/send`,
method: "post",
data: body,
});
},
// ─── 发送日志 ────────────────────────────────────────────
listLog(query?: EmailLogPageQuery) {
return request<ApiResponse<PageResult<EmailLogTable>>>({
url: `${API_PATH}/log/list`,
method: "get",
params: query,
});
},
};
export default EmailAPI;
// ─── EmailConfig 类型 ──────────────────────────────────────
export interface EmailConfigPageQuery extends PageQuery, UserByQueryParams {
name?: string;
is_default?: boolean;
}
export interface EmailConfigTable extends BaseType {
name: string;
smtp_host: string;
smtp_port: number;
smtp_user: string;
from_name: string;
use_tls: boolean;
is_default: boolean;
timeout: number;
status?: number;
description?: string;
}
export interface EmailConfigCreateForm {
name: string;
smtp_host: string;
smtp_port: number;
smtp_user: string;
smtp_password: string;
from_name?: string;
use_tls?: boolean;
is_default?: boolean;
timeout?: number;
status?: number;
description?: string;
}
export interface EmailConfigUpdateForm {
name?: string;
smtp_host?: string;
smtp_port?: number;
smtp_user?: string;
smtp_password?: string;
from_name?: string;
use_tls?: boolean;
is_default?: boolean;
timeout?: number;
status?: number;
description?: string;
}
export interface EmailTestForm {
config_id: number;
to_email: string;
}
// ─── EmailTemplate 类型 ──────────────────────────────────────
export interface EmailTemplatePageQuery extends PageQuery, UserByQueryParams {
name?: string;
template_code?: string;
}
export interface EmailTemplateTable extends BaseType {
name: string;
template_code: string;
subject: string;
body_html: string;
body_text?: string;
variables?: string;
status?: number;
description?: string;
}
export interface EmailTemplateCreateForm {
name: string;
template_code: string;
subject: string;
body_html: string;
body_text?: string;
variables?: string;
description?: string;
}
export interface EmailTemplateUpdateForm {
name?: string;
template_code?: string;
subject?: string;
body_html?: string;
body_text?: string;
variables?: string;
description?: string;
}
// ─── EmailLog 类型 ──────────────────────────────────────────
export interface EmailLogPageQuery extends PageQuery, UserByQueryParams {
to_email?: string;
biz_type?: string;
template_code?: string;
status?: number;
}
export interface EmailLogTable {
id: number;
config_id?: number;
template_code?: string;
to_email: string;
to_name?: string;
subject: string;
biz_type: string;
status: number;
error_msg?: string;
retry_count: number;
tenant_id?: number;
created_time?: string;
sent_time?: string;
}
export interface EmailSendForm {
to_email: string;
to_name?: string;
template_code: string;
variables?: Record<string, unknown>;
config_id?: number;
biz_type?: string;
}
@@ -1,33 +1,8 @@
import { request } from "@utils";
const API_PATH = "/invoice";
const API_PATH = "/platform/invoice";
const InvoiceAPI = {
// ─── 平台端 ───
listInvoices(query?: InvoicePageQuery) {
return request<ApiResponse<{ list: InvoiceTable[]; total: number }>>({
url: `${API_PATH}/list`,
method: "get",
params: query,
});
},
issueInvoice(invoiceId: number, body: { pdf_url?: string; api_response?: string }) {
return request<ApiResponse>({
url: `${API_PATH}/issue/${invoiceId}`,
method: "put",
data: body,
});
},
voidInvoice(invoiceId: number, reason?: string) {
return request<ApiResponse>({
url: `${API_PATH}/void/${invoiceId}`,
method: "put",
data: { description: reason },
});
},
// ─── 租户端 ───
tenantListInvoices(query?: InvoicePageQuery) {
return request<ApiResponse<{ list: InvoiceTable[]; total: number }>>({
@@ -74,8 +49,6 @@ export interface InvoiceTable {
bank_info?: string;
address_info?: string;
pdf_url?: string;
oss_license_pdf_url?: string;
api_response?: string;
description?: string;
created_time?: string;
}
+19 -43
View File
@@ -61,18 +61,9 @@ const OrderAPI = {
});
},
// ─── 支付记录 ───
listPaymentRecords(query?: PageQuery) {
return request<ApiResponse<{ items: PaymentRecordTable[]; total: number }>>({
url: `${API_PATH}/record/list`,
method: "get",
params: query,
});
},
// ─── 退款管理 ───
listRefunds(query?: RefundPageQuery) {
return request<ApiResponse<{ items: RefundTable[]; total: number }>>({
return request<ApiResponse<{ items: OrderTable[]; total: number }>>({
url: `${API_PATH}/refund/list`,
method: "get",
params: query,
@@ -98,7 +89,6 @@ const OrderAPI = {
tenantCreateOrder(body: {
tenant_id: number;
package_id?: number;
plugin_id?: number;
order_type: string;
pay_method?: string;
}) {
@@ -125,6 +115,7 @@ export default OrderAPI;
export interface OrderPageQuery extends PageQuery, TenantByQueryParams {
order_type?: string;
status?: number;
refund_status?: number;
}
export interface OrderTable {
@@ -132,7 +123,6 @@ export interface OrderTable {
order_no: string;
tenant_id: number;
package_id?: number;
plugin_id?: number;
order_type: string;
amount: number;
period_count: number;
@@ -141,45 +131,31 @@ export interface OrderTable {
pay_time?: string;
expire_time: string;
created_time?: string;
// 支付信息
transaction_id?: string;
raw_response?: string;
// 退款信息
refund_no?: string;
refund_amount?: number;
refund_reason?: string;
refund_transaction_id?: string;
reviewer_id?: number;
review_time?: string;
reject_reason?: string;
refund_status?: number;
}
export interface OrderCreateForm {
tenant_id: number;
package_id?: number;
plugin_id?: number;
order_type: "new" | "renew" | "upgrade" | "downgrade" | "plugin";
order_type: "new" | "renew" | "upgrade" | "downgrade";
pay_method?: string;
}
// ─── Payment 类型 ────────────────────────────────────────
// ─── Refund 类型(复用 OrderTable 的退款字段)─────────────
export interface PaymentRecordTable {
id: number;
order_id: number;
transaction_id?: string;
pay_method: string;
amount: number;
status: number;
pay_time?: string;
created_time?: string;
}
// ─── Refund 类型 ─────────────────────────────────────────
export interface RefundPageQuery extends PageQuery, UserByQueryParams, TenantByQueryParams {
export interface RefundPageQuery extends PageQuery {
status?: number;
}
export interface RefundTable {
id: number;
order_id: number;
refund_no: string;
amount: number;
reason: string;
status: number;
refund_transaction_id?: string;
reviewer_id?: number;
review_time?: string;
reject_reason?: string;
created_time?: string;
}
@@ -65,20 +65,12 @@ const PackageAPI = {
});
},
getPackagePlugins(packageId: number) {
return request<ApiResponse<number[]>>({
url: `${API_PATH}/plugins/${packageId}`,
getPackageOptions() {
return request<ApiResponse<OptionType[]>>({
url: `${API_PATH}/options`,
method: "get",
});
},
setPackagePlugins(packageId: number, pluginIds: number[]) {
return request<ApiResponse>({
url: `${API_PATH}/plugins/${packageId}/set`,
method: "post",
data: { plugin_ids: pluginIds },
});
},
};
export default PackageAPI;
@@ -1,142 +0,0 @@
import { request } from "@utils";
const API_PATH = "/platform/plugin";
const PluginAPI = {
// 超管:插件列表
list(page: PageQuery, search?: PluginQueryParam) {
return request<ApiResponse<PageResult<PluginTable>>>({
url: `${API_PATH}/list`,
method: "get",
params: { ...page, ...search },
});
},
// 超管:插件详情
detail(id: number) {
return request<ApiResponse<PluginTable>>({
url: `${API_PATH}/detail/${id}`,
method: "get",
});
},
// 超管:创建插件
create(body: PluginForm) {
return request<ApiResponse<PluginTable>>({
url: `${API_PATH}/create`,
method: "post",
data: body,
});
},
// 超管:更新插件
update(id: number, body: PluginForm) {
return request<ApiResponse<PluginTable>>({
url: `${API_PATH}/update/${id}`,
method: "put",
data: body,
});
},
// 超管:删除插件
delete(ids: number[]) {
return request<ApiResponse>({
url: `${API_PATH}/delete`,
method: "delete",
data: ids,
});
},
// 租户:插件市场
marketplace(page: PageQuery, category?: string) {
return request<ApiResponse<PageResult<PluginTable>>>({
url: `${API_PATH}/marketplace`,
method: "get",
params: { ...page, category },
});
},
// 租户:安装插件
install(pluginId: number) {
return request<ApiResponse>({
url: `${API_PATH}/install`,
method: "post",
data: { plugin_id: pluginId },
});
},
// 租户:卸载插件
uninstall(pluginId: number) {
return request<ApiResponse>({
url: `${API_PATH}/uninstall`,
method: "post",
data: { plugin_id: pluginId },
});
},
// 租户:启用/禁用插件
toggle(pluginId: number) {
return request<ApiResponse>({
url: `${API_PATH}/toggle`,
method: "post",
data: { plugin_id: pluginId },
});
},
// 租户:我的插件
myPlugins() {
return request<ApiResponse<PluginTable[]>>({
url: `${API_PATH}/my`,
method: "get",
});
},
// 超管:热重载插件路由
reload() {
return request<ApiResponse<string>>({
url: `${API_PATH}/reload`,
method: "post",
});
},
};
export default PluginAPI;
export interface PluginQueryParam extends PageQuery, UserByQueryParams, TenantByQueryParams {
name?: string;
category?: string;
status?: number;
}
export interface PluginTable extends BaseType {
name: string;
code: string;
category?: string;
icon?: string;
version?: string;
price?: number;
installed?: boolean;
author?: string;
menu_path?: string;
permission_prefix?: string;
dependencies?: string;
sort?: number;
status?: number;
description?: string;
}
export interface PluginForm extends BaseFormType {
name?: string;
code?: string;
category?: string;
icon?: string;
version?: string;
price?: number;
sort?: number;
author?: string;
menu_path?: string;
permission_prefix?: string;
dependencies?: string;
status?: number;
description?: string;
}
@@ -177,15 +177,6 @@ const TenantAPI = {
method: "get",
});
},
/** 购买付费插件 */
purchasePlugin(body: { plugin_id: number; pay_method?: string }) {
return request<ApiResponse<{ id: number; order_no: string }>>({
url: `${API_PATH}/plugin/purchase`,
method: "post",
data: body,
});
},
};
export default TenantAPI;
@@ -61,6 +61,24 @@ const AuthAPI = {
data: { tenant_id: tenantId },
});
},
/** 返回平台管理模式,清除 tenant_id 返回平台作用域 JWT */
enterPlatform() {
return request<ApiResponse<SelectTenantResult>>({
url: `${API_PATH}/enter-platform`,
method: "post",
});
},
/** 平台管理员代签入(以指定租户身份登录) */
impersonate(tenantId: number) {
return request<ApiResponse<ImpersonateResult>>({
url: `${API_PATH}/impersonate`,
method: "post",
data: { tenant_id: tenantId },
});
},
/** 租户自助注册(PRD §4.5) */
tenantRegister(body: TenantRegisterForm) {
return request<ApiResponse<TenantRegisterResult>>({
@@ -69,6 +87,23 @@ const AuthAPI = {
data: body,
});
},
/** 根据编码查询租户 */
lookupTenant(code: string) {
return request<ApiResponse>({
url: `${API_PATH}/tenant/${encodeURIComponent(code)}`,
method: "get",
});
},
/** 根据域名查询租户 */
lookupTenantByDomain(domain: string) {
return request<ApiResponse>({
url: `${API_PATH}/tenant-by-domain`,
method: "get",
params: { domain },
});
},
};
export default AuthAPI;
@@ -140,6 +175,16 @@ export interface SelectTenantResult {
expires_in: number;
}
/** 平台管理员代签入返回 (ImpersonateOutSchema) */
export interface ImpersonateResult {
access_token: string;
refresh_token: string;
token_type: string;
expires_in: number;
tenant_id: number;
tenant_name: string;
}
/** 验证码信息 */
export interface CaptchaInfo {
enable: boolean;
@@ -44,6 +44,7 @@ export interface OperationLogPageQuery extends PageQuery, UserByQueryParams, Ten
request_path?: string;
creator_name?: string;
status?: number;
request_ip?: string;
}
export interface OperationLogTable {
@@ -56,6 +57,7 @@ export interface OperationLogTable {
response_json?: Record<string, unknown> | string;
process_time?: string;
created_time?: string;
request_ip?: string;
}
// ==================== 登录日志 ====================
@@ -56,43 +56,6 @@ const NoticeAPI = {
data: body,
});
},
exportNotice(body: NoticePageQuery) {
return request<Blob>({
url: `${API_PATH}/export`,
method: "post",
data: body,
responseType: "blob",
});
},
readNotice(id: number) {
return request<ApiResponse>({
url: `${API_PATH}/read/${id}`,
method: "post",
});
},
readAllNotice() {
return request<ApiResponse>({
url: `${API_PATH}/read-all`,
method: "post",
});
},
getUnreadCount() {
return request<ApiResponse<number>>({
url: `${API_PATH}/unread-count`,
method: "get",
});
},
getNotificationPanel() {
return request<ApiResponse<NotificationPanel>>({
url: `${API_PATH}/panel`,
method: "get",
});
},
};
export default NoticeAPI;
@@ -118,17 +81,3 @@ export interface NoticeForm extends BaseFormType {
status?: number;
description?: string;
}
export interface NotificationPanelMessage {
id?: number;
title: string;
content?: string;
time: string;
type?: string;
}
export interface NotificationPanel {
notices: NoticeTable[];
messages: NotificationPanelMessage[];
pendings: NotificationPanelMessage[];
}
@@ -58,6 +58,13 @@ const PositionAPI = {
responseType: "blob",
});
},
getPositionOptions() {
return request<ApiResponse<OptionType[]>>({
url: `${API_PATH}/options`,
method: "get",
});
},
};
export default PositionAPI;
@@ -66,6 +66,13 @@ const RoleAPI = {
responseType: "blob",
});
},
getRoleOptions() {
return request<ApiResponse<OptionType[]>>({
url: `${API_PATH}/options`,
method: "get",
});
},
};
export default RoleAPI;
@@ -35,6 +35,22 @@ const TicketAPI = {
},
};
export function getTicketComments(ticketId: number, params?: PageQuery) {
return request<ApiResponse<PageResult<TicketCommentTable>>>({
url: `${API_PATH}/${ticketId}/comments`,
method: "get",
params,
});
}
export function createTicketComment(ticketId: number, data: TicketCommentCreateForm) {
return request<ApiResponse<TicketCommentTable>>({
url: `${API_PATH}/${ticketId}/comments`,
method: "post",
data,
});
}
export default TicketAPI;
export interface TicketPageQuery extends PageQuery, UserByQueryParams {
@@ -88,3 +104,18 @@ export interface TicketForm extends BaseFormType {
status?: number;
description?: string;
}
// ─── 评论 ───
export interface TicketCommentTable extends BaseType {
ticket_id: number;
content: string;
created_by_name?: string;
}
export interface TicketCommentPageQuery extends PageQuery {
ticket_id: number;
}
export interface TicketCommentCreateForm {
content: string;
}
+5 -11
View File
@@ -44,14 +44,6 @@ export const UserAPI = {
});
},
registerUser(body: RegisterForm) {
return request<ApiResponse<UserInfo>>({
url: `${API_PATH}/register`,
method: "post",
data: body,
});
},
forgetPassword(body: ForgetPasswordForm) {
return request<ApiResponse>({
url: `${API_PATH}/password/forget`,
@@ -139,6 +131,7 @@ export const UserAPI = {
export default UserAPI;
export interface ForgetPasswordForm {
tenant_name: string;
username: string;
new_password: string;
mobile?: string;
@@ -146,6 +139,7 @@ export interface ForgetPasswordForm {
}
export interface RegisterForm {
tenant_name: string;
username: string;
password: string;
confirmPassword: string;
@@ -184,12 +178,12 @@ export interface UserInfo extends BaseType {
position_names?: positionSelectorType["name"][];
position_ids?: positionSelectorType["id"][];
is_superuser?: boolean;
is_impersonate?: boolean;
last_login?: string;
created_by?: CommonType;
updated_by?: CommonType;
deleted_by?: CommonType;
tenant_id?: number;
tenant_name?: string;
tenant_by?: CommonType;
gitee_login?: string;
github_login?: string;
wx_login?: string;
@@ -237,7 +231,7 @@ export interface InfoFormState {
updated_time?: string;
status?: number;
description?: string;
tenant_by?: { id?: number; name?: string };
tenant_by?: CommonType;
gitee_login?: string;
github_login?: string;
wx_login?: string;
@@ -0,0 +1,84 @@
import { request } from "@utils";
const API_PATH = "/system/versions";
const VersionAPI = {
getVersionList(query: VersionPageQuery) {
return request<ApiResponse<PageResult<VersionTable>>>({
url: `${API_PATH}/list`,
method: "get",
params: query,
});
},
getPublishedVersions() {
return request<ApiResponse<VersionTable[]>>({ url: `${API_PATH}/published`, method: "get" });
},
getVersionDetail(query: number) {
return request<ApiResponse<VersionTable>>({
url: `${API_PATH}/detail/${query}`,
method: "get",
});
},
createVersion(body: VersionForm) {
return request<ApiResponse>({
url: `${API_PATH}/create`,
method: "post",
data: body,
});
},
updateVersion(id: number, body: VersionForm) {
return request<ApiResponse>({
url: `${API_PATH}/update/${id}`,
method: "put",
data: body,
});
},
deleteVersion(body: number[]) {
return request<ApiResponse>({
url: `${API_PATH}/delete`,
method: "delete",
data: body,
});
},
setVersionStatus(id: number, body: { status: number }) {
return request<ApiResponse<VersionTable>>({
url: `${API_PATH}/${id}/status`,
method: "put",
data: body,
});
},
};
export default VersionAPI;
export interface VersionPageQuery extends PageQuery {
status?: number;
}
export interface VersionTable extends BaseType {
version?: string;
title?: string;
date?: string;
content?: string;
description?: string;
sort?: number;
status?: number;
require_re_login?: boolean;
}
export interface VersionForm extends BaseFormType {
version?: string;
title?: string;
date?: string;
content?: string;
description?: string;
sort?: number;
status?: number;
require_re_login?: boolean;
}