sync: 对齐小程序 v1.0.2 生产代码并脱敏

This commit is contained in:
MiFaZhan
2026-10-29 15:15:12 +08:00
parent a7abd476f0
commit 5fcf74deb0
423 changed files with 15001 additions and 6382 deletions
+4
View File
@@ -11,6 +11,9 @@ import (
)
type IAppV1 interface {
WarningPreference(ctx context.Context, req *v1.WarningPreferenceReq) (*v1.WarningPreferenceRes, error)
SaveWarningPreference(ctx context.Context, req *v1.SaveWarningPreferenceReq) (*v1.SaveWarningPreferenceRes, error)
UnbindWechat(ctx context.Context, req *v1.UnbindWechatReq) (*v1.UnbindWechatRes, error)
Captcha(ctx context.Context, req *v1.CaptchaReq) (res *v1.CaptchaRes, err error)
SideCaptcha(ctx context.Context, req *v1.SideCaptchaReq) (res *v1.SideCaptchaRes, err error)
CheckSideCaptcha(ctx context.Context, req *v1.CheckSideCaptchaReq) (res *v1.CheckSideCaptchaRes, err error)
@@ -67,6 +70,7 @@ type IAppV1 interface {
WarningConfigMeta(ctx context.Context, req *v1.WarningConfigMetaReq) (res *v1.WarningConfigMetaRes, err error)
WarningConfigBatchSave(ctx context.Context, req *v1.WarningConfigBatchSaveReq) (res *v1.WarningConfigBatchSaveRes, err error)
WarningConfigBatchNotify(ctx context.Context, req *v1.WarningConfigBatchNotifyReq) (res *v1.WarningConfigBatchNotifyRes, err error)
WorkOrderAction(ctx context.Context, req *v1.WorkOrderActionReq) (res *v1.WorkOrderActionRes, err error)
WorkOrderList(ctx context.Context, req *v1.WorkOrderListReq) (res *v1.WorkOrderListRes, err error)
WorkOrderDetail(ctx context.Context, req *v1.WorkOrderDetailReq) (res *v1.WorkOrderDetailRes, err error)
WorkOrderCreate(ctx context.Context, req *v1.WorkOrderCreateReq) (res *v1.WorkOrderCreateRes, err error)
+21
View File
@@ -0,0 +1,21 @@
package v1
import (
"github.com/gogf/gf/v2/frame/g"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model"
)
type AllocateResultReq struct {
g.Meta `path:"/card/allocate-result" method:"get" tags:"APP-卡片" summary:"查询本人划拨结果" x-check-permission:"cpm:iot:tSimCardAllocate:batch:submit"`
BatchNo string `json:"batchNo" v:"length:0,64"`
RequestId string `json:"requestId" v:"length:0,96"`
}
type AllocateResultRes struct{ *model.AppExecutionLogItem }
type AllocateDetailsReq struct {
g.Meta `path:"/card/allocate-details" method:"get" tags:"APP-卡片" summary:"查询本人划拨明细" x-check-permission:"cpm:iot:tSimCardAllocate:batch:submit"`
model.AppExecutionLogDetailParam
}
type AllocateDetailsRes struct {
Items []*model.AppExecutionLogDetail `json:"items"`
Total int `json:"total"`
}
+9
View File
@@ -59,6 +59,15 @@ type PhoneLoginRes struct {
model.AppAuthTokenModel
}
type PhoneSmsLoginReq struct {
g.Meta `path:"/auth/phone-login" method:"post" tags:"APP-授权" summary:"手机号短信验证码登录"`
model.AppPhoneSmsLoginParam
}
type PhoneSmsLoginRes struct {
model.AppAuthTokenModel
}
type WechatLoginReq struct {
g.Meta `path:"/auth/wechat-login" method:"post" tags:"APP-授权" summary:"微信一键登录"`
model.AppWechatLoginParam
+3 -2
View File
@@ -12,8 +12,9 @@ type CustomerListReq struct {
}
type CustomerListRes struct {
Items []*model.AppCustomerModel `json:"items" dc:"客户列表"`
Total int `json:"total" dc:"总数"`
Summary *model.AppCustomerSummary `json:"summary" dc:"当前筛选结果汇总"`
Items []*model.AppCustomerModel `json:"items" dc:"客户列表"`
Total int `json:"total" dc:"总数"`
}
type CustomerDetailReq struct {
+28
View File
@@ -0,0 +1,28 @@
package v1
import (
"github.com/gogf/gf/v2/frame/g"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model"
)
type ExecutionLogListReq struct {
g.Meta `path:"/execution-log/list" method:"get" tags:"APP-执行日志" summary:"查询权限范围内执行日志" x-check-permission:"cpm:common:batchExecutionLog:list"`
model.AppExecutionLogListParam
}
type ExecutionLogListRes struct {
Items []*model.AppExecutionLogItem `json:"items"`
Total int `json:"total"`
}
type ExecutionLogSummaryReq struct {
g.Meta `path:"/execution-log/summary" method:"get" tags:"APP-执行日志" summary:"查询权限范围内执行日志概要" x-check-permission:"cpm:common:batchExecutionLog:summary"`
BatchNo string `json:"batchNo" v:"required|length:1,64"`
}
type ExecutionLogSummaryRes struct{ *model.AppExecutionLogItem }
type ExecutionLogDetailsReq struct {
g.Meta `path:"/execution-log/details" method:"get" tags:"APP-执行日志" summary:"查询权限范围内执行日志明细" x-check-permission:"cpm:common:batchExecutionLog:detailList"`
model.AppExecutionLogDetailParam
}
type ExecutionLogDetailsRes struct {
Items []*model.AppExecutionLogDetail `json:"items"`
Total int `json:"total"`
}
+24
View File
@@ -0,0 +1,24 @@
package v1
import (
"github.com/gogf/gf/v2/frame/g"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model"
)
type WarningPreferenceReq struct {
g.Meta `path:"/user/wechat/warning-preference" method:"get" tags:"APP-用户" summary:"读取微信预警提醒偏好"`
}
type WarningPreferenceRes struct {
model.AppWarningPreferenceModel
}
type SaveWarningPreferenceReq struct {
g.Meta `path:"/user/wechat/warning-preference" method:"post" tags:"APP-用户" summary:"保存微信预警提醒偏好"`
model.AppWarningPreferenceParam
}
type SaveWarningPreferenceRes struct {
model.AppWarningPreferenceModel
}
type UnbindWechatReq struct {
g.Meta `path:"/user/wechat/unbind" method:"post" tags:"APP-用户" summary:"解除当前账号微信绑定"`
}
type UnbindWechatRes struct{ model.AppWechatBindModel }
+6
View File
@@ -42,3 +42,9 @@ type WorkOrderUploadReq struct {
type WorkOrderUploadRes struct {
*model.SysOssUploadModel
}
type WorkOrderActionReq struct {
g.Meta `path:"/work-order/action" method:"post" tags:"APP-工单" summary:"按权限跟进或办理工单" x-check-permission:"cpm:gen:tWoMain:view,cpm:gen:tWoMain:list"`
model.AppWorkOrderActionParam
}
type WorkOrderActionRes struct{}
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package testdemo
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version
package v1 //testdemo
+2 -2
View File
@@ -1,7 +1,7 @@
// Package testtree
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version
package v1 //testtree
@@ -64,4 +64,4 @@ type TestTreeTreeOptionReq struct {
g.Meta `path:"/testTree/treeOption" method:"get" tags:"测试树表" summary:"获取测试树表关系树选项" x-check-permission:"cpm:gen:testTree:treeOption"`
}
type TestTreeTreeOptionRes []tree.Node
type TestTreeTreeOptionRes []tree.Node
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package sysnoticeuser
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version
package v1 //sysnoticeuser
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
+1 -1
View File
@@ -1,7 +1,7 @@
// Package v1
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package v1
@@ -1,7 +1,7 @@
# config.yaml 配置文件
# @Link https://github.com/xiujiecn/xiu-admin
# @Copyright Copyright (c) 2025 LiXiujie
# @Author Lxj <li@xiujie.cn>
# @Author Lxj <li@example.com>
# @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
# 系统配置
system:
@@ -14,6 +14,7 @@ system:
# path: "/data/app/iotlcmadmin-web-svc/upload"
# 本地开发环境
path: "resource/upload"
publicUrl: ""
# 服务配置
server:
@@ -76,7 +77,7 @@ register:
url: "http://192.0.2.29:11190/api/v1/sms/send"
method: "POST"
headers: {}
bodyTemplate: '{"config":{"serviceType":"1","regionId":"cn-hangzhou","accessKeyId":"","accessKeySecret":"","signName":"","templateId":""},"params":{"phoneNumber":"{contact}","msgContent":"{\"code\":\"{code}\"}"}}'
bodyTemplate: '{"config":{"scene":"{scene}"},"params":{"phoneNumber":"{contact}","msgContent":"{code}"}}'
successStatus: 200
database:
@@ -147,34 +148,34 @@ payment:
enabled: true
envFile: ""
apiBase: "https://api.mch.weixin.qq.com"
mchId: "1723059989"
mchSerialNo: "32A3CB6381D743A4ADBF3885BB16882C6CE06D03"
apiV3Key: "ce9e5486d2979810f21d09f398d212e0"
mchId: "${WECHAT_MCH_ID}"
mchSerialNo: "${WECHAT_MCH_SERIAL_NO}"
apiV3Key: "${WECHAT_API_V3_KEY}"
privateKeyPath: "resource/certs/wechatpay_apiclient_key.pem"
notifyUrl: "https://app.iotlcm.example.com/api/v1/payment/wechat/notify"
notifyBaseUrl: "https://app.iotlcm.example.com"
refundNotifyUrl: "https://app.iotlcm.example.com/api/v1/payment/wechat/refund-notify"
notifyUrl: "https://example.com/"
notifyBaseUrl: "https://example.com/"
refundNotifyUrl: "https://example.com/"
timeoutMinutes: 5 #待支付时间(分钟)
platformPublicKeyId: "PUB_KEY_ID_0117230599892026052200111565002404"
platformPublicKeyId: "${WECHAT_PLATFORM_KEY_ID}"
platformPublicKeyPath: "resource/certs/wechatpay_platform_public_key.pem"
h5:
enabled: true
appId: "wx9e26905702c1a372"
appId: "${WECHAT_APP_ID}"
appName: "物联网卡管理平台"
appUrl: "https://app.iotlcm.example.com"
appUrl: "https://example.com/"
payerClientIp: ""
mini:
enabled: true
appId: "wx9e26905702c1a372"
appSecret: "3ee708d13993282fed770ea1cab95d90"
appId: "${WECHAT_APP_ID}"
appSecret: "${WECHAT_APP_SECRET}"
appCardRecognition:
enabled: true
provider: "openai-compatible"
baseUrl: "https://xueyangai.com/v1"
endpoint: ""
model: "qwen3.7-flash"
apiKey: "sk-nAhIIyqOn7JvQp1ti8o24GcBLgWqBUFKBaDTwAmFYZm0Hycy"
model: "qwen3.7-plus"
apiKey: "${AI_API_KEY}"
timeout: "25s"
maxImageBytes: 8388608
maxTokens: 256
@@ -184,7 +185,7 @@ appCardRecognition:
period: "1m"
appWarning:
wechatSubscribeTemplateId: "DMDP2PKktdtG1ES_3Ic1JcR0LGELQmWE6LunYyerHCY"
wechatSubscribeTemplateId: "${WECHAT_SUBSCRIBE_TEMPLATE_ID}"
tsdb:
database: "TdEngine" #可选择 TdEngine、Influxdb
@@ -193,8 +194,10 @@ tsdb:
# dsn: "root:taosdata@http(127.0.0.1:6041)/"
type: "taosWS" #websocket连接方式,端口是6041
# dsn: "root:taosdata@ws(127.0.0.1:6041)/"
dsn: "root:sdyz2026__@ws(192.0.2.29:6041)/"
dsn: "${TAOS_USER}:${TAOS_PASSWORD}@ws(${TAOS_HOST}:6041)/"
dbName: "iotlcm"
dailyDbName: "iotlcm_daily"
monthlyDbName: "iotlcm_monthly"
maxOpenConns: 100
maxIdleConns: 10
@@ -213,6 +216,7 @@ router:
- /api/v1/auth/sms
- /api/v1/auth/register
- /api/v1/auth/login
- /api/v1/auth/phone-login
- /api/v1/auth/wechat-login
- /api/v1/auth/wechat-bind-phone
- /api/v1/auth/forgot-password
@@ -273,17 +277,20 @@ upstream:
# clientName: "iotlcm.example.com:8510"
clientName: "http://iotlcm.example.com:8110"
timeout: 10s
gateway:
clientName: "${UPSTREAM_GATEWAY_ADDR}"
timeout: 10s
onelinkMock:
enabled: false
baseUrl: "https://iotlcm.example.com/onelink-mock/v5"
appid: "100059999270000006"
password: "577d2b16546cbac103df9e0ce38393b5014152c8e4d76d5636ea5ccc51319033"
appid: "${ONELINK_APP_ID}"
password: "${ONELINK_PASSWORD}"
timeout: "10s"
tokenTTL: 3600
accounts:
- name: "默认测试应用"
appid: "100059999270000006"
password: "577d2b16546cbac103df9e0ce38393b5014152c8e4d76d5636ea5ccc51319033"
appid: "${ONELINK_APP_ID}"
password: "${ONELINK_PASSWORD}"
latestToken: ""
tokenExpireAt: ""
isDefault: true
+16 -5
View File
@@ -1,7 +1,7 @@
# config_default.yaml 配置文件
# @Link https://github.com/xiujiecn/xiu-admin
# @Copyright Copyright (c) 2025 LiXiujie
# @Author Lxj <li@xiujie.cn>
# @Author Lxj <li@example.com>
# @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
# 系统配置
system:
@@ -12,6 +12,7 @@ system:
upload:
local:
path: "resource/upload"
publicUrl: ""
# 服务配置
server:
# 基本配置
@@ -69,10 +70,15 @@ register:
url: "http://127.0.0.1:11190/api/v1/sms/send"
method: "POST"
headers: {}
bodyTemplate: '{"config":{"serviceType":"1","regionId":"cn-hangzhou","accessKeyId":"","accessKeySecret":"","signName":"","templateId":""},"params":{"phoneNumber":"{contact}","msgContent":"{\"code\":\"{code}\"}"}}'
bodyTemplate: '{"config":{"scene":"{scene}"},"params":{"phoneNumber":"{contact}","msgContent":"{code}"}}'
successStatus: 200
database:
legacyCard:
link: "${LEGACY_CARD_DSN}" # Optional read-only legacy database
debug: false
maxOpen: 5
maxIdle: 2
logger:
path: "resource/log/server/sql"
level: "all"
@@ -149,8 +155,8 @@ appCardRecognition:
provider: "openai-compatible"
baseUrl: "https://xueyangai.com/v1"
endpoint: ""
model: "qwen3.7-flash"
apiKey: "sk-nAhIIyqOn7JvQp1ti8o24GcBLgWqBUFKBaDTwAmFYZm0Hycy"
model: "qwen3.7-plus"
apiKey: "${AI_API_KEY}"
timeout: "25s"
maxImageBytes: 8388608
maxTokens: 256
@@ -160,7 +166,7 @@ appCardRecognition:
period: "1m"
appWarning:
wechatSubscribeTemplateId: "DMDP2PKktdtG1ES_3Ic1JcR0LGELQmWE6LunYyerHCY"
wechatSubscribeTemplateId: "${WECHAT_SUBSCRIBE_TEMPLATE_ID}"
appBusinessAsync:
enabled: false
@@ -169,11 +175,15 @@ appBusinessAsync:
failOnPublish: false
upstream:
appDiagnosisToken: "${APP_DIAGNOSIS_TOKEN}"
provider: "onelink_mock"
default:
# 正式环境建议配置为上游代理 HTTP 服务名,例如 iotlcmupstreamproxy-http-svc:8510
clientName: ""
timeout: 10s
gateway:
clientName: "${UPSTREAM_GATEWAY_ADDR}"
timeout: 10s
onelinkMock:
enabled: false
baseUrl: "https://iotlcm.example.com/onelink-mock/v5"
@@ -215,6 +225,7 @@ router:
- /api/v1/auth/sms
- /api/v1/auth/register
- /api/v1/auth/login
- /api/v1/auth/phone-login
- /api/v1/auth/wechat-login
- /api/v1/auth/wechat-bind-phone
- /api/v1/auth/forgot-password
+1 -1
View File
@@ -32,6 +32,7 @@ require (
go.opentelemetry.io/otel v1.38.0
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394
golang.org/x/net v0.40.0
golang.org/x/sync v0.14.0
golang.org/x/tools v0.31.0
gorm.io/gorm v1.25.12
)
@@ -105,7 +106,6 @@ require (
golang.org/x/crypto v0.38.0 // indirect
golang.org/x/image v0.23.0 // indirect
golang.org/x/mod v0.24.0 // indirect
golang.org/x/sync v0.14.0 // indirect
golang.org/x/sys v0.35.0 // indirect
golang.org/x/text v0.25.0 // indirect
golang.org/x/time v0.8.0 // indirect
+1 -1
View File
@@ -1,7 +1,7 @@
// Package cmd
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package cmd
+1 -1
View File
@@ -1,7 +1,7 @@
// Package cmd
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package cmd
+4
View File
@@ -6,6 +6,7 @@ import (
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/websocket"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/router"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/service"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/service/allocatedispatch"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/tasks"
"github.com/gogf/gf/v2/frame/g"
@@ -41,7 +42,10 @@ var Http = &gcmd.Command{
s.SetDumpRouterMap(dumpRouterMap)
router.InitRouter(ctx, s)
websocket.StartWebSocket(ctx)
stopAllocateRecovery := allocatedispatch.Start(ctx)
defer stopAllocateRecovery()
s.Run()
stopAllocateRecovery()
inithttp.CleanupHttp(ctx)
return nil
},
+1 -1
View File
@@ -1,7 +1,7 @@
// Package cmd
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package cmd
+2 -2
View File
@@ -1,18 +1,18 @@
// Package cmd
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package cmd
import (
"context"
"fmt"
"time"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/cmd/inithttp"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/consts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/websocket"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/service"
"time"
)
func init() {
+2 -2
View File
@@ -2,10 +2,10 @@ package cmd
import (
"context"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/consts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/event"
"os"
"sync"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/consts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/event"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
+1
View File
@@ -27,6 +27,7 @@ const (
BatchDetailStatusFailed = 3
BatchSourceTypeBatchSelect = 0
BatchSourceTypeFile = 3
BatchTypePrepare = 4
BatchTypeAllocate = 3
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts
+4 -2
View File
@@ -1,12 +1,14 @@
// Package consts
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts
const (
QueueSysOptLog = "queue:sys_opt_log"
QueueSysOptLog = "queue:sys_opt_log"
QueueWorkOrderAutoClose = "iotlcm.work_order.auto_close"
QueueWorkOrderAutoCloseDelay = "iotlcm.work_order.auto_close.delay"
)
// 数据库变动类型
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts
+1 -1
View File
@@ -1,7 +1,7 @@
// Package consts
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package consts
@@ -0,0 +1,39 @@
package app
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"strings"
v1 "git.5iot.com/iotlcm-public/iotlcm-app/api/app/v1"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/allocaterequest"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/contexts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/service/executionlog"
)
type AllocateResultController struct{}
func (c *AllocateResultController) Result(ctx context.Context, req *v1.AllocateResultReq) (*v1.AllocateResultRes, error) {
batchNo := strings.TrimSpace(req.BatchNo)
if batchNo == "" {
batch, err := allocaterequest.Find(ctx, contexts.GetTenantId(ctx), contexts.GetUserId(ctx), req.RequestId)
if err != nil {
return nil, err
}
if batch == nil {
return nil, gerror.New("划拨批次不存在或无权查看")
}
batchNo = batch.BatchNo
}
item, err := executionlog.AllocateSummary(ctx, batchNo)
if err != nil {
return nil, err
}
return &v1.AllocateResultRes{AppExecutionLogItem: item}, nil
}
func (c *AllocateResultController) Details(ctx context.Context, req *v1.AllocateDetailsReq) (*v1.AllocateDetailsRes, error) {
items, total, err := executionlog.AllocateDetails(ctx, &req.AppExecutionLogDetailParam)
if err != nil {
return nil, err
}
return &v1.AllocateDetailsRes{Items: items, Total: total}, nil
}
@@ -57,6 +57,14 @@ func (c *ControllerV1) PhoneLogin(ctx context.Context, req *v1.PhoneLoginReq) (r
return &v1.PhoneLoginRes{AppAuthTokenModel: *token}, nil
}
func (c *ControllerV1) PhoneSmsLogin(ctx context.Context, req *v1.PhoneSmsLoginReq) (res *v1.PhoneSmsLoginRes, err error) {
token, err := service.AppAuth().PhoneSmsLogin(ctx, &req.AppPhoneSmsLoginParam)
if err != nil {
return nil, err
}
return &v1.PhoneSmsLoginRes{AppAuthTokenModel: *token}, nil
}
func (c *ControllerV1) WechatLogin(ctx context.Context, req *v1.WechatLoginReq) (res *v1.WechatLoginRes, err error) {
data, err := service.AppAuth().WechatLogin(ctx, &req.AppWechatLoginParam)
if err != nil {
@@ -8,11 +8,11 @@ import (
)
func (c *ControllerV1) CustomerList(ctx context.Context, req *v1.CustomerListReq) (res *v1.CustomerListRes, err error) {
items, total, err := service.AppUser().CustomerList(ctx, &req.AppCustomerListParam)
items, total, summary, err := service.AppUser().CustomerList(ctx, &req.AppCustomerListParam)
if err != nil {
return nil, err
}
return &v1.CustomerListRes{Items: items, Total: total}, nil
return &v1.CustomerListRes{Items: items, Total: total, Summary: summary}, nil
}
func (c *ControllerV1) CustomerDetail(ctx context.Context, req *v1.CustomerDetailReq) (res *v1.CustomerDetailRes, err error) {
@@ -0,0 +1,29 @@
package app
import (
"context"
v1 "git.5iot.com/iotlcm-public/iotlcm-app/api/app/v1"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/service"
)
func (c *ControllerV1) WarningPreference(ctx context.Context, req *v1.WarningPreferenceReq) (*v1.WarningPreferenceRes, error) {
data, err := service.AppUser().WarningPreference(ctx)
if err != nil {
return nil, err
}
return &v1.WarningPreferenceRes{AppWarningPreferenceModel: *data}, nil
}
func (c *ControllerV1) SaveWarningPreference(ctx context.Context, req *v1.SaveWarningPreferenceReq) (*v1.SaveWarningPreferenceRes, error) {
data, err := service.AppUser().SaveWarningPreference(ctx, &req.AppWarningPreferenceParam)
if err != nil {
return nil, err
}
return &v1.SaveWarningPreferenceRes{AppWarningPreferenceModel: *data}, nil
}
func (c *ControllerV1) UnbindWechat(ctx context.Context, req *v1.UnbindWechatReq) (*v1.UnbindWechatRes, error) {
data, err := service.AppUser().UnbindWechat(ctx)
if err != nil {
return nil, err
}
return &v1.UnbindWechatRes{AppWechatBindModel: *data}, nil
}
@@ -38,3 +38,10 @@ func (c *ControllerV1) WorkOrderUpload(ctx context.Context, req *v1.WorkOrderUpl
}
return &v1.WorkOrderUploadRes{SysOssUploadModel: workOrderFile}, nil
}
func (c *ControllerV1) WorkOrderAction(ctx context.Context, req *v1.WorkOrderActionReq) (*v1.WorkOrderActionRes, error) {
if err := service.AppWorkOrder().Action(ctx, &req.AppWorkOrderActionParam); err != nil {
return nil, err
}
return &v1.WorkOrderActionRes{}, nil
}
@@ -0,0 +1,31 @@
package app
import (
"context"
v1 "git.5iot.com/iotlcm-public/iotlcm-app/api/app/v1"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/service/executionlog"
)
type ExecutionLogController struct{}
func (c *ExecutionLogController) List(ctx context.Context, req *v1.ExecutionLogListReq) (*v1.ExecutionLogListRes, error) {
items, total, err := executionlog.List(ctx, &req.AppExecutionLogListParam)
if err != nil {
return nil, err
}
return &v1.ExecutionLogListRes{Items: items, Total: total}, nil
}
func (c *ExecutionLogController) Summary(ctx context.Context, req *v1.ExecutionLogSummaryReq) (*v1.ExecutionLogSummaryRes, error) {
item, err := executionlog.Summary(ctx, req.BatchNo)
if err != nil {
return nil, err
}
return &v1.ExecutionLogSummaryRes{AppExecutionLogItem: item}, nil
}
func (c *ExecutionLogController) Details(ctx context.Context, req *v1.ExecutionLogDetailsReq) (*v1.ExecutionLogDetailsRes, error) {
items, total, err := executionlog.Details(ctx, &req.AppExecutionLogDetailParam)
if err != nil {
return nil, err
}
return &v1.ExecutionLogDetailsRes{Items: items, Total: total}, nil
}
+1 -1
View File
@@ -1,7 +1,7 @@
// Package gen
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version
package gen
+1 -1
View File
@@ -1,7 +1,7 @@
// Package gen
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version
package gen
@@ -1,7 +1,7 @@
// Package gen
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version
package system
@@ -9,6 +9,7 @@ import (
"git.5iot.com/iotlcm-public/iotlcm-app/internal/service"
)
func (c *ControllerV1) SysDictTypeList(ctx context.Context, req *v1.SysDictTypeListReq) (res *v1.SysDictTypeListRes, err error) {
items, total, err := service.SysDictType().List(ctx, &req.SysDictTypeListParam)
if err != nil {
+7 -3
View File
@@ -26,19 +26,19 @@ type BatchMainColumns struct {
OrderSn string // 订单编号
BatchType string // 批次类型 枚举
BatchStatus string // 批次状态 枚举
BatchAsyncStatus string // 异步处理状态 0=已创建 1=待处理 2=处理中 3=成功 4=失败 5=部分成功
BatchAsyncStatus string // 异步处理状态
SourceType string // 来源方式 枚举
SourceBatchNo string // 来源批次编号
SourceOssId string // 源文件OSS ID
ResultOssId string // 结果文件OSS ID
IsCrossDept string // 是否跨级操作机构 0-否 1-是
IsCrossDept string // 是否跨级操作机构
TargetDeptId string // 目标机构编号
DeptId string // 机构编号
TotalCount string // 总数量
ValidCount string // 有效数量
SuccessCount string // 成功数量
FailCount string // 失败数量
RunResult string // 运行结果:0-待运行 1-运行中 2-成功 3-失败
RunResult string // 运行结果
FailReason string // 失败原因
BatchInfo string // 批次信息:入库/出库展示字段
Remark string // 备注扩展字段
@@ -50,6 +50,8 @@ type BatchMainColumns struct {
CreatedAt string // 创建时间
UpdatedBy string // 更新者ID
UpdatedAt string // 更新时间
SourceChannel string // 发起渠道:console/mini_program/api/system/legacy
ExecutionMode string // 操作规模:0未知1单卡2批量
}
// batchMainColumns holds the columns for the table batch_main.
@@ -83,6 +85,8 @@ var batchMainColumns = BatchMainColumns{
CreatedAt: "created_at",
UpdatedBy: "updated_by",
UpdatedAt: "updated_at",
SourceChannel: "source_channel",
ExecutionMode: "execution_mode",
}
// NewBatchMainDao creates and returns a new DAO object for table data access.
+1 -1
View File
@@ -1,7 +1,7 @@
// Package addons
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package addons
@@ -0,0 +1,35 @@
package allocaterequest
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"regexp"
"sort"
"strings"
"github.com/gogf/gf/v2/errors/gerror"
)
var validID = regexp.MustCompile(`^[A-Za-z0-9_-]{16,96}$`)
func Key(tenant string, user int64, requestID string) (string, error) {
requestID = strings.TrimSpace(requestID)
if tenant == "" || user <= 0 || !validID.MatchString(requestID) {
return "", gerror.New("划拨请求标识无效")
}
value, err := json.Marshal([]any{tenant, user, "allocate", requestID})
if err != nil {
return "", gerror.Wrap(err, "生成划拨请求标识失败")
}
digest := sha256.Sum256(value)
return hex.EncodeToString(digest[:]), nil
}
func Fingerprint(cards []string, source, target int64, mode int, remark string) string {
sorted := append([]string(nil), cards...)
sort.Strings(sorted)
value, _ := json.Marshal([]any{sorted, source, target, mode, strings.TrimSpace(remark)})
digest := sha256.Sum256(value)
return hex.EncodeToString(digest[:])
}
@@ -0,0 +1,41 @@
package allocaterequest
import "testing"
func TestRequestIdentity(t *testing.T) {
requestID := "alloc_0123456789abcdef"
first, err := Key("A", 7, requestID)
if err != nil || len(first) != 64 {
t.Fatal(first, err)
}
same, _ := Key("A", 7, requestID)
if first != same {
t.Fatal("unstable identity")
}
for _, entry := range []struct {
tenant string
user int64
id string
}{{"B", 7, requestID}, {"A", 8, requestID}, {"A", 7, requestID + "2"}} {
other, err := Key(entry.tenant, entry.user, entry.id)
if err != nil || other == first {
t.Fatal("identity scope collision", err)
}
}
for _, id := range []string{"", "short", "0123456789abcdef/"} {
if _, err := Key("A", 7, id); err == nil {
t.Fatal("invalid identity accepted", id)
}
}
}
func TestFingerprint(t *testing.T) {
first := Fingerprint([]string{"B", "A"}, 1, 2, 2, " remark ")
if first != Fingerprint([]string{"A", "B"}, 1, 2, 2, "remark") {
t.Fatal("card order changed identity")
}
for _, other := range []string{Fingerprint([]string{"A"}, 1, 2, 2, "remark"), Fingerprint([]string{"A", "B"}, 2, 2, 2, "remark"), Fingerprint([]string{"A", "B"}, 1, 3, 2, "remark"), Fingerprint([]string{"A", "B"}, 1, 2, 1, "remark"), Fingerprint([]string{"A", "B"}, 1, 2, 2, "other")} {
if first == other {
t.Fatal("changed parameters accepted")
}
}
}
@@ -0,0 +1,25 @@
package allocaterequest
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/dao"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model/entity"
)
func Find(ctx context.Context, tenant string, user int64, requestID string) (*entity.BatchMain, error) {
key, err := Key(tenant, user, requestID)
if err != nil {
return nil, err
}
var batch *entity.BatchMain
columns := dao.BatchMain.Columns()
scope := dao.BatchMain.Ctx(ctx).Where(columns.TenantId, tenant).Where(columns.CreatedBy, user)
if err = scope.Clone().Where(columns.BatchNo, "ALC"+key[:60]).Scan(&batch); err != nil {
return nil, gerror.Wrap(err, "查询历史划拨请求失败")
}
if batch != nil {
return batch, nil
}
return nil, nil
}
@@ -0,0 +1,141 @@
package allocationunits
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gerror"
"strings"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/dao"
)
// Fields 是日志展示契约,不增加数据库字段。
type Fields struct {
SourceDeptId int64 `json:"sourceDeptId" orm:"-"`
SourceDeptName string `json:"sourceDeptName" orm:"-"`
TargetDeptId int64 `json:"targetDeptId" orm:"-"`
TargetDeptName string `json:"targetDeptName" orm:"-"`
TargetDeptMode string `json:"targetDeptMode" orm:"-"`
}
type Unit struct {
Id int64 `orm:"dept_id"`
Key string `orm:"dept_key"`
Name string `orm:"dept_name"`
}
func Load(ctx context.Context, tenant string, ids []int64, tx ...gdb.TX) (map[int64]Unit, error) {
unique := map[int64]bool{}
for _, id := range ids {
if id > 0 {
unique[id] = true
}
}
result := map[int64]Unit{}
if len(unique) == 0 {
return result, nil
}
ids = nil
for id := range unique {
ids = append(ids, id)
}
var rows []Unit
if len(tx) > 0 {
result, err := tx[0].GetAll("SELECT dept_id,dept_key,dept_name FROM sys_dept WHERE tenant_id=? AND deleted_at IS NULL AND dept_id IN (?)", tenant, ids)
if err != nil {
return nil, gerror.Wrap(err, "读取划拨单位信息失败")
}
if err := result.Structs(&rows); err != nil {
return nil, err
}
units := map[int64]Unit{}
for _, row := range rows {
units[row.Id] = row
}
return units, nil
}
mod := dao.SysDept.Ctx(ctx)
if err := mod.WhereNull("deleted_at").Where("tenant_id", tenant).WhereIn("dept_id", ids).Fields("dept_id", "dept_key", "dept_name", "deleted_at").Scan(&rows); err != nil {
return nil, gerror.Wrap(err, "读取划拨单位信息失败")
}
for _, row := range rows {
result[row.Id] = row
}
return result, nil
}
// Snapshot 名称由服务端查询,仅在受理时记录,执行时不覆盖。
func Snapshot(ctx context.Context, tenant string, source, target int64, tx ...gdb.TX) (*gjson.Json, error) {
units, err := Load(ctx, tenant, []int64{source, target}, tx...)
if err != nil {
return nil, err
}
mode := "single"
if target <= 0 {
mode = "per_row"
}
return gjson.New(map[string]any{"sourceDeptId": source, "sourceDeptKey": units[source].Key, "sourceDeptName": units[source].Name, "targetDeptId": target, "targetDeptKey": units[target].Key, "targetDeptName": units[target].Name, "targetDeptMode": mode}), nil
}
func Resolve(info *gjson.Json, source, target int64) Fields {
f := Fields{SourceDeptId: source, TargetDeptId: target}
if info != nil {
if id := info.Get("sourceDeptId").Int64(); id > 0 {
f.SourceDeptId = id
}
if id := info.Get("targetDeptId").Int64(); id > 0 {
f.TargetDeptId = id
}
f.SourceDeptName = strings.TrimSpace(info.Get("sourceDeptName").String())
f.TargetDeptName = strings.TrimSpace(info.Get("targetDeptName").String())
f.TargetDeptMode = info.Get("targetDeptMode").String()
}
if f.TargetDeptMode == "" {
if f.TargetDeptId > 0 {
f.TargetDeptMode = "single"
} else {
f.TargetDeptMode = "per_row"
}
}
return f
}
// Fill 一页只补查一次旧数据的单位名称,不扫描卡片当前归属,不覆盖历史快照。
func Fill(ctx context.Context, tenant string, fields []*Fields) error {
ids := []int64{}
for _, f := range fields {
if f.SourceDeptName == "" {
ids = append(ids, f.SourceDeptId)
}
if f.TargetDeptName == "" {
ids = append(ids, f.TargetDeptId)
}
}
units, err := Load(ctx, tenant, ids)
if err != nil {
return err
}
for _, f := range fields {
if f.SourceDeptName == "" {
f.SourceDeptName = units[f.SourceDeptId].Name
}
if f.TargetDeptName == "" {
f.TargetDeptName = units[f.TargetDeptId].Name
}
}
return nil
}
func Merge(info, units *gjson.Json) *gjson.Json {
data := map[string]any{}
if info != nil {
for k, v := range info.Map() {
data[k] = v
}
}
if units != nil {
for k, v := range units.Map() {
data[k] = v
}
}
return gjson.New(data)
}
@@ -0,0 +1,55 @@
package allocationunits
import (
"context"
"encoding/json"
_ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"strings"
"testing"
)
func TestSnapshotAndLegacyFallback(t *testing.T) {
ctx := context.Background()
if err := gdb.SetConfig(gdb.Config{"default": gdb.ConfigGroup{{Type: "sqlite", Link: "sqlite::@file(:memory:)", MaxOpenConnCount: 1}}}); err != nil {
t.Fatal(err)
}
t.Cleanup(func() { _ = g.DB().Close(ctx) })
for _, sql := range []string{"CREATE TABLE sys_dept(dept_id INTEGER,tenant_id TEXT,dept_key TEXT,dept_name TEXT,deleted_at TEXT)", "INSERT INTO sys_dept VALUES(1,'A','a','划拨单位',NULL),(2,'A','b','接收单位',NULL),(3,'B','other','其他租户',NULL),(4,'A','gone','已删除单位','2026-01-01')"} {
if _, err := g.DB().Exec(ctx, sql); err != nil {
t.Fatal(err)
}
}
snapshot, err := Snapshot(ctx, "A", 1, 2)
if err != nil {
t.Fatal(err)
}
if _, err := g.DB().Exec(ctx, "UPDATE sys_dept SET dept_name='新名称' WHERE dept_id=2"); err != nil {
t.Fatal(err)
}
frozen := Resolve(snapshot, 0, 0)
legacy := Resolve(nil, 1, 2)
foreign := Resolve(nil, 3, 4)
if err := Fill(ctx, "A", []*Fields{&frozen, &legacy, &foreign}); err != nil {
t.Fatal(err)
}
if frozen.TargetDeptName != "接收单位" || legacy.TargetDeptName != "新名称" || foreign.SourceDeptName != "" || foreign.TargetDeptName != "" {
t.Fatalf("快照/回退/隔离错误: %+v %+v %+v", frozen, legacy, foreign)
}
if f := Resolve(gjson.New(map[string]any{"sourceDeptName": "历史名称"}), 1, 0); f.TargetDeptMode != "per_row" {
t.Fatal(f)
}
encoded, err := json.Marshal(frozen)
if err != nil {
t.Fatal(err)
}
if !strings.Contains(string(encoded), "sourceDeptName") {
t.Fatal("JSON契约缺少单位字段")
}
merged := Merge(gjson.New(map[string]any{"jobRole": "allocate_parent"}), snapshot)
if merged.Get("jobRole").String() != "allocate_parent" || merged.Get("sourceDeptName").String() != "划拨单位" {
t.Fatal(merged)
}
}
@@ -3,6 +3,7 @@ package batchimport
import (
"context"
"strings"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/batchmetadata"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/consts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/dao"
@@ -21,6 +22,9 @@ type PendingOptions struct {
}
func CreatePendingUpload(ctx context.Context, req SubmitRequest, p Processor, options PendingOptions) (*Result, error) {
if err := batchmetadata.ValidateCreation(req.SourceChannel, req.ExecutionMode); err != nil {
return nil, err
}
cfg := p.Config()
if req.File == nil {
return nil, gerror.New("请选择上传文件")
@@ -59,6 +63,9 @@ func CreatePendingUpload(ctx context.Context, req SubmitRequest, p Processor, op
}
func CreatePendingRows(ctx context.Context, req SubmitRequest, p Processor, rows []Row, options PendingOptions) (*Result, error) {
if err := batchmetadata.ValidateCreation(req.SourceChannel, req.ExecutionMode); err != nil {
return nil, err
}
batchNo, err := NextBatchNoContext(ctx, p.Config().BatchNoPrefix)
if err != nil {
return nil, err
@@ -103,6 +110,8 @@ func createPending(ctx context.Context, req *SubmitRequest, p Processor, rows []
BatchStatus: consts.BatchAsyncStatusPending,
BatchAsyncStatus: consts.BatchAsyncStatusPending,
SourceType: req.SourceType,
SourceChannel: batchmetadata.Channel(req.SourceChannel),
ExecutionMode: batchmetadata.NormalizeMode(req.ExecutionMode),
SourceBatchNo: sourceBatchNo,
IsCrossDept: 0,
TargetDeptId: req.TargetDeptId,
+12 -3
View File
@@ -3,17 +3,18 @@ package batchimport
import (
"context"
"fmt"
"io"
"os"
"strings"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/consts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/dao"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/batchmetadata"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model/do"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model/entity"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/service"
"git.5iot.com/iotlcm-public/iotlcm-app/utility/hash"
"git.5iot.com/iotlcm-public/iotlcm-app/utility/iot_excelize"
"io"
"os"
"strings"
"github.com/gogf/gf/v2/crypto/gmd5"
"github.com/gogf/gf/v2/database/gdb"
@@ -25,6 +26,9 @@ import (
)
func SubmitAndRun(ctx context.Context, req SubmitRequest, p Processor) (*Result, error) {
if err := batchmetadata.ValidateCreation(req.SourceChannel, req.ExecutionMode); err != nil {
return nil, err
}
cfg := p.Config()
if req.File == nil {
return nil, gerror.New("请选择上传文件")
@@ -107,6 +111,9 @@ func SubmitAndRun(ctx context.Context, req SubmitRequest, p Processor) (*Result,
}
func RunRows(ctx context.Context, req SubmitRequest, p Processor, rows []Row, sourceName string) (*Result, error) {
if err := batchmetadata.ValidateCreation(req.SourceChannel, req.ExecutionMode); err != nil {
return nil, err
}
cfg := p.Config()
batchNo, err := NextBatchNoContext(ctx, cfg.BatchNoPrefix)
if err != nil {
@@ -268,6 +275,8 @@ func saveBatchAndExecute(ctx context.Context, req *SubmitRequest, p Processor, r
BatchStatus: batchStatusByImportStatus(result.ImportStatus),
BatchAsyncStatus: batchStatusByImportStatus(result.ImportStatus),
SourceType: req.SourceType,
SourceChannel: batchmetadata.Channel(req.SourceChannel),
ExecutionMode: batchmetadata.NormalizeMode(req.ExecutionMode),
SourceBatchNo: sourceBatchNo,
IsCrossDept: 0,
TargetDeptId: req.TargetDeptId,
@@ -10,6 +10,9 @@ import (
)
type SubmitRequest struct {
SourceChannel string
// ExecutionMode is the semantic size of the operation. Zero means the caller did not specify it.
ExecutionMode int
File *ghttp.UploadFile
BizParams any
SourceType int
@@ -0,0 +1,52 @@
package batchmetadata
import "github.com/gogf/gf/v2/errors/gerror"
const (
Console = "console"
MiniProgram = "mini_program"
API = "api"
System = "system"
Legacy = "legacy"
Unknown = 0
Single = 1
Bulk = 2
)
// NormalizeMode validates the explicit execution size supplied by the business entry point.
// Execution size is request metadata and must not be inferred from context or result counts.
func NormalizeMode(requested int) int {
if requested == Single || requested == Bulk {
return requested
}
return Unknown
}
func ValidChannel(value string) bool {
switch value {
case Console, MiniProgram, API, System, Legacy:
return true
}
return false
}
func Channel(value string) string {
if ValidChannel(value) {
return value
}
return Legacy
}
func ValidMode(value int) bool { return value >= Unknown && value <= Bulk }
// ValidateCreation rejects missing attribution for new work; historical reads
// and resumed work continue to use Channel/NormalizeMode for compatibility.
func ValidateCreation(channel string, mode int) error {
if !ValidChannel(channel) || channel == Legacy {
return gerror.New("新建批次发起渠道无效")
}
if mode != Single && mode != Bulk {
return gerror.New("新建批次必须指定单卡或批量操作规模")
}
return nil
}
@@ -0,0 +1,52 @@
package batchmetadata
import "testing"
func TestValidateCreation(t *testing.T) {
for _, channel := range []string{Console, MiniProgram, API, System} {
for _, mode := range []int{Single, Bulk} {
if err := ValidateCreation(channel, mode); err != nil {
t.Fatal(channel, mode, err)
}
}
}
for _, channel := range []string{"", Legacy} {
if err := ValidateCreation(channel, Single); err == nil {
t.Fatal("missing new batch attribution accepted", channel)
}
}
if ValidateCreation("worker", Single) == nil {
t.Fatal("invalid source accepted")
}
for _, mode := range []int{-1, Unknown, 3} {
if ValidateCreation(Console, mode) == nil {
t.Fatal("invalid new execution size accepted", mode)
}
}
}
func TestMetadata(t *testing.T) {
if NormalizeMode(0) != Unknown {
t.Fatal("unspecified entry mode must remain unknown")
}
if NormalizeMode(Single) != Single {
t.Fatal("single entry mode lost")
}
if NormalizeMode(Bulk) != Bulk {
t.Fatal("bulk entry mode lost")
}
if NormalizeMode(99) != Unknown {
t.Fatal("invalid entry mode accepted")
}
for _, c := range []string{Console, MiniProgram, API, System, Legacy} {
if Channel(c) != c {
t.Fatal(c)
}
}
if Channel("worker") != Legacy || Channel("") != Legacy {
t.Fatal("unknown source was attributed")
}
if ValidMode(-1) || ValidMode(3) {
t.Fatal("invalid mode accepted")
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
// Package bcache
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package bcache
@@ -1,16 +1,16 @@
// Package bcache
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package bcache
import (
"context"
"fmt"
"time"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/consts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/cache"
"time"
"github.com/gogf/gf/v2/frame/g"
)
+1 -1
View File
@@ -1,7 +1,7 @@
// Package cache
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package cache
+1 -1
View File
@@ -1,7 +1,7 @@
// Package file
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package file
+2 -2
View File
@@ -1,15 +1,15 @@
// Package contexts
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package contexts
import (
"context"
"slices"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/consts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model"
"slices"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
+1 -1
View File
@@ -1,7 +1,7 @@
// Package event
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package event
+1 -1
View File
@@ -1,7 +1,7 @@
// Package mcache
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// 内存缓存管理
package mcache
@@ -1,17 +1,17 @@
// Package mcache
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package mcache
import (
"context"
"fmt"
"time"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/consts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/event"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/service"
"time"
"github.com/gogf/gf/v2/frame/g"
)
@@ -28,7 +28,29 @@ func init() {
}
type requestAccessKey struct{}
type requestAccessSnapshot struct {
userId int64
codes []string
scopes []string
}
// WithFreshUserAccess 为小程序请求读取当前权限并保留请求内快照。
// 控制台清理本地缓存不会清理小程序进程内的权限缓存。
func WithFreshUserAccess(ctx context.Context, userId int64) (context.Context, error) {
codes, scopes, err := service.SysAuth().GetUserAccessCodeList(ctx, userId)
if err != nil {
return ctx, err
}
snapshot := requestAccessSnapshot{userId: userId, codes: ensureCurrentUserAccessCode(codes), scopes: scopes}
return context.WithValue(ctx, requestAccessKey{}, snapshot), nil
}
func GetUserAccessCodeList(ctx context.Context, userId int64) ([]string, []string, error) {
if snapshot, ok := ctx.Value(requestAccessKey{}).(requestAccessSnapshot); ok && snapshot.userId == userId {
return snapshot.codes, snapshot.scopes, nil
}
accessCodeList, err := Instance().Get(ctx, fmt.Sprintf(consts.MemCacheUserAccessCodeList, userId))
menuRoleDataAccessCodeList, err := Instance().Get(ctx, fmt.Sprintf(consts.MemCacheUserRoleDataAccessCodeList, userId))
if err != nil || accessCodeList == nil {
@@ -0,0 +1,19 @@
package mcache
import (
"context"
"reflect"
"testing"
)
func TestRequestAccessSnapshotOverridesProcessCache(t *testing.T) {
for _, codes := range [][]string{{"cpm:iot:tSimCardAllocate:batch:submit"}, {}} {
ctx := context.WithValue(context.Background(), requestAccessKey{}, requestAccessSnapshot{
userId: 123, codes: ensureCurrentUserAccessCode(codes), scopes: []string{"scope-current"},
})
got, scopes, err := GetUserAccessCodeList(ctx, 123)
if err != nil || !reflect.DeepEqual(got, ensureCurrentUserAccessCode(codes)) || !reflect.DeepEqual(scopes, []string{"scope-current"}) {
t.Fatalf("request snapshot was not respected: codes=%v scopes=%v err=%v", got, scopes, err)
}
}
}
@@ -1,20 +1,20 @@
// Package mcache
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package mcache
import (
"context"
"fmt"
"time"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/consts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/contexts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/event"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model/request"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/service"
"time"
)
func init() {
@@ -1,17 +1,17 @@
// Package mcache
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package mcache
import (
"context"
"fmt"
"time"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/consts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/event"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/service"
"time"
)
func init() {
@@ -1,18 +1,18 @@
// Package mcache
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package mcache
import (
"context"
"fmt"
"time"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/consts"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/event"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/service"
"time"
"github.com/gogf/gf/v2/util/gconv"
)
@@ -3,6 +3,7 @@ package rabbitmq
import (
"context"
"encoding/json"
"fmt"
"sync"
"time"
@@ -41,6 +42,25 @@ func Publish(ctx context.Context, queue string, data any) error {
return PublishBytes(ctx, queue, body)
}
func PublishDelayed(ctx context.Context, delayQueue, targetQueue string, delay time.Duration, data any) error {
body, err := json.Marshal(data)
if err != nil {
return gerror.Wrap(err, "序列化延时工单消息失败")
}
ch, err := channel(ctx)
if err != nil {
return err
}
defer ch.Close()
if _, err = ch.QueueDeclare(targetQueue, true, false, false, false, nil); err != nil {
return gerror.Wrap(err, "声明工单目标队列失败")
}
if _, err = ch.QueueDeclare(delayQueue, true, false, false, false, amqp.Table{"x-dead-letter-exchange": "", "x-dead-letter-routing-key": targetQueue}); err != nil {
return gerror.Wrap(err, "声明工单延时队列失败")
}
return gerror.Wrap(ch.PublishWithContext(ctx, "", delayQueue, false, false, amqp.Publishing{ContentType: "application/json", DeliveryMode: amqp.Persistent, Expiration: fmt.Sprintf("%d", delay.Milliseconds()), Timestamp: time.Now(), Body: body}), "发送工单延时消息失败")
}
func PublishBytes(ctx context.Context, queue string, body []byte) error {
if queue == "" {
return gerror.New("RabbitMQ 队列名不能为空")
+1 -1
View File
@@ -1,7 +1,7 @@
// Package websocket
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package websocket
@@ -1,7 +1,7 @@
// Package websocket
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package websocket
@@ -1,7 +1,7 @@
// Package websocket
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package websocket
+2 -2
View File
@@ -1,14 +1,14 @@
// Package websocket
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package websocket
import (
"context"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/contexts"
"net/http"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/library/contexts"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
+1 -1
View File
@@ -1,7 +1,7 @@
// Package websocket
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package websocket
+1 -1
View File
@@ -1,7 +1,7 @@
// Package websocket
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package websocket
+1 -1
View File
@@ -1,7 +1,7 @@
// Package worker
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package worker
@@ -1,7 +1,7 @@
// package worker
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package worker
+1 -1
View File
@@ -1,7 +1,7 @@
// package worker
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package worker
@@ -1,7 +1,7 @@
// package genconsts
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package genconsts
@@ -1,7 +1,7 @@
// package genconsts
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package genconsts
@@ -1,7 +1,7 @@
// package gendao
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <li@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package gendao

Some files were not shown because too many files have changed in this diff Show More