Skip to content

Commit ce9a07f

Browse files
authored
Merge pull request #408 from lazzyfu/dev
Dev
2 parents 152c777 + e18b9fb commit ce9a07f

86 files changed

Lines changed: 5466 additions & 942 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
---
2+
name: ant-design-vue
3+
description: Use when building, refactoring, or reviewing Vue 3 interfaces with Ant Design Vue 4.x in this repository, especially for layout, spacing, radius, button consistency, forms, tables, navigation, feedback, and enterprise admin page styling decisions.
4+
---
5+
6+
# Ant Design Vue(GoInsight 统一版)
7+
8+
用于当前仓库的前端 UI 规范技能。目标是输出可维护、可复用、视觉一致的企业后台界面方案,并减少一次性样式和组件漂移。
9+
10+
## 适用范围
11+
12+
- 技术栈:Vue 3 + Ant Design Vue 4.x(当前项目使用 4.2.6)。
13+
- 语法约束:使用 `script setup`,不使用 `lang="ts"`
14+
- 页面范围:登录、列表、详情、编辑、仪表盘、设置等全前端页面。
15+
- 任务类型:新页面设计、旧页面重构、组件替换、样式统一、代码评审建议。
16+
17+
## 触发信号(命中任一即使用本技能)
18+
19+
- 用户提到:`Ant Design Vue``AntDV``ant-design-vue`
20+
- 用户要求:按钮/表单/表格/弹窗/菜单/分页等组件实现或改造。
21+
- 用户提到:布局、间距、圆角、主题、视觉统一、组件规范。
22+
23+
## 输出方式(无强制门禁)
24+
25+
默认先给“规范化 UI 方案”,再给实现建议。
26+
方案中至少包含:
27+
28+
1. 页面结构与布局建议
29+
2. 组件映射建议
30+
3. 与全局规范一致性的检查点
31+
32+
## 全局强制规范
33+
34+
以以下文件作为唯一真源:
35+
36+
- `/Users/zongfei.fu/Downloads/CodeX/goInsight/www/src/design/tokens.js`
37+
- `/Users/zongfei.fu/Downloads/CodeX/goInsight/www/src/design/antdTheme.js`
38+
39+
### 1) 间距规范(强制)
40+
41+
- 仅使用:`4 / 8 / 12 / 16 / 24 / 32`
42+
- 禁止散点间距(如 10、14、18、22 等无来源值)
43+
44+
### 2) 圆角规范(强制)
45+
46+
- 仅使用:`6 / 8 / 10 / 12`
47+
- 禁止组件内手写临时圆角值
48+
49+
### 3) 按钮规范(强制)
50+
51+
- 默认统一:`size="middle"`
52+
- 禁止手动设置按钮颜色、圆角、高度(包含 inline style)
53+
- 仅允许使用 AntDV 语义属性控制按钮表现:`type``danger``ghost``block``size`
54+
- 登录页按钮也遵守统一 `middle`
55+
56+
## 布局规范
57+
58+
推荐后台壳层结构:
59+
60+
```
61+
Layout
62+
|- Sider (Menu)
63+
|- Header
64+
`- Content
65+
```
66+
67+
- 使用 `Layout` / `Layout.Sider` / `Layout.Header` / `Layout.Content`
68+
- 侧边栏宽度建议 `200px ~ 240px`
69+
- 主内容区优先用 `a-card` 承载
70+
- 页面内边距建议 `16px ~ 24px`
71+
- 使用 24 栅格:`a-row` + `a-col`
72+
- 栅格 `gutter` 优先 `16``24`
73+
74+
## 语义颜色规范
75+
76+
优先使用 Ant Design 语义色,不随意造色。基础语义:
77+
78+
- Primary / Info:`#1677ff`
79+
- Success:`#52c41a`
80+
- Warning:`#faad14`
81+
- Error:`#ff4d4f`
82+
- Border:`#d9d9d9`
83+
- 主文本:`rgba(0,0,0,0.88)`
84+
- 次文本:`rgba(0,0,0,0.65)`
85+
86+
规则:
87+
88+
- 重要动作用主色
89+
- 状态展示优先 `a-tag` 语义色
90+
- 禁止页面内零散定义“看起来差不多”的新颜色
91+
92+
## 组件规范
93+
94+
### 按钮
95+
96+
- 主操作:`a-button type="primary"`
97+
- 次操作:默认 `a-button`
98+
- 危险操作:`a-button danger`
99+
- 同一视觉区域最多两个主按钮
100+
101+
### 表单
102+
103+
- 统一使用 `a-form`
104+
- 必须有 label 和基础校验规则
105+
- 标签对齐方式同页保持一致
106+
- 复杂表单优先纵向布局
107+
- 输入组件优先:`a-input` / `a-select` / `a-date-picker` / `a-switch` / `a-radio-group` / `a-checkbox-group`
108+
109+
### 表格
110+
111+
- 统一使用 `a-table`
112+
- 必须设置 `rowKey`
113+
- 默认启用分页
114+
- 列信息聚焦,避免密度过高
115+
- 排序仅在显著提升任务效率时启用
116+
117+
### 导航与信息组织
118+
119+
- 导航:`a-menu` / `a-breadcrumb` / `a-tabs`
120+
- 分组:`a-card`
121+
- 操作组:`a-dropdown`
122+
- 详情展示:`a-descriptions`
123+
124+
### 反馈
125+
126+
- 轻提示:`message.success()`
127+
- 显著错误:`notification.error()`
128+
- 不可逆动作:`modal.confirm()`
129+
- 加载反馈:`a-spin`
130+
131+
## 页面蓝图
132+
133+
### 列表页
134+
135+
1. 顶部筛选区(`a-form`
136+
2. 中部数据区(`a-table`
137+
3. 底部分页(`a-pagination` 或表格内建)
138+
139+
### 详情页
140+
141+
1. 核心信息区用 `a-descriptions`
142+
2. 自然分区内容再使用 `a-tabs`
143+
144+
### 编辑页
145+
146+
1. 以表单为主结构
147+
2. 提交与取消按钮放在清晰的操作行
148+
149+
### 仪表盘
150+
151+
1. 关键指标用 `a-statistic`
152+
2. 分模块卡片化展示
153+
154+
### 设置页
155+
156+
1. 按领域拆分 `a-tabs`
157+
2. 每个 tab 内聚焦一组表单能力
158+
159+
## 交互位置约定
160+
161+
- 全局主操作:右上或标题区右侧
162+
- 筛选/检索:页面顶部
163+
- 主数据区:中部连续区域
164+
- 同类按钮:紧邻分组并有明确优先级
165+
166+
## 常见反模式与纠偏
167+
168+
| 反模式 | 纠偏方式 |
169+
| --- | --- |
170+
| 按钮写 inline style 改颜色和圆角 | 改用全局 token + AntDV 语义属性 |
171+
| 页面出现 14px/18px 这类散点间距 | 回退到 4/8/12/16/24/32 |
172+
| 组件圆角写成 5px/9px/14px | 回退到 6/8/10/12 |
173+
| 登录页按钮单独用 `large` | 统一为 `middle` |
174+
| 同页混用多个组件库 | 优先统一为 AntDV 组件 |
175+
| 使用 `<script setup lang="ts">` | 改为 JS 版 `script setup` |
176+
177+
## 快速检查清单
178+
179+
- 是否仅使用项目 token 定义的间距与圆角?
180+
- 按钮是否全部 `size="middle"`
181+
- 是否存在按钮手写视觉样式(颜色/高度/圆角/inline style)?
182+
- 页面是否使用 AntDV 语义组件而不是自造同类组件?
183+
- 是否保持布局层级清晰、操作优先级明确?
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
interface:
2+
display_name: "Ant Design Vue 统一规范"
3+
short_description: "统一 Ant Design Vue 页面布局、间距、圆角与按钮规范"
4+
default_prompt: "请基于 Vue3 + Ant Design Vue 4.x 先输出规范化 UI 方案(布局、组件映射、一致性检查),再给实现建议;严格遵守全局间距/圆角 token 和按钮统一 middle 规则。"

backend/config.yaml

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,3 @@ ghost:
5555
"--concurrent-rowcount=false",
5656
"--chunk-size=800",
5757
]
58-
59-
# 消息通知配置,用于工单消息推送
60-
notify:
61-
notice_url: "http://localhost:8083" # 消息通知和导出工单域名前缀
62-
wechat:
63-
enable: true
64-
webhook: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=123.com"
65-
dingtalk:
66-
enable: false
67-
webhook: "https://oapi.dingtalk.com/robot/send?access_token=1234"
68-
keywords: "goinsight"
69-
mail:
70-
enable: false
71-
username: "xxx@163.com"
72-
password: "1234.com"
73-
host: "smtp.163.com"
74-
port: 465

backend/config.yaml.template

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,3 @@ ghost:
5555
"--concurrent-rowcount=false",
5656
"--chunk-size=800",
5757
]
58-
59-
# 消息通知配置,用于工单消息推送
60-
notify:
61-
notice_url: "http://localhost:8083" # 消息通知和导出工单域名前缀
62-
wechat:
63-
enable: true
64-
webhook: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=123.com"
65-
dingtalk:
66-
enable: false
67-
webhook: "https://oapi.dingtalk.com/robot/send?access_token=1234"
68-
keywords: "goinsight"
69-
mail:
70-
enable: false
71-
username: "xxx@163.com"
72-
password: "1234.com"
73-
host: "smtp.163.com"
74-
port: 465

backend/internal/bootstrap/config.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package bootstrap
22

33
import (
44
"fmt"
5-
"strings"
65

76
"github.com/lazzyfu/goinsight/internal/global"
87

@@ -22,13 +21,5 @@ func InitializeConfig(config string) *viper.Viper {
2221
fmt.Println(err)
2322
}
2423

25-
sanitizeConfig()
26-
2724
return v
2825
}
29-
30-
// sanitizeConfig cleans up loaded configuration values for safe use.
31-
// Example: trim trailing slashes from base URLs to avoid double slashes when concatenating paths.
32-
func sanitizeConfig() {
33-
global.App.Config.Notify.NoticeURL = strings.TrimRight(global.App.Config.Notify.NoticeURL, "/")
34-
}

backend/internal/bootstrap/db.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package bootstrap
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
7+
"strings"
68
"time"
79

810
"github.com/lazzyfu/goinsight/internal/global"
@@ -83,6 +85,8 @@ func initializeMySQLGorm() *gorm.DB {
8385
initializeGlobalInspectParams(db)
8486
// 初始化系统管理员
8587
initializeAdminUser(db)
88+
// 初始化通知配置
89+
initializeNotifySettings(db)
8690
return db
8791
}
8892
}
@@ -99,6 +103,7 @@ func initializeTables(db *gorm.DB) {
99103
&commonModels.InsightInstanceEnvironments{},
100104
&commonModels.InsightInstances{},
101105
&commonModels.InsightInstanceSchemas{},
106+
&commonModels.InsightNotifySettings{},
102107
// inspect
103108
&inspectModels.InsightInspectGlobalParams{},
104109
&inspectModels.InsightInspectInstanceParams{},
@@ -310,3 +315,45 @@ func initializeGlobalInspectParams(db *gorm.DB) {
310315
}
311316
}
312317
}
318+
319+
// 初始化消息通知配置(优先使用DB,首次则写入默认配置)
320+
func initializeNotifySettings(db *gorm.DB) {
321+
const notifyConfigKeyDefault = "default"
322+
323+
var record commonModels.InsightNotifySettings
324+
err := db.Where("config_key = ?", notifyConfigKeyDefault).First(&record).Error
325+
if errors.Is(err, gorm.ErrRecordNotFound) {
326+
record = commonModels.InsightNotifySettings{
327+
ConfigKey: notifyConfigKeyDefault,
328+
NoticeURL: defaultNoticeURL(),
329+
WechatEnable: false,
330+
WechatWebhook: "",
331+
DingTalkEnable: false,
332+
DingTalkWebhook: "",
333+
DingTalkKeywords: "",
334+
MailEnable: false,
335+
MailUsername: "",
336+
MailPassword: "",
337+
MailHost: "",
338+
MailPort: 465,
339+
}
340+
if err := db.Create(&record).Error; err != nil {
341+
global.App.Log.Fatal("seed notify settings failed", err.Error())
342+
}
343+
return
344+
}
345+
if err != nil {
346+
global.App.Log.Fatal("load notify settings failed", err.Error())
347+
}
348+
}
349+
350+
func defaultNoticeURL() string {
351+
address := strings.TrimSpace(global.App.Config.App.ListenAddress)
352+
if address == "" {
353+
return ""
354+
}
355+
if strings.HasPrefix(address, "http://") || strings.HasPrefix(address, "https://") {
356+
return strings.TrimRight(address, "/")
357+
}
358+
return "http://" + strings.TrimRight(address, "/")
359+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package forms
2+
3+
type NotifyWechatForm struct {
4+
Enable bool `json:"enable"`
5+
Webhook string `json:"webhook"`
6+
}
7+
8+
type NotifyDingTalkForm struct {
9+
Enable bool `json:"enable"`
10+
Webhook string `json:"webhook"`
11+
Keywords string `json:"keywords"`
12+
}
13+
14+
type NotifyMailForm struct {
15+
Enable bool `json:"enable"`
16+
Username string `json:"username"`
17+
Password string `json:"password"`
18+
Host string `json:"host"`
19+
Port int `json:"port"`
20+
HasPassword bool `json:"has_password"`
21+
}
22+
23+
type AdminUpdateNotifyConfigForm struct {
24+
NoticeURL string `json:"notice_url" binding:"required"`
25+
Wechat NotifyWechatForm `json:"wechat"`
26+
DingTalk NotifyDingTalkForm `json:"dingtalk"`
27+
Mail NotifyMailForm `json:"mail"`
28+
}
29+
30+
type AdminTestNotifyConfigForm struct {
31+
Channel string `json:"channel" binding:"required,oneof=wechat dingtalk mail"`
32+
}
33+
34+
type AdminNotifyConfigResponse struct {
35+
NoticeURL string `json:"notice_url"`
36+
Wechat NotifyWechatForm `json:"wechat"`
37+
DingTalk NotifyDingTalkForm `json:"dingtalk"`
38+
Mail NotifyMailForm `json:"mail"`
39+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package models
2+
3+
// 系统消息通知配置(单例)
4+
type InsightNotifySettings struct {
5+
*Model
6+
ConfigKey string `gorm:"type:varchar(32);not null;default:default;uniqueIndex:uniq_notify_config_key;comment:配置唯一键" json:"config_key"`
7+
8+
NoticeURL string `gorm:"type:varchar(512);not null;default:'';comment:通知链接前缀" json:"notice_url"`
9+
10+
WechatEnable bool `gorm:"type:boolean;not null;default:false;comment:是否启用企业微信通知" json:"wechat_enable"`
11+
WechatWebhook string `gorm:"type:varchar(512);not null;default:'';comment:企业微信Webhook" json:"wechat_webhook"`
12+
13+
DingTalkEnable bool `gorm:"type:boolean;not null;default:false;comment:是否启用钉钉通知" json:"dingtalk_enable"`
14+
DingTalkWebhook string `gorm:"type:varchar(512);not null;default:'';comment:钉钉Webhook" json:"dingtalk_webhook"`
15+
DingTalkKeywords string `gorm:"type:varchar(256);not null;default:'';comment:钉钉关键字" json:"dingtalk_keywords"`
16+
17+
MailEnable bool `gorm:"type:boolean;not null;default:false;comment:是否启用邮件通知" json:"mail_enable"`
18+
MailUsername string `gorm:"type:varchar(254);not null;default:'';comment:邮件用户名" json:"mail_username"`
19+
MailPassword string `gorm:"type:varchar(1024);not null;default:'';comment:邮件密码(加密)" json:"mail_password"`
20+
MailHost string `gorm:"type:varchar(255);not null;default:'';comment:邮件主机" json:"mail_host"`
21+
MailPort int `gorm:"type:int;not null;default:0;comment:邮件端口" json:"mail_port"`
22+
}
23+
24+
func (InsightNotifySettings) TableName() string {
25+
return "insight_notify_settings"
26+
}

0 commit comments

Comments
 (0)