@befly-addon/admin 1.0.54 → 1.0.56

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.
Files changed (82) hide show
  1. package/apis/admin/cacheRefresh.ts +17 -14
  2. package/apis/admin/ins.ts +11 -15
  3. package/apis/admin/upd.ts +1 -13
  4. package/apis/api/all.ts +1 -1
  5. package/apis/api/list.ts +30 -0
  6. package/apis/auth/login.ts +51 -7
  7. package/apis/dashboard/serviceStatus.ts +2 -2
  8. package/apis/dashboard/systemResources.ts +1 -1
  9. package/apis/dict/all.ts +1 -1
  10. package/apis/dict/del.ts +1 -1
  11. package/apis/dict/detail.ts +2 -2
  12. package/apis/dict/ins.ts +1 -1
  13. package/apis/dict/upd.ts +1 -1
  14. package/apis/email/config.ts +16 -0
  15. package/apis/email/logList.ts +13 -0
  16. package/apis/email/send.ts +42 -0
  17. package/apis/email/verify.ts +12 -0
  18. package/apis/loginLog/list.ts +13 -0
  19. package/apis/menu/all.ts +2 -2
  20. package/apis/menu/list.ts +1 -1
  21. package/apis/operateLog/list.ts +13 -0
  22. package/apis/role/del.ts +2 -2
  23. package/apis/role/save.ts +2 -2
  24. package/apis/sysConfig/all.ts +12 -0
  25. package/apis/sysConfig/del.ts +30 -0
  26. package/apis/sysConfig/get.ts +31 -0
  27. package/apis/sysConfig/ins.ts +38 -0
  28. package/apis/sysConfig/list.ts +14 -0
  29. package/apis/sysConfig/upd.ts +50 -0
  30. package/package.json +14 -3
  31. package/plugins/email.ts +206 -0
  32. package/styles/variables.scss +121 -60
  33. package/tables/admin.json +0 -15
  34. package/tables/emailLog.json +69 -0
  35. package/tables/loginLog.json +96 -0
  36. package/tables/operateLog.json +82 -0
  37. package/tables/role.json +1 -1
  38. package/tables/sysConfig.json +53 -0
  39. package/views/403_1/meta.json +4 -0
  40. package/views/{dict → config/dict}/components/edit.vue +7 -5
  41. package/views/config/dict/index.vue +205 -0
  42. package/views/config/dict/meta.json +4 -0
  43. package/views/config/meta.json +4 -0
  44. package/views/config/system/components/edit.vue +179 -0
  45. package/views/config/system/index.vue +256 -0
  46. package/views/config/system/meta.json +4 -0
  47. package/views/index/index.vue +46 -9
  48. package/views/index/meta.json +4 -0
  49. package/views/log/email/index.vue +285 -0
  50. package/views/log/email/meta.json +4 -0
  51. package/views/log/login/index.vue +180 -0
  52. package/views/log/login/meta.json +4 -0
  53. package/views/log/meta.json +4 -0
  54. package/views/log/operate/index.vue +242 -0
  55. package/views/log/operate/meta.json +4 -0
  56. package/views/login_1/meta.json +4 -0
  57. package/views/{admin → people/admin}/components/edit.vue +23 -35
  58. package/views/{admin → people/admin}/index.vue +37 -96
  59. package/views/people/admin/meta.json +4 -0
  60. package/views/people/meta.json +4 -0
  61. package/views/permission/api/index.vue +143 -0
  62. package/views/permission/api/meta.json +4 -0
  63. package/views/permission/menu/index.vue +146 -0
  64. package/views/permission/menu/meta.json +4 -0
  65. package/views/permission/meta.json +4 -0
  66. package/views/{role → permission/role}/components/api.vue +22 -51
  67. package/views/{role → permission/role}/components/edit.vue +14 -15
  68. package/views/{role → permission/role}/components/menu.vue +11 -38
  69. package/views/permission/role/index.vue +227 -0
  70. package/views/permission/role/meta.json +4 -0
  71. package/apis/menu/del.ts +0 -31
  72. package/apis/menu/ins.ts +0 -19
  73. package/apis/menu/upd.ts +0 -27
  74. package/views/dict/index.vue +0 -162
  75. package/views/menu/components/edit.vue +0 -145
  76. package/views/menu/index.vue +0 -173
  77. package/views/role/index.vue +0 -184
  78. /package/views/{403 → 403_1}/index.vue +0 -0
  79. /package/views/{login → login_1}/components/emailLoginForm.vue +0 -0
  80. /package/views/{login → login_1}/components/registerForm.vue +0 -0
  81. /package/views/{login → login_1}/components/welcomePanel.vue +0 -0
  82. /package/views/{login/index_1.vue → login_1/index.vue} +0 -0
@@ -0,0 +1,14 @@
1
+ export default {
2
+ name: '获取系统配置列表',
3
+ handler: async (befly, ctx) => {
4
+ const result = await befly.db.getList({
5
+ table: 'addon_admin_sys_config',
6
+ fields: ['id', 'name', 'code', 'value', 'valueType', 'group', 'sort', 'isSystem', 'description', 'state', 'createdAt', 'updatedAt'],
7
+ page: ctx.body.page,
8
+ limit: ctx.body.limit,
9
+ orderBy: ['group#ASC', 'sort#ASC', 'id#ASC']
10
+ });
11
+
12
+ return befly.tool.Yes('操作成功', result);
13
+ }
14
+ };
@@ -0,0 +1,50 @@
1
+ import sysConfigTable from '../../tables/sysConfig.json';
2
+
3
+ export default {
4
+ name: '更新系统配置',
5
+ fields: sysConfigTable,
6
+ handler: async (befly, ctx) => {
7
+ try {
8
+ // 检查是否为系统配置
9
+ const config = await befly.db.getDetail({
10
+ table: 'addon_admin_sys_config',
11
+ where: { id: ctx.body.id }
12
+ });
13
+
14
+ if (!config) {
15
+ return befly.tool.No('配置不存在');
16
+ }
17
+
18
+ // 系统配置只能修改 value
19
+ if (config.isSystem === 1) {
20
+ await befly.db.updData({
21
+ table: 'addon_admin_sys_config',
22
+ data: {
23
+ value: ctx.body.value
24
+ },
25
+ where: { id: ctx.body.id }
26
+ });
27
+ } else {
28
+ await befly.db.updData({
29
+ table: 'addon_admin_sys_config',
30
+ data: {
31
+ name: ctx.body.name,
32
+ code: ctx.body.code,
33
+ value: ctx.body.value,
34
+ valueType: ctx.body.valueType,
35
+ group: ctx.body.group,
36
+ sort: ctx.body.sort,
37
+ description: ctx.body.description,
38
+ state: ctx.body.state
39
+ },
40
+ where: { id: ctx.body.id }
41
+ });
42
+ }
43
+
44
+ return befly.tool.Yes('操作成功');
45
+ } catch (error) {
46
+ befly.logger.error({ err: error }, '更新系统配置失败');
47
+ return befly.tool.No('操作失败');
48
+ }
49
+ }
50
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@befly-addon/admin",
3
- "version": "1.0.54",
3
+ "version": "1.0.56",
4
4
  "title": "管理后台",
5
5
  "description": "Befly - 管理后台功能组件",
6
6
  "type": "module",
@@ -10,6 +10,10 @@
10
10
  "registry": "https://registry.npmjs.org"
11
11
  },
12
12
  "main": "package.json",
13
+ "exports": {
14
+ ".": "./package.json",
15
+ "./styles/*": "./styles/*"
16
+ },
13
17
  "scripts": {
14
18
  "dev": "vite",
15
19
  "build": "vite build",
@@ -17,6 +21,7 @@
17
21
  },
18
22
  "files": [
19
23
  "apis",
24
+ "plugins",
20
25
  "styles",
21
26
  "tables",
22
27
  "views",
@@ -38,8 +43,14 @@
38
43
  "url": "https://github.com/chenbimo/befly.git",
39
44
  "directory": "packages/addon-admin"
40
45
  },
41
- "gitHead": "1f3cacbe4134ee60654b75338bcaeda535898a84",
46
+ "gitHead": "d9a4c57539f6eb692d7db6c7fd800e021891a07c",
42
47
  "dependencies": {
43
- "befly-util": "^1.0.7"
48
+ "befly-shared": "^1.1.2",
49
+ "nodemailer": "^7.0.11",
50
+ "ua-parser-js": "^2.0.6"
51
+ },
52
+ "devDependencies": {
53
+ "@types/nodemailer": "^7.0.4",
54
+ "@types/ua-parser-js": "^0.7.39"
44
55
  }
45
56
  }
@@ -0,0 +1,206 @@
1
+ /**
2
+ * 邮件插件
3
+ * 提供邮件发送功能,支持 SMTP 配置
4
+ */
5
+
6
+ import nodemailer from 'nodemailer';
7
+
8
+ import type { Transporter } from 'nodemailer';
9
+ import type { Plugin } from 'befly-core/types/plugin.js';
10
+ import type { BeflyContext } from 'befly-core/types/befly.js';
11
+
12
+ /** 邮件配置 */
13
+ export interface EmailConfig {
14
+ /** SMTP 服务器地址 */
15
+ host: string;
16
+ /** SMTP 端口 */
17
+ port: number;
18
+ /** 是否使用 SSL */
19
+ secure: boolean;
20
+ /** 发件人邮箱 */
21
+ user: string;
22
+ /** 邮箱密码或授权码 */
23
+ pass: string;
24
+ /** 发件人名称 */
25
+ fromName?: string;
26
+ }
27
+
28
+ /** 发送邮件参数 */
29
+ export interface SendEmailOptions {
30
+ /** 收件人邮箱 */
31
+ to: string;
32
+ /** 邮件主题 */
33
+ subject: string;
34
+ /** 纯文本内容 */
35
+ text?: string;
36
+ /** HTML 内容 */
37
+ html?: string;
38
+ /** 抄送 */
39
+ cc?: string;
40
+ /** 密送 */
41
+ bcc?: string;
42
+ /** 发送人ID */
43
+ adminId?: number;
44
+ /** 发送人账号 */
45
+ username?: string;
46
+ /** 发送人昵称 */
47
+ nickname?: string;
48
+ }
49
+
50
+ /** 发送结果 */
51
+ export interface SendEmailResult {
52
+ success: boolean;
53
+ messageId?: string;
54
+ error?: string;
55
+ }
56
+
57
+ /** 默认配置 */
58
+ const defaultConfig: EmailConfig = {
59
+ host: 'smtp.qq.com',
60
+ port: 465,
61
+ secure: true,
62
+ user: '',
63
+ pass: '',
64
+ fromName: 'Befly System'
65
+ };
66
+
67
+ /**
68
+ * 邮件助手类
69
+ */
70
+ class EmailHelper {
71
+ private config: EmailConfig;
72
+ private transporter: Transporter | null = null;
73
+ private befly: BeflyContext;
74
+
75
+ constructor(befly: BeflyContext, config: EmailConfig) {
76
+ this.befly = befly;
77
+ this.config = config;
78
+
79
+ // 如果配置了邮箱,则创建 transporter
80
+ if (this.config.user && this.config.pass) {
81
+ this.transporter = nodemailer.createTransport({
82
+ host: this.config.host,
83
+ port: this.config.port,
84
+ secure: this.config.secure,
85
+ auth: {
86
+ user: this.config.user,
87
+ pass: this.config.pass
88
+ }
89
+ });
90
+ }
91
+ }
92
+
93
+ /**
94
+ * 发送邮件
95
+ */
96
+ async send(options: SendEmailOptions): Promise<SendEmailResult> {
97
+ if (!this.transporter) {
98
+ return {
99
+ success: false,
100
+ error: '邮件服务未配置,请检查 SMTP 配置'
101
+ };
102
+ }
103
+
104
+ const fromAddress = this.config.fromName ? `"${this.config.fromName}" <${this.config.user}>` : this.config.user;
105
+
106
+ try {
107
+ const info = await this.transporter.sendMail({
108
+ from: fromAddress,
109
+ to: options.to,
110
+ subject: options.subject,
111
+ text: options.text,
112
+ html: options.html,
113
+ cc: options.cc,
114
+ bcc: options.bcc
115
+ });
116
+
117
+ return {
118
+ success: true,
119
+ messageId: info.messageId
120
+ };
121
+ } catch (error: any) {
122
+ return {
123
+ success: false,
124
+ error: error.message || '发送失败'
125
+ };
126
+ }
127
+ }
128
+
129
+ /**
130
+ * 发送邮件并记录日志
131
+ */
132
+ async sendAndLog(options: SendEmailOptions): Promise<SendEmailResult> {
133
+ const startTime = Date.now();
134
+ const result = await this.send(options);
135
+
136
+ // 记录邮件发送日志
137
+ try {
138
+ await this.befly.db.insData({
139
+ table: 'addon_admin_email_log',
140
+ data: {
141
+ adminId: options.adminId || 0,
142
+ username: options.username || '',
143
+ nickname: options.nickname || '',
144
+ toEmail: options.to,
145
+ subject: options.subject,
146
+ content: options.html || options.text || '',
147
+ ccEmail: options.cc || '',
148
+ bccEmail: options.bcc || '',
149
+ sendTime: startTime,
150
+ sendResult: result.success ? 1 : 0,
151
+ messageId: result.messageId || '',
152
+ failReason: result.error || ''
153
+ }
154
+ });
155
+ } catch (logError: any) {
156
+ this.befly.logger.error({ err: logError }, '记录邮件日志失败');
157
+ }
158
+
159
+ return result;
160
+ }
161
+
162
+ /**
163
+ * 验证 SMTP 连接
164
+ */
165
+ async verify(): Promise<boolean> {
166
+ if (!this.transporter) {
167
+ return false;
168
+ }
169
+
170
+ try {
171
+ await this.transporter.verify();
172
+ return true;
173
+ } catch {
174
+ return false;
175
+ }
176
+ }
177
+
178
+ /**
179
+ * 获取当前配置(隐藏密码)
180
+ */
181
+ getConfig(): Omit<EmailConfig, 'pass'> & { pass: string } {
182
+ return {
183
+ ...this.config,
184
+ pass: this.config.pass ? '******' : ''
185
+ };
186
+ }
187
+ }
188
+
189
+ /**
190
+ * 邮件插件
191
+ */
192
+ const emailPlugin: Plugin = {
193
+ after: ['db', 'logger', 'config'],
194
+ async handler(befly: BeflyContext): Promise<EmailHelper> {
195
+ // 从 befly.config.addons.admin.email 获取配置
196
+ const addonEmailConfig = befly.config?.addons?.admin?.email || {};
197
+ const emailConfig: EmailConfig = {
198
+ ...defaultConfig,
199
+ ...addonEmailConfig
200
+ };
201
+
202
+ return new EmailHelper(befly, emailConfig);
203
+ }
204
+ };
205
+
206
+ export default emailPlugin;
@@ -1,87 +1,148 @@
1
+ // ============================================
1
2
  // CSS 原生变量(支持运行时动态修改)
3
+ // 基于 TDesign 设计规范优化
4
+ // ============================================
5
+
2
6
  :root {
3
- // 主题色
7
+ // ============================================
8
+ // 品牌色 - 基于 TDesign 官方色板优化
9
+ // ============================================
4
10
  --primary-color: #0052d9;
5
- --success-color: #00a870;
6
- --warning-color: #ed7b2f;
7
- --error-color: #e34d59;
8
- --info-color: #0052d9;
11
+ --primary-color-hover: #366ef4;
12
+ --primary-color-active: #0034b5;
13
+ --primary-color-light: #ecf2fe;
14
+ --primary-color-focus: #ccdcf9;
9
15
 
10
- // 主题色 RGB 格式(用于 rgba)
11
- --primary-color-rgb: 0, 82, 217;
12
- --success-color-rgb: 0, 168, 112;
13
- --warning-color-rgb: 237, 123, 47;
14
- --error-color-rgb: 227, 77, 89;
15
- --info-color-rgb: 0, 82, 217;
16
+ // 功能色
17
+ --success-color: #2ba471;
18
+ --success-color-hover: #56c08d;
19
+ --success-color-light: #e8f8f2;
20
+ --warning-color: #e37318;
21
+ --warning-color-hover: #fa9550;
22
+ --warning-color-light: #fef3e6;
23
+ --error-color: #d54941;
24
+ --error-color-hover: #e6635a;
25
+ --error-color-light: #fdecee;
26
+ --info-color: #0052d9;
16
27
 
17
- // 文本颜色
18
- --text-primary: #1f2329;
19
- --text-secondary: #646a73;
20
- --text-placeholder: #8f959e;
28
+ // ============================================
29
+ // 文本颜色 - 增强层次对比
30
+ // ============================================
31
+ --text-primary: #1d2129;
32
+ --text-secondary: #4e5969;
33
+ --text-placeholder: #86909c;
21
34
  --text-disabled: #c9cdd4;
35
+ --text-anti: #ffffff;
22
36
 
23
- // 背景色
24
- --bg-color-page: #f5f7fa;
37
+ // ============================================
38
+ // 背景色 - 增强层次区分
39
+ // ============================================
40
+ --bg-color-page: #f8f8f8;
25
41
  --bg-color-container: #ffffff;
26
- --bg-color-overlay: rgba(0, 0, 0, 0.6);
27
- --bg-color-hover: #f5f7fa;
42
+ --bg-color-container-hover: #f7f8fa;
43
+ --bg-color-secondarycontainer: #f7f8fa;
44
+ --bg-color-overlay: #8a8a8a;
45
+ --bg-color-hover: #f5f5f5;
46
+ --bg-color-active: #e6effc;
47
+
48
+ // 表格专用背景色 - 增强对比
49
+ --table-header-bg: #e3e3e3;
50
+ --table-header-text: #1d2129;
51
+ --table-row-stripe: #fafbfc;
52
+ --table-row-hover: #f0f5ff;
53
+ --table-row-selected: #e6effc;
54
+ --table-row-active: #dce8fa;
28
55
 
29
- // 边框
30
- --border-color: #e8eaed;
31
- --border-color-light: #f0f1f3;
32
- --border-radius: 8px;
33
- --border-radius-small: 4px;
34
- --border-radius-large: 12px;
56
+ // ============================================
57
+ // 边框色 - 更柔和的分隔线
58
+ // ============================================
59
+ --border-color: #e5e6eb;
60
+ --border-color-light: #f2f3f5;
61
+ --border-color-dark: #c9cdd4;
62
+ --border-radius: 6px;
63
+ --border-radius-small: 3px;
64
+ --border-radius-large: 10px;
35
65
 
66
+ // ============================================
67
+ // 阴影 - 更精致的层次感
68
+ // ============================================
69
+ --shadow-1: 0 1px 2px #f0f0f0, 0 1px 2px #ebebeb;
70
+ --shadow-2: 0 2px 4px #f0f0f0, 0 4px 8px #ebebeb;
71
+ --shadow-3: 0 4px 8px #e8e8e8, 0 8px 16px #e0e0e0;
72
+ --shadow-inset: inset 0 1px 2px #f2f2f2;
73
+
74
+ // 兼容旧变量
75
+ --shadow-small: var(--shadow-1);
76
+ --shadow-medium: var(--shadow-2);
77
+ --shadow-large: var(--shadow-3);
78
+ --shadow-card: var(--shadow-1);
79
+
80
+ // ============================================
36
81
  // 间距
82
+ // ============================================
37
83
  --spacing-xs: 4px;
38
84
  --spacing-sm: 8px;
39
85
  --spacing-md: 16px;
40
86
  --spacing-lg: 24px;
41
87
  --spacing-xl: 32px;
42
88
 
43
- // 阴影
44
- --shadow-small: 0 2px 8px rgba(0, 0, 0, 0.04);
45
- --shadow-medium: 0 4px 12px rgba(0, 0, 0, 0.08);
46
- --shadow-large: 0 8px 24px rgba(0, 0, 0, 0.12);
47
- --shadow-card: 0 2px 8px rgba(0, 0, 0, 0.04);
89
+ // ============================================
90
+ // 动画
91
+ // ============================================
92
+ --transition-fast: 0.15s ease;
93
+ --transition-normal: 0.25s ease;
94
+ --transition-slow: 0.35s ease;
95
+ --transition-duration: 0.25s;
48
96
 
49
- // 动画时间
50
- --transition-fast: 0.15s;
51
- --transition-normal: 0.3s;
52
- --transition-slow: 0.5s;
53
-
54
- // 字体大小
97
+ // ============================================
98
+ // 字体
99
+ // ============================================
55
100
  --font-size-xs: 12px;
56
- --font-size-sm: 14px;
57
- --font-size-md: 16px;
58
- --font-size-lg: 18px;
59
- --font-size-xl: 20px;
101
+ --font-size-sm: 13px;
102
+ --font-size-md: 14px;
103
+ --font-size-lg: 16px;
104
+ --font-size-xl: 18px;
105
+ --font-weight-regular: 400;
106
+ --font-weight-medium: 500;
107
+ --font-weight-semibold: 600;
60
108
 
109
+ // ============================================
61
110
  // 布局尺寸
62
- --header-height: 64px;
63
- --sidebar-width: 240px;
64
- --footer-height: 48px;
65
- --search-height: 56px;
66
- --pagination-height: 56px;
67
- --detail-width: 320px;
68
- --transition-duration: 0.3s;
111
+ // ============================================
112
+ --header-height: 56px;
113
+ --sidebar-width: 220px;
114
+ --footer-height: 40px;
115
+ --search-height: 52px;
116
+ --pagination-height: 52px;
117
+ --detail-width: 260px;
118
+ --detail-bg: #fafbfc;
119
+ --layout-gap: 12px;
120
+ --card-radius: 10px;
121
+ --t-dialog--default: 16px;
122
+
123
+ // ============================================
124
+ // 菜单样式
125
+ // ============================================
126
+ --menu-item-height: 40px;
127
+ --menu-active-indicator: 3px;
69
128
 
129
+ // ============================================
70
130
  // 登录页配色
71
- --login-bg: #f5f7fa;
131
+ // ============================================
132
+ --login-bg: var(--bg-color-page);
72
133
  --login-left-gradient-start: #f8f9fa;
73
134
  --login-left-gradient-end: #e9ecef;
74
- --login-circle-bg: rgba(0, 0, 0, 0.03);
75
- --login-brand-title: #2c3e50;
76
- --login-brand-subtitle: #6c757d;
135
+ --login-circle-bg: #f5f5f5;
136
+ --login-brand-title: #1f2329;
137
+ --login-brand-subtitle: #5c6066;
77
138
  --login-card-bg: #ffffff;
78
- --login-card-border: #e9ecef;
79
- --login-card-shadow: rgba(0, 0, 0, 0.08);
80
- --login-title: #2c3e50;
81
- --login-subtitle: #6c757d;
82
- --login-link: #495057;
83
- --login-link-hover: #2c3e50;
84
- --login-btn-gradient-start: #495057;
85
- --login-btn-gradient-end: #343a40;
86
- --login-btn-shadow: rgba(52, 58, 64, 0.3);
139
+ --login-card-border: var(--border-color-light);
140
+ --login-card-shadow: var(--shadow-2);
141
+ --login-title: #1f2329;
142
+ --login-subtitle: #5c6066;
143
+ --login-link: #5c6066;
144
+ --login-link-hover: var(--primary-color);
145
+ --login-btn-gradient-start: var(--primary-color);
146
+ --login-btn-gradient-end: var(--primary-color-active);
147
+ --login-btn-shadow: #b3c9ed;
87
148
  }
package/tables/admin.json CHANGED
@@ -5,21 +5,6 @@
5
5
  "min": 1,
6
6
  "max": 50
7
7
  },
8
- "email": {
9
- "name": "邮箱",
10
- "type": "string",
11
- "min": 5,
12
- "max": 100,
13
- "index": true,
14
- "regexp": "@email"
15
- },
16
- "phone": {
17
- "name": "手机号",
18
- "type": "string",
19
- "min": 11,
20
- "max": 11,
21
- "regexp": "@phone"
22
- },
23
8
  "username": {
24
9
  "name": "用户名",
25
10
  "type": "string",
@@ -0,0 +1,69 @@
1
+ {
2
+ "adminId": {
3
+ "name": "发送人ID",
4
+ "type": "number",
5
+ "min": 0,
6
+ "max": 999999999999999,
7
+ "index": true
8
+ },
9
+ "username": {
10
+ "name": "发送人账号",
11
+ "type": "string",
12
+ "max": 100
13
+ },
14
+ "nickname": {
15
+ "name": "发送人昵称",
16
+ "type": "string",
17
+ "max": 100
18
+ },
19
+ "toEmail": {
20
+ "name": "收件人邮箱",
21
+ "type": "string",
22
+ "min": 5,
23
+ "max": 200,
24
+ "required": true,
25
+ "regex": "email"
26
+ },
27
+ "subject": {
28
+ "name": "邮件主题",
29
+ "type": "string",
30
+ "min": 1,
31
+ "max": 200,
32
+ "required": true
33
+ },
34
+ "content": {
35
+ "name": "邮件内容",
36
+ "type": "text"
37
+ },
38
+ "ccEmail": {
39
+ "name": "抄送邮箱",
40
+ "type": "string",
41
+ "max": 500
42
+ },
43
+ "bccEmail": {
44
+ "name": "密送邮箱",
45
+ "type": "string",
46
+ "max": 500
47
+ },
48
+ "sendTime": {
49
+ "name": "发送时间",
50
+ "type": "number"
51
+ },
52
+ "sendResult": {
53
+ "name": "发送结果",
54
+ "type": "number",
55
+ "min": 0,
56
+ "max": 1,
57
+ "default": 0
58
+ },
59
+ "messageId": {
60
+ "name": "消息ID",
61
+ "type": "string",
62
+ "max": 200
63
+ },
64
+ "failReason": {
65
+ "name": "失败原因",
66
+ "type": "string",
67
+ "max": 500
68
+ }
69
+ }