sync: 对齐小程序 v1.0.2 生产代码并脱敏
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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 }
|
||||
@@ -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,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 @@
|
||||
// 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
|
||||
|
||||
@@ -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,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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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 @@
|
||||
// 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,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 @@
|
||||
// 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
|
||||
@@ -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
@@ -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,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,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
|
||||
|
||||
|
||||
@@ -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,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,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,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"
|
||||
|
||||
@@ -27,6 +27,7 @@ const (
|
||||
BatchDetailStatusFailed = 3
|
||||
|
||||
BatchSourceTypeBatchSelect = 0
|
||||
BatchSourceTypeFile = 3
|
||||
|
||||
BatchTypePrepare = 4
|
||||
BatchTypeAllocate = 3
|
||||
|
||||
@@ -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,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,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,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,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,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,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,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,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,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,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,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 {
|
||||
|
||||
@@ -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,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,
|
||||
|
||||
@@ -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,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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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,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,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,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
|
||||
|
||||
|
||||
@@ -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,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 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,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
Reference in New Issue
Block a user