\345\271\263\345\217\260\345\220\210app\346\216\210\346\235\203/\345\237\272\344\272\216gw\347\232\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260.md
... ...
@@ -0,0 +1,397 @@
1
+我来详细分析这个授权过期提醒策略需求,并提供完整的Go语言实现方案。
2
+
3
+## 需求分析
4
+
5
+### 核心目标
6
+1. **完善授权到期前后的提醒机制**
7
+2. **分阶段提醒**:到期前60天、30天、15天、到期后、超期7天
8
+3. **差异化提醒对象**:平台管理员/租户管理员 vs 所有用户
9
+4. **不同触发频率**:每月、每天、每次登录、每个请求
10
+5. **提醒不阻塞业务**(除超期后的概率异常)
11
+
12
+### 策略阶段分析
13
+| 阶段 | 时间区间 | 提醒对象 | 触发条件 | 业务影响 |
14
+|------|----------|----------|----------|----------|
15
+| 阶段1 | 到期前60天开始 | 平台/租户管理员 | 每月一次,登录时 | 不阻塞 |
16
+| 阶段2 | 到期前30天开始 | 平台/租户管理员 | 每天一次,登录时 | 不阻塞 |
17
+| 阶段3 | 到期前15天开始 | 平台/租户管理员 | 每次登录时 | 不阻塞 |
18
+| 阶段4 | 到期后0天开始 | 所有用户 + 平台/租户管理员 | 所有请求 + 登录时 | 概率阻塞 |
19
+| 阶段5 | 超期7天开始 | 所有用户 + 平台/租户管理员 | 所有请求 + 登录时 | 概率阻塞 |
20
+
21
+## Go语言实现方案
22
+
23
+### 1. 数据结构定义
24
+
25
+```go
26
+package main
27
+
28
+import (
29
+ "fmt"
30
+ "time"
31
+ "math/rand"
32
+)
33
+
34
+// 许可证信息
35
+type License struct {
36
+ ExpireTime time.Time
37
+ IsValid bool
38
+ LicenseType string
39
+}
40
+
41
+// 用户信息
42
+type User struct {
43
+ ID string
44
+ Username string
45
+ Role UserRole
46
+ LastRemind map[RemindStage]time.Time
47
+}
48
+
49
+// 用户角色
50
+type UserRole int
51
+
52
+const (
53
+ RoleNormalUser UserRole = iota
54
+ RoleTenantAdmin
55
+ RolePlatformAdmin
56
+)
57
+
58
+// 提醒阶段
59
+type RemindStage int
60
+
61
+const (
62
+ Stage60DaysBefore RemindStage = iota
63
+ Stage30DaysBefore
64
+ Stage15DaysBefore
65
+ StageAfterExpire
66
+ Stage7DaysAfterExpire
67
+)
68
+
69
+// 提醒策略配置
70
+type RemindStrategy struct {
71
+ Stage RemindStage
72
+ DaysFromExpire int // 正数表示到期前,负数表示到期后
73
+ TargetUsers []UserRole
74
+ TriggerCondition string
75
+ Frequency time.Duration
76
+ MessageTemplate string
77
+ BlockBusiness bool
78
+ ExceptionRate float64 // 异常抛出概率(0-1)
79
+}
80
+
81
+// 提醒记录
82
+type RemindRecord struct {
83
+ UserID string
84
+ Stage RemindStage
85
+ RemindTime time.Time
86
+ Message string
87
+ IsShown bool
88
+}
89
+```
90
+
91
+### 2. 策略配置管理
92
+
93
+```go
94
+// 策略管理器
95
+type RemindStrategyManager struct {
96
+ strategies map[RemindStage]*RemindStrategy
97
+ license *License
98
+ remindHistory map[string][]*RemindRecord // userID -> records
99
+}
100
+
101
+func NewRemindStrategyManager(license *License) *RemindStrategyManager {
102
+ manager := &RemindStrategyManager{
103
+ license: license,
104
+ strategies: make(map[RemindStage]*RemindStrategy),
105
+ remindHistory: make(map[string][]*RemindRecord),
106
+ }
107
+ manager.initStrategies()
108
+ return manager
109
+}
110
+
111
+func (m *RemindStrategyManager) initStrategies() {
112
+ // 阶段1: 到期前60天开始
113
+ m.strategies[Stage60DaysBefore] = &RemindStrategy{
114
+ Stage: Stage60DaysBefore,
115
+ DaysFromExpire: 60,
116
+ TargetUsers: []UserRole{RolePlatformAdmin, RoleTenantAdmin},
117
+ TriggerCondition: "登录时",
118
+ Frequency: time.Hour * 24 * 30, // 每月一次
119
+ MessageTemplate: "平台许可证将在%d天后,%s到期,为避免到期后系统不能正常使用而影响业务,请在到期前及时进行许可证续期。",
120
+ BlockBusiness: false,
121
+ ExceptionRate: 0,
122
+ }
123
+
124
+ // 阶段2: 到期前30天开始
125
+ m.strategies[Stage30DaysBefore] = &RemindStrategy{
126
+ Stage: Stage30DaysBefore,
127
+ DaysFromExpire: 30,
128
+ TargetUsers: []UserRole{RolePlatformAdmin, RoleTenantAdmin},
129
+ TriggerCondition: "登录时",
130
+ Frequency: time.Hour * 24, // 每天一次
131
+ MessageTemplate: "平台许可证将在%d天后,%s到期,为避免到期后系统不能正常使用而影响业务,请在到期前及时进行许可证续期。",
132
+ BlockBusiness: false,
133
+ ExceptionRate: 0,
134
+ }
135
+
136
+ // 阶段3: 到期前15天开始
137
+ m.strategies[Stage15DaysBefore] = &RemindStrategy{
138
+ Stage: Stage15DaysBefore,
139
+ DaysFromExpire: 15,
140
+ TargetUsers: []UserRole{RolePlatformAdmin, RoleTenantAdmin},
141
+ TriggerCondition: "登录时",
142
+ Frequency: time.Hour * 1, // 每次登录(按小时频率)
143
+ MessageTemplate: "平台许可证将在%d天后,%s到期,为避免到期后系统不能正常使用而影响业务,请在到期前及时进行许可证续期。",
144
+ BlockBusiness: false,
145
+ ExceptionRate: 0,
146
+ }
147
+
148
+ // 阶段4: 到期后
149
+ m.strategies[StageAfterExpire] = &RemindStrategy{
150
+ Stage: StageAfterExpire,
151
+ DaysFromExpire: 0,
152
+ TargetUsers: []UserRole{RolePlatformAdmin, RoleTenantAdmin, RoleNormalUser},
153
+ TriggerCondition: "所有请求",
154
+ Frequency: time.Hour * 1,
155
+ MessageTemplate: "平台许可证已于%s到期,请在7天内完成许可证续期,否则系统将在%s后不能正常使用!",
156
+ BlockBusiness: true,
157
+ ExceptionRate: 0.3, // 30%概率抛异常
158
+ }
159
+
160
+ // 阶段5: 超期7天开始
161
+ m.strategies[Stage7DaysAfterExpire] = &RemindStrategy{
162
+ Stage: Stage7DaysAfterExpire,
163
+ DaysFromExpire: -7,
164
+ TargetUsers: []UserRole{RolePlatformAdmin, RoleTenantAdmin, RoleNormalUser},
165
+ TriggerCondition: "所有请求",
166
+ Frequency: time.Hour * 1,
167
+ MessageTemplate: "平台许可证已过期,系统不能正常使用,请联系您的系统管理员进行处理!",
168
+ BlockBusiness: true,
169
+ ExceptionRate: 0.5, // 50%概率抛异常
170
+ }
171
+}
172
+```
173
+
174
+### 3. 核心业务逻辑
175
+
176
+```go
177
+// 获取当前提醒阶段
178
+func (m *RemindStrategyManager) getCurrentStage() RemindStage {
179
+ now := time.Now()
180
+ daysUntilExpire := int(m.license.ExpireTime.Sub(now).Hours() / 24)
181
+
182
+ switch {
183
+ case daysUntilExpire >= 60:
184
+ return Stage60DaysBefore
185
+ case daysUntilExpire >= 30:
186
+ return Stage30DaysBefore
187
+ case daysUntilExpire >= 15:
188
+ return Stage15DaysBefore
189
+ case daysUntilExpire >= 0:
190
+ return StageAfterExpire
191
+ default:
192
+ if daysUntilExpire <= -7 {
193
+ return Stage7DaysAfterExpire
194
+ }
195
+ return StageAfterExpire
196
+ }
197
+}
198
+
199
+// 检查用户是否需要提醒
200
+func (m *RemindStrategyManager) shouldRemindUser(user *User, stage RemindStage, triggerType string) bool {
201
+ strategy, exists := m.strategies[stage]
202
+ if !exists {
203
+ return false
204
+ }
205
+
206
+ // 检查触发条件
207
+ if triggerType != strategy.TriggerCondition && strategy.TriggerCondition != "所有请求" {
208
+ return false
209
+ }
210
+
211
+ // 检查用户角色
212
+ userInTarget := false
213
+ for _, role := range strategy.TargetUsers {
214
+ if user.Role == role {
215
+ userInTarget = true
216
+ break
217
+ }
218
+ }
219
+ if !userInTarget {
220
+ return false
221
+ }
222
+
223
+ // 检查频率限制
224
+ lastRemind, exists := user.LastRemind[stage]
225
+ if exists && time.Since(lastRemind) < strategy.Frequency {
226
+ return false
227
+ }
228
+
229
+ return true
230
+}
231
+
232
+// 生成提醒消息
233
+func (m *RemindStrategyManager) generateMessage(stage RemindStage, user *User) string {
234
+ strategy := m.strategies[stage]
235
+ expireTimeStr := m.license.ExpireTime.Format("2006年01月02日 15:04:05")
236
+ daysUntil := int(m.license.ExpireTime.Sub(time.Now()).Hours() / 24)
237
+
238
+ switch stage {
239
+ case Stage60DaysBefore, Stage30DaysBefore, Stage15DaysBefore:
240
+ return fmt.Sprintf(strategy.MessageTemplate, daysUntil, expireTimeStr)
241
+ case StageAfterExpire:
242
+ deadline := m.license.ExpireTime.AddDate(0, 0, 7)
243
+ return fmt.Sprintf(strategy.MessageTemplate, expireTimeStr, deadline.Format("2006年01月02日 15:04:05"))
244
+ case Stage7DaysAfterExpire:
245
+ if user.Role == RoleNormalUser {
246
+ return "平台许可证已过期,系统不能正常使用,请联系您的系统管理员进行处理!"
247
+ } else {
248
+ return fmt.Sprintf("平台许可证已于%s到期,经多次提醒贵司未能在宽限期内完成许可证续期,系统已不能正常使用!", expireTimeStr)
249
+ }
250
+ default:
251
+ return "许可证状态异常,请联系管理员。"
252
+ }
253
+}
254
+
255
+// 处理业务阻塞逻辑
256
+func (m *RemindStrategyManager) checkBusinessBlock(stage RemindStage) error {
257
+ strategy := m.strategies[stage]
258
+ if strategy.BlockBusiness && rand.Float64() < strategy.ExceptionRate {
259
+ return fmt.Errorf("许可证已过期,系统不能正常使用")
260
+ }
261
+ return nil
262
+}
263
+```
264
+
265
+### 4. API接口实现
266
+
267
+```go
268
+// 登录提醒处理
269
+func (m *RemindStrategyManager) HandleLoginRemind(user *User) (*RemindRecord, error) {
270
+ stage := m.getCurrentStage()
271
+
272
+ if !m.shouldRemindUser(user, stage, "登录时") {
273
+ return nil, nil
274
+ }
275
+
276
+ // 检查业务阻塞
277
+ if err := m.checkBusinessBlock(stage); err != nil {
278
+ return nil, err
279
+ }
280
+
281
+ message := m.generateMessage(stage, user)
282
+ record := &RemindRecord{
283
+ UserID: user.ID,
284
+ Stage: stage,
285
+ RemindTime: time.Now(),
286
+ Message: message,
287
+ IsShown: false,
288
+ }
289
+
290
+ // 保存提醒记录
291
+ m.remindHistory[user.ID] = append(m.remindHistory[user.ID], record)
292
+ user.LastRemind[stage] = time.Now()
293
+
294
+ return record, nil
295
+}
296
+
297
+// 请求提醒处理
298
+func (m *RemindStrategyManager) HandleRequestRemind(user *User) (*RemindRecord, error) {
299
+ stage := m.getCurrentStage()
300
+
301
+ if !m.shouldRemindUser(user, stage, "所有请求") {
302
+ return nil, nil
303
+ }
304
+
305
+ // 检查业务阻塞
306
+ if err := m.checkBusinessBlock(stage); err != nil {
307
+ return nil, err
308
+ }
309
+
310
+ message := m.generateMessage(stage, user)
311
+ record := &RemindRecord{
312
+ UserID: user.ID,
313
+ Stage: stage,
314
+ RemindTime: time.Now(),
315
+ Message: message,
316
+ IsShown: false,
317
+ }
318
+
319
+ return record, nil
320
+}
321
+```
322
+
323
+### 5. 使用示例
324
+
325
+```go
326
+func main() {
327
+ // 初始化许可证信息
328
+ expireTime := time.Now().AddDate(0, 0, 45) // 45天后到期
329
+ license := &License{
330
+ ExpireTime: expireTime,
331
+ IsValid: true,
332
+ LicenseType: "企业版",
333
+ }
334
+
335
+ // 创建策略管理器
336
+ strategyManager := NewRemindStrategyManager(license)
337
+
338
+ // 模拟用户登录
339
+ adminUser := &User{
340
+ ID: "user001",
341
+ Username: "admin",
342
+ Role: RolePlatformAdmin,
343
+ LastRemind: make(map[RemindStage]time.Time),
344
+ }
345
+
346
+ // 处理登录提醒
347
+ record, err := strategyManager.HandleLoginRemind(adminUser)
348
+ if err != nil {
349
+ fmt.Printf("业务阻塞: %v\n", err)
350
+ return
351
+ }
352
+
353
+ if record != nil {
354
+ fmt.Printf("提醒消息: %s\n", record.Message)
355
+ fmt.Printf("提醒阶段: %v\n", record.Stage)
356
+ fmt.Printf("提醒时间: %s\n", record.RemindTime.Format("2006-01-02 15:04:05"))
357
+ }
358
+
359
+ // 模拟普通用户请求
360
+ normalUser := &User{
361
+ ID: "user002",
362
+ Username: "user1",
363
+ Role: RoleNormalUser,
364
+ LastRemind: make(map[RemindStage]time.Time),
365
+ }
366
+
367
+ // 处理请求提醒(在到期后阶段)
368
+ requestRecord, err := strategyManager.HandleRequestRemind(normalUser)
369
+ if err != nil {
370
+ fmt.Printf("请求被阻塞: %v\n", err)
371
+ return
372
+ }
373
+
374
+ if requestRecord != nil {
375
+ fmt.Printf("请求提醒: %s\n", requestRecord.Message)
376
+ }
377
+}
378
+```
379
+
380
+## 系统架构建议
381
+
382
+### 1. 存储设计
383
+- 使用Redis缓存用户最近提醒记录
384
+- 使用MySQL持久化提醒历史
385
+- 许可证信息配置在配置中心
386
+
387
+### 2. 性能优化
388
+- 使用本地缓存减少数据库查询
389
+- 异步记录提醒日志
390
+- 批量处理用户提醒
391
+
392
+### 3. 扩展性考虑
393
+- 支持动态策略配置
394
+- 可插拔的提醒渠道(邮件、短信、站内信)
395
+- 多租户隔离支持
396
+
397
+这个实现方案完整覆盖了需求中的所有策略阶段,提供了灵活的配置方式和良好的扩展性,可以直接集成到现有的微服务架构中。
... ...
\ No newline at end of file