feat: 完善后端并新增 Vue3 WebUI
后端: - 修复登录校验、DB 并发(单例+WAL+纯Go sqlite)、会话密钥持久化等核心缺陷 - 新增 Timer CRUD/签到/手动触发、执行日志、仪表盘、驱动元数据等 API - 统一驱动接口: 带 context 的执行器、真实错误返回、敏感字段掩码、连通性测试 - 补全钉钉执行器; Timer 触发/提醒去重; 配置支持默认值与环境变量覆盖 前端: - Vite+Vue3+TS+Pinia+Element Plus, 由驱动元数据动态渲染配置表单 - 登录/仪表盘(倒计时环)/定时器/规则/账号/日志/设置页面, 支持暗色模式 - 主题色 #66ccff, 信号波纹 logo, go:embed 单二进制部署 构建: Dockerfile 增加前端构建阶段; 补充各驱动配置文档 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import { api } from './client'
|
||||
import type {
|
||||
Account,
|
||||
AccountRequest,
|
||||
DashboardOverview,
|
||||
ExecutionLog,
|
||||
LogPage,
|
||||
Providers,
|
||||
Rule,
|
||||
RuleRequest,
|
||||
SiteInfo,
|
||||
Timer,
|
||||
TimerRequest,
|
||||
UserInfo,
|
||||
} from './types'
|
||||
|
||||
export const siteApi = {
|
||||
info: () => api.get<SiteInfo>('/site'),
|
||||
}
|
||||
|
||||
export const userApi = {
|
||||
register: (username: string, password: string) =>
|
||||
api.post<string>('/user/registry', { username, password }),
|
||||
login: (username: string, password: string) =>
|
||||
api.post<string>('/user/login', { username, password }),
|
||||
logout: () => api.post<string>('/user/logout'),
|
||||
info: () => api.get<UserInfo>('/user/info'),
|
||||
changePassword: (oldPassword: string, newPassword: string) =>
|
||||
api.post<string>('/user/password', {
|
||||
old_password: oldPassword,
|
||||
new_password: newPassword,
|
||||
}),
|
||||
updateNotify: (dingtalkConfig: string | null) =>
|
||||
api.put<string>('/user/notify', { dingtalk_config: dingtalkConfig }),
|
||||
}
|
||||
|
||||
export const dashboardApi = {
|
||||
overview: () => api.get<DashboardOverview>('/dashboard'),
|
||||
}
|
||||
|
||||
export const providerApi = {
|
||||
all: () => api.get<Providers>('/providers'),
|
||||
}
|
||||
|
||||
export const timerApi = {
|
||||
list: () => api.get<Timer[]>('/timers/'),
|
||||
get: (id: number) => api.get<{ timer: Timer; rule_count: number }>(`/timers/${id}`),
|
||||
create: (body: TimerRequest) => api.post<Timer>('/timers/', body),
|
||||
update: (id: number, body: TimerRequest) => api.put<Timer>(`/timers/${id}`, body),
|
||||
sign: (id: number) => api.post<Timer>(`/timers/${id}/sign`),
|
||||
signAll: () => api.post<{ signed: number; last_sign: number }>('/timers/sign'),
|
||||
trigger: (id: number) => api.post<{ total: number; failed: string[] }>(`/timers/${id}/trigger`),
|
||||
checkDelete: (id: number) => api.get<Rule[]>(`/timers/${id}/check`),
|
||||
remove: (id: number) => api.delete<string>(`/timers/${id}`),
|
||||
}
|
||||
|
||||
export const ruleApi = {
|
||||
list: (timerId?: number) =>
|
||||
api.get<Rule[]>('/rules/', timerId ? { timer_id: timerId } : undefined),
|
||||
create: (body: RuleRequest) => api.post<Rule>('/rules/', body),
|
||||
update: (id: number, body: RuleRequest) => api.put<Rule>(`/rules/${id}`, body),
|
||||
test: (id: number) => api.post<string>(`/rules/${id}/test`),
|
||||
remove: (id: number) => api.delete<string>(`/rules/${id}`),
|
||||
}
|
||||
|
||||
export const accountApi = {
|
||||
list: (type?: string) =>
|
||||
api.get<Account[]>('/accounts/', type ? { type } : undefined),
|
||||
create: (body: AccountRequest) => api.post<Account>('/accounts/', body),
|
||||
update: (id: number, body: AccountRequest) => api.put<Account>(`/accounts/${id}`, body),
|
||||
test: (id: number) => api.post<string>(`/accounts/${id}/test`),
|
||||
checkDelete: (id: number) => api.get<Rule[]>(`/accounts/${id}/check`),
|
||||
remove: (id: number) => api.delete<string>(`/accounts/${id}`),
|
||||
}
|
||||
|
||||
export const logApi = {
|
||||
list: (params: { page?: number; page_size?: number; rule_id?: number; success?: string }) =>
|
||||
api.get<LogPage>('/logs/', params),
|
||||
clear: () => api.delete<string>('/logs/'),
|
||||
}
|
||||
|
||||
export type { ExecutionLog }
|
||||
Reference in New Issue
Block a user