chore: initial commit of ai site platform

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
whm
2026-07-31 10:31:17 +08:00
commit 4ca82fb58a
203 changed files with 45745 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
package userstore
import (
"fmt"
"regexp"
"strings"
"unicode"
)
var tenantSlugRe = regexp.MustCompile(`^[a-z][a-z0-9-]{1,31}$`)
// 路径段保留字:不可用作公司 slug与后续 /{slug}/ 路由冲突)
var reservedTenantSlugs = map[string]struct{}{
"api": {}, "ai": {}, "gateway": {}, "platform": {}, "_platform": {},
"admin": {}, "assets": {}, "static": {}, "www": {}, "m": {}, "public": {},
"health": {}, "ops": {}, "console": {}, "login": {}, "register": {},
"favicon.ico": {}, "robots.txt": {},
}
// NormalizeTenantSlug 规范化公司路径 slug全局唯一用于 www.yuxinda.com/{slug}/)。
func NormalizeTenantSlug(raw string) (string, error) {
s := strings.TrimSpace(strings.ToLower(raw))
s = strings.ReplaceAll(s, "_", "-")
s = strings.ReplaceAll(s, " ", "-")
var b strings.Builder
prevDash := false
for _, r := range s {
if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') {
b.WriteRune(r)
prevDash = false
continue
}
if r == '-' {
if b.Len() == 0 || prevDash {
continue
}
b.WriteByte('-')
prevDash = true
continue
}
// 跳过其它字符(含中文);中文名需用户另填 slug
}
s = strings.Trim(b.String(), "-")
if s == "" {
return "", fmt.Errorf("公司路径 slug 不能为空(请用英文/数字,如 aaa")
}
if !tenantSlugRe.MatchString(s) {
return "", fmt.Errorf("slug 须为 232 位,小写字母开头,仅含 a-z / 0-9 / -")
}
if _, bad := reservedTenantSlugs[s]; bad {
return "", fmt.Errorf("slug %q 为系统保留字", s)
}
return s, nil
}
// SuggestTenantSlug 从公司名生成候选(中文名可能得不到可用 slug需人工填写
func SuggestTenantSlug(name string) string {
name = strings.TrimSpace(name)
if name == "" {
return ""
}
// 纯 ASCII 名:直接规范化
ascii := true
for _, r := range name {
if r > unicode.MaxASCII {
ascii = false
break
}
}
if ascii {
s, err := NormalizeTenantSlug(name)
if err == nil {
return s
}
}
return ""
}