qing-client 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ import { AxiosInstance, RawAxiosRequestHeaders } from 'axios';
2
+ import { UserContext, ClientConfig, RequestOptions, TokenStorage, PaginatedResponse } from '../types';
3
+ export declare abstract class BaseClient {
4
+ protected config: ClientConfig;
5
+ protected serviceName: string;
6
+ protected axiosInstance: AxiosInstance;
7
+ protected userContext?: UserContext;
8
+ protected isFrontendMode: boolean;
9
+ protected serviceBasePath: string;
10
+ protected tokenStorage: TokenStorage;
11
+ constructor(config: ClientConfig, serviceName: string);
12
+ initUserContext(context: UserContext): RawAxiosRequestHeaders;
13
+ setUserContext(context: UserContext): this;
14
+ setTokenStorage(storage: TokenStorage): this;
15
+ private getBaseUrl;
16
+ setToken(token: string): Promise<void>;
17
+ clearToken(): Promise<void>;
18
+ protected request<T>(path: string, options?: RequestOptions): Promise<T>;
19
+ protected paginatedRequest<T>(path: string, options?: RequestOptions): Promise<PaginatedResponse<T>>;
20
+ private handleApiError;
21
+ }
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BaseClient = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ // 默认内存存储实现
9
+ const memoryTokenStorage = {
10
+ token: undefined,
11
+ async getToken() {
12
+ return this.token;
13
+ },
14
+ async setToken(token) {
15
+ this.token = token;
16
+ },
17
+ async clearToken() {
18
+ this.token = undefined;
19
+ }
20
+ };
21
+ class BaseClient {
22
+ constructor(config, serviceName) {
23
+ this.config = config;
24
+ this.serviceName = serviceName;
25
+ this.isFrontendMode = !!config.gatewayUrl;
26
+ this.serviceBasePath = `/api/${serviceName}`;
27
+ // 设置令牌存储
28
+ this.tokenStorage = config.tokenStorage || memoryTokenStorage;
29
+ // 创建Axios实例
30
+ this.axiosInstance = axios_1.default.create({
31
+ baseURL: this.getBaseUrl(),
32
+ timeout: 30000,
33
+ headers: {
34
+ 'Content-Type': 'application/json',
35
+ 'Accept': 'application/json'
36
+ }
37
+ });
38
+ // 添加请求拦截器
39
+ this.axiosInstance.interceptors.request.use(async (config) => {
40
+ let headers = config.headers || {};
41
+ // 1. 注入用户上下文(后端模式)
42
+ if (!this.isFrontendMode && this.userContext)
43
+ headers = {
44
+ ...headers,
45
+ ...this.initUserContext(this.userContext)
46
+ };
47
+ // 2. 注入认证令牌
48
+ const token = await this.tokenStorage.getToken();
49
+ if (token) {
50
+ headers['Authorization'] = `Bearer ${token}`;
51
+ }
52
+ // 合并自定义头
53
+ if (config.headers) {
54
+ Object.assign(headers, config.headers);
55
+ }
56
+ return {
57
+ ...config,
58
+ headers
59
+ };
60
+ });
61
+ }
62
+ initUserContext(context) {
63
+ return {
64
+ 'v-user-id': context.userId,
65
+ 'v-user-role': context.role,
66
+ 'v-project-id': context.projectId
67
+ };
68
+ }
69
+ // 设置用户上下文(后端模式使用)
70
+ setUserContext(context) {
71
+ this.userContext = context;
72
+ return this;
73
+ }
74
+ // 设置令牌存储(可在运行时更换存储策略)
75
+ setTokenStorage(storage) {
76
+ this.tokenStorage = storage;
77
+ return this;
78
+ }
79
+ // 确定请求基础URL
80
+ getBaseUrl() {
81
+ if (this.isFrontendMode) {
82
+ return this.config.gatewayUrl;
83
+ }
84
+ // 后端模式使用服务专属URL
85
+ switch (this.serviceName) {
86
+ case 'auth': return this.config.authServiceUrl;
87
+ case 'msg': return this.config.msgServiceUrl;
88
+ case 'users': return this.config.userServiceUrl;
89
+ case 'file': return this.config.fileServiceUrl;
90
+ case 'survey': return this.config.surveyServiceUrl;
91
+ case 'token': return this.config.tokenServiceUrl;
92
+ default: throw new Error(`Unsupported service: ${this.serviceName}`);
93
+ }
94
+ }
95
+ // 设置认证令牌
96
+ async setToken(token) {
97
+ await this.tokenStorage.setToken(token);
98
+ }
99
+ // 清除认证令牌
100
+ async clearToken() {
101
+ await this.tokenStorage.clearToken();
102
+ }
103
+ // 统一请求方法 - 处理标准API响应
104
+ async request(path, options = { method: 'GET' }) {
105
+ try {
106
+ const fullPath = this.isFrontendMode
107
+ ? `${this.serviceBasePath}${path}`
108
+ : path;
109
+ let headers = options.headers || {};
110
+ const context = options.userContext || this.userContext;
111
+ if (context) {
112
+ headers = { ...headers, ...this.initUserContext(context) };
113
+ }
114
+ const response = await this.axiosInstance.request({
115
+ url: fullPath,
116
+ method: options.method,
117
+ headers,
118
+ params: options.params,
119
+ data: options.body
120
+ });
121
+ console.log('Request URL:', this.getBaseUrl() + fullPath);
122
+ console.log('Request params:', options.params);
123
+ // 检查业务成功状态
124
+ if (!response.data.success) {
125
+ throw new Error(response.data.message || `业务请求失败`);
126
+ }
127
+ // 返回实际数据
128
+ return response.data.data;
129
+ }
130
+ catch (error) {
131
+ // 明确返回错误处理
132
+ return this.handleApiError(error, path);
133
+ }
134
+ }
135
+ // 分页请求方法 - 处理分页API响应
136
+ async paginatedRequest(path, options = { method: 'GET' }) {
137
+ try {
138
+ const fullPath = this.isFrontendMode
139
+ ? `${this.serviceBasePath}${path}`
140
+ : path;
141
+ const response = await this.axiosInstance.request({
142
+ url: fullPath,
143
+ method: options.method,
144
+ headers: options.headers,
145
+ params: options.params,
146
+ data: options.body
147
+ });
148
+ // 检查业务成功状态
149
+ if (!response.data.success) {
150
+ throw new Error(response.data.message || `业务请求失败`);
151
+ }
152
+ // 返回分页数据 - 直接返回整个data部分
153
+ return response.data;
154
+ }
155
+ catch (error) {
156
+ this.handleApiError(error, path);
157
+ }
158
+ }
159
+ // 统一错误处理方法
160
+ handleApiError(error, path) {
161
+ let errorMessage = `[${this.serviceName}服务] `;
162
+ if (error.response) {
163
+ const responseData = error.response.data;
164
+ // 尝试从响应体中提取错误信息
165
+ if (responseData?.message) {
166
+ errorMessage += responseData.message;
167
+ }
168
+ else if (responseData?.error) {
169
+ errorMessage += responseData.error;
170
+ }
171
+ else {
172
+ errorMessage += `请求失败,状态码: ${error.response.status}`;
173
+ }
174
+ // 添加详细错误信息(开发环境)
175
+ if (process.env.NODE_ENV === 'development') {
176
+ errorMessage += ` | 状态码: ${error.response.status}`;
177
+ if (error.response.headers?.['x-request-id']) {
178
+ errorMessage += ` | 请求ID: ${error.response.headers['x-request-id']}`;
179
+ }
180
+ }
181
+ }
182
+ else if (error.request) {
183
+ errorMessage += '服务器未响应';
184
+ }
185
+ else {
186
+ errorMessage += error.message;
187
+ }
188
+ // 添加路径信息
189
+ errorMessage += ` (路径: ${path})`;
190
+ // 明确抛出错误
191
+ throw new Error(errorMessage);
192
+ }
193
+ }
194
+ exports.BaseClient = BaseClient;
@@ -0,0 +1,14 @@
1
+ import { AuthService } from "../srvice/AuthService";
2
+ import { MsgService } from "../srvice/MsgService";
3
+ import { TokenService } from "../srvice/TokenService";
4
+ import { UserService } from "../srvice/UserService";
5
+ import { ClientConfig, UserContext } from "../types";
6
+ export declare class Client {
7
+ protected config: ClientConfig;
8
+ readonly auth: AuthService;
9
+ readonly msg: MsgService;
10
+ readonly user: UserService;
11
+ readonly token: TokenService;
12
+ constructor(config: ClientConfig);
13
+ setUserContext(context: UserContext): this;
14
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Client = void 0;
4
+ const AuthService_1 = require("../srvice/AuthService");
5
+ const MsgService_1 = require("../srvice/MsgService");
6
+ const TokenService_1 = require("../srvice/TokenService");
7
+ const UserService_1 = require("../srvice/UserService");
8
+ class Client {
9
+ constructor(config) {
10
+ this.config = config;
11
+ this.auth = new AuthService_1.AuthService(config);
12
+ this.msg = new MsgService_1.MsgService(config);
13
+ this.user = new UserService_1.UserService(config);
14
+ this.token = new TokenService_1.TokenService(config);
15
+ }
16
+ setUserContext(context) {
17
+ this.auth.setUserContext(context);
18
+ this.msg.setUserContext(context);
19
+ this.user.setUserContext(context);
20
+ this.token.setUserContext(context);
21
+ return this;
22
+ }
23
+ }
24
+ exports.Client = Client;
package/lib/index.d.ts ADDED
File without changes
package/lib/index.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,8 @@
1
+ import { BaseClient } from "../client/BaseClient";
2
+ import { ClientConfig, RequestOptions } from "../types";
3
+ import { LoginResponse } from "../types/user";
4
+ export declare class AuthService extends BaseClient {
5
+ constructor(config: ClientConfig);
6
+ login(identifier: string, password: string, projectId?: number, options?: RequestOptions): Promise<LoginResponse>;
7
+ logout(token: string, options?: RequestOptions): Promise<void>;
8
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AuthService = void 0;
7
+ const BaseClient_1 = require("../client/BaseClient");
8
+ const qs_1 = __importDefault(require("qs"));
9
+ class AuthService extends BaseClient_1.BaseClient {
10
+ constructor(config) {
11
+ super(config, 'auth');
12
+ }
13
+ // 用户登录 - 匹配后端请求格式
14
+ async login(identifier, password, projectId = 0, options) {
15
+ const body = qs_1.default.stringify({
16
+ grant_type: "password",
17
+ username: identifier,
18
+ password
19
+ });
20
+ return this.request('/login', {
21
+ ...options,
22
+ method: 'POST',
23
+ headers: {
24
+ ...options?.headers,
25
+ "Content-Type": "application/x-www-form-urlencoded"
26
+ },
27
+ params: {
28
+ project_id: projectId
29
+ },
30
+ body: body
31
+ });
32
+ }
33
+ // 用户登出 - 匹配后端请求格式
34
+ async logout(token, options) {
35
+ return this.request('/logout', {
36
+ ...options,
37
+ method: 'POST',
38
+ headers: {
39
+ ...options?.headers,
40
+ Authorization: `Bearer ${token}`
41
+ }
42
+ });
43
+ }
44
+ }
45
+ exports.AuthService = AuthService;
@@ -0,0 +1,8 @@
1
+ import { BaseClient } from "../client/BaseClient";
2
+ import { ClientConfig, RequestOptions } from "../types";
3
+ import { FeishuMessage, MailRequest } from "../types/msg";
4
+ export declare class MsgService extends BaseClient {
5
+ constructor(config: ClientConfig);
6
+ sendMail(request: MailRequest, options?: RequestOptions): Promise<void>;
7
+ sendFeishuMessage(message: FeishuMessage, options?: RequestOptions): Promise<void>;
8
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MsgService = void 0;
4
+ const BaseClient_1 = require("../client/BaseClient");
5
+ class MsgService extends BaseClient_1.BaseClient {
6
+ constructor(config) {
7
+ super(config, 'msg');
8
+ }
9
+ // 发送邮件 - 返回实际结果
10
+ async sendMail(request, options) {
11
+ return this.request('/mail/send', {
12
+ ...options,
13
+ method: 'POST',
14
+ body: request
15
+ });
16
+ }
17
+ // 发送飞书消息 - 返回实际结果
18
+ async sendFeishuMessage(message, options) {
19
+ return this.request('/webhook/feishu/send', {
20
+ ...options,
21
+ method: 'POST',
22
+ body: message
23
+ });
24
+ }
25
+ }
26
+ exports.MsgService = MsgService;
@@ -0,0 +1,10 @@
1
+ import { BaseClient } from "../client/BaseClient";
2
+ import { ClientConfig, RequestOptions } from "../types";
3
+ import { WxOfficialAccountTokenResponse, WxJsapiTicketResponse, WxSignatureRequest, WxSignatureResponse, WxMiniProgramTokenResponse } from "../types/token";
4
+ export declare class TokenService extends BaseClient {
5
+ constructor(config: ClientConfig);
6
+ getWxOfficialAccountToken(appid: string, options?: RequestOptions): Promise<WxOfficialAccountTokenResponse>;
7
+ getWxJsapiTicket(appid: string, options?: RequestOptions): Promise<WxJsapiTicketResponse>;
8
+ getWxSignature(signatureRequest: WxSignatureRequest, options?: RequestOptions): Promise<WxSignatureResponse>;
9
+ getWxMiniProgramToken(appid: string, options?: RequestOptions): Promise<WxMiniProgramTokenResponse>;
10
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TokenService = void 0;
4
+ const BaseClient_1 = require("../client/BaseClient");
5
+ class TokenService extends BaseClient_1.BaseClient {
6
+ constructor(config) {
7
+ super(config, 'token');
8
+ }
9
+ // 获取微信公众号access_token
10
+ async getWxOfficialAccountToken(appid, options) {
11
+ return this.request('/wxh5/accesstoken', {
12
+ ...options,
13
+ method: 'GET',
14
+ params: { appid }
15
+ });
16
+ }
17
+ // 获取微信公众号jsapi_ticket
18
+ async getWxJsapiTicket(appid, options) {
19
+ return this.request('/wxh5/jsapi_ticket', {
20
+ ...options,
21
+ method: 'GET',
22
+ params: { appid }
23
+ });
24
+ }
25
+ // 获取微信公众号签名
26
+ async getWxSignature(signatureRequest, options) {
27
+ return this.request('/wxh5/signature', {
28
+ ...options,
29
+ method: 'POST',
30
+ body: signatureRequest
31
+ });
32
+ }
33
+ // 获取微信小程序access_token
34
+ async getWxMiniProgramToken(appid, options) {
35
+ return this.request('/wxmp/accesstoken', {
36
+ ...options,
37
+ method: 'GET',
38
+ params: { appid }
39
+ });
40
+ }
41
+ }
42
+ exports.TokenService = TokenService;
@@ -0,0 +1,10 @@
1
+ import { BaseClient } from "../client/BaseClient";
2
+ import { ClientConfig, RequestOptions, PaginatedResponse } from "../types";
3
+ import { User, UserCreateRequest, UserUpdateRequest } from "../types/user";
4
+ export declare class UserService extends BaseClient {
5
+ constructor(config: ClientConfig);
6
+ getCurrentUser(options?: RequestOptions): Promise<User>;
7
+ createUser(userData: UserCreateRequest, options?: RequestOptions): Promise<User>;
8
+ updateUser(userId: number, updateData: UserUpdateRequest, options?: RequestOptions): Promise<User>;
9
+ listUsers(includeInactive?: boolean, page?: number, perPage?: number, options?: RequestOptions): Promise<PaginatedResponse<User>>;
10
+ }
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserService = void 0;
4
+ const BaseClient_1 = require("../client/BaseClient");
5
+ class UserService extends BaseClient_1.BaseClient {
6
+ constructor(config) {
7
+ super(config, 'users');
8
+ }
9
+ // 获取当前用户信息 - 返回完整响应
10
+ async getCurrentUser(options) {
11
+ return this.request('/me', {
12
+ ...options,
13
+ method: 'GET'
14
+ });
15
+ }
16
+ // 创建用户(管理员) - 匹配后端请求格式
17
+ async createUser(userData, options) {
18
+ return this.request('', {
19
+ ...options,
20
+ method: 'POST',
21
+ body: {
22
+ username: userData.username,
23
+ email: userData.email,
24
+ password: userData.password,
25
+ name: userData.name,
26
+ role: userData.role,
27
+ phone: userData.phone,
28
+ project_id: userData.project_id
29
+ }
30
+ });
31
+ }
32
+ // 更新用户信息 - 匹配后端请求格式
33
+ async updateUser(userId, updateData, options) {
34
+ return this.request(`/${userId}`, {
35
+ ...options,
36
+ method: 'PUT',
37
+ body: {
38
+ name: updateData.name,
39
+ avatar: updateData.avatar,
40
+ phone: updateData.phone,
41
+ role: updateData.role,
42
+ project_id: updateData.project_id
43
+ }
44
+ });
45
+ }
46
+ // 获取用户列表(管理员) - 返回分页数据
47
+ async listUsers(includeInactive = false, page = 1, perPage = 10, options) {
48
+ const response = await this.paginatedRequest('', {
49
+ ...options,
50
+ method: 'GET',
51
+ params: {
52
+ include_inactive: includeInactive,
53
+ page,
54
+ per_page: perPage
55
+ }
56
+ });
57
+ // 直接返回分页响应
58
+ return response;
59
+ }
60
+ }
61
+ exports.UserService = UserService;
@@ -0,0 +1,44 @@
1
+ export interface ApiResponse<T = any> {
2
+ success: boolean;
3
+ message: string;
4
+ data: T;
5
+ }
6
+ export interface Pagination {
7
+ page: number;
8
+ per_page: number;
9
+ total: number;
10
+ total_pages: number;
11
+ }
12
+ export interface PaginatedResponse<T> {
13
+ data: T[];
14
+ success: boolean;
15
+ message: string;
16
+ pagination: Pagination;
17
+ }
18
+ export interface TokenStorage {
19
+ getToken(): Promise<string | undefined>;
20
+ setToken(token: string): Promise<void>;
21
+ clearToken(): Promise<void>;
22
+ }
23
+ export interface ClientConfig {
24
+ gatewayUrl?: string;
25
+ authServiceUrl?: string;
26
+ msgServiceUrl?: string;
27
+ userServiceUrl?: string;
28
+ fileServiceUrl?: string;
29
+ surveyServiceUrl?: string;
30
+ tokenServiceUrl?: string;
31
+ tokenStorage?: TokenStorage;
32
+ }
33
+ export interface UserContext {
34
+ userId: string;
35
+ role: 'SUPER_ADMIN' | 'ADMIN' | 'STAFF' | 'USER' | 'SYSTEM';
36
+ projectId: string;
37
+ }
38
+ export interface RequestOptions {
39
+ method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
40
+ headers?: Record<string, string>;
41
+ params?: Record<string, any>;
42
+ body?: any;
43
+ userContext?: UserContext;
44
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,31 @@
1
+ export interface MailRequest {
2
+ to: string[];
3
+ subject: string;
4
+ text?: string;
5
+ html?: string;
6
+ from?: string;
7
+ cc?: string[];
8
+ bcc?: string[];
9
+ attachments?: Array<{
10
+ filename: string;
11
+ content: string;
12
+ contentType?: string;
13
+ }>;
14
+ }
15
+ export interface FeishuMessage {
16
+ url: string;
17
+ title?: string;
18
+ bgColor?: string;
19
+ elements: Array<{
20
+ title: string;
21
+ text: string;
22
+ color?: string;
23
+ }>;
24
+ noticeUser?: Array<{
25
+ userId: string;
26
+ }>;
27
+ actions?: Array<{
28
+ text: string;
29
+ url: string;
30
+ }>;
31
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,22 @@
1
+ export interface WxOfficialAccountTokenResponse {
2
+ access_token: string;
3
+ }
4
+ export interface WxJsapiTicketResponse {
5
+ jsapi_ticket: string;
6
+ }
7
+ export interface WxSignatureRequest {
8
+ appid: string;
9
+ url: string;
10
+ imgUrl?: string;
11
+ }
12
+ export interface WxSignatureResponse {
13
+ appId: string;
14
+ timestamp: number;
15
+ nonceStr: string;
16
+ signature: string;
17
+ url: string;
18
+ imgUrl: string;
19
+ }
20
+ export interface WxMiniProgramTokenResponse {
21
+ access_token: string;
22
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,37 @@
1
+ export interface User {
2
+ id: number;
3
+ username: string;
4
+ email: string;
5
+ name?: string;
6
+ avatar?: string;
7
+ phone?: string;
8
+ role: string;
9
+ project_id: number;
10
+ is_active: boolean;
11
+ last_login_ip?: string;
12
+ last_login?: string;
13
+ created_at: string;
14
+ updated_at: string;
15
+ }
16
+ export interface UserCreateRequest {
17
+ username: string;
18
+ email: string;
19
+ password: string;
20
+ name?: string;
21
+ role?: string;
22
+ phone?: string;
23
+ project_id?: number;
24
+ }
25
+ export interface UserUpdateRequest {
26
+ name?: string;
27
+ avatar?: string;
28
+ phone?: string;
29
+ role?: string;
30
+ project_id?: number;
31
+ }
32
+ export interface LoginResponse {
33
+ access_token: string;
34
+ token_type: string;
35
+ expires_at: string;
36
+ project_id: number;
37
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });