sync: 对齐小程序 v1.0.2 生产代码并脱敏
This commit is contained in:
@@ -2,10 +2,13 @@ package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"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/appidentity"
|
||||
"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"
|
||||
@@ -14,6 +17,7 @@ import (
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
@@ -42,9 +46,38 @@ func init() {
|
||||
|
||||
func (s *sAppWorkOrder) Upload(ctx context.Context) (output *model.SysOssUploadModel, err error) {
|
||||
if err = appEnsureFeatureAccess(ctx, "workorder:create"); err != nil {
|
||||
if err = appEnsureFeatureAccess(ctx, "workorder:detail"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
request := g.RequestFromCtx(ctx)
|
||||
if request == nil {
|
||||
return nil, gerror.New("上传请求无效")
|
||||
}
|
||||
file := request.GetUploadFile("file")
|
||||
if file == nil {
|
||||
return nil, gerror.New("请选择附件")
|
||||
}
|
||||
if file.Size > 10*1024*1024 {
|
||||
return nil, gerror.New("单个附件不能超过10MB")
|
||||
}
|
||||
originalName, err := appWorkOrderOriginalName(request.GetForm("originalName").String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return service.SysOss().Upload(ctx, &model.SysOssUploadParam{FileType: "file"})
|
||||
output, err = service.SysOss().Upload(ctx, &model.SysOssUploadParam{FileType: "file"})
|
||||
if err != nil || originalName == "" {
|
||||
return output, err
|
||||
}
|
||||
columns := dao.SysOss.Columns()
|
||||
if _, err = dao.SysOss.Ctx(ctx).
|
||||
Where(columns.OssId, output.OssId).
|
||||
Where(columns.TenantId, output.TenantId).
|
||||
Data(do.SysOss{OriginalName: originalName}).Update(); err != nil {
|
||||
return nil, gerror.Wrap(err, "保存工单附件原名失败")
|
||||
}
|
||||
output.OriginalName = originalName
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func (s *sAppWorkOrder) List(ctx context.Context, param *model.AppWorkOrderListParam) (items []*model.AppWorkOrderModel, total int, err error) {
|
||||
@@ -70,11 +103,30 @@ func (s *sAppWorkOrder) List(ctx context.Context, param *model.AppWorkOrderListP
|
||||
}
|
||||
|
||||
mod := s.ownerModel(ctx, user)
|
||||
if param.Scope != "" && param.Scope != "all" && param.Scope != "submitted" && param.Scope != "received" {
|
||||
return nil, 0, gerror.New("工单范围不正确")
|
||||
}
|
||||
if param.Scope == "submitted" {
|
||||
mod = mod.Where(dao.TWoMain.Columns().CreatorUserId, user.UserId)
|
||||
}
|
||||
if param.Scope == "received" {
|
||||
if appIsTerminalUser(ctx, user) {
|
||||
return nil, 0, gerror.New("终端账号不能查看待处理工单")
|
||||
}
|
||||
columns := dao.TWoMain.Columns()
|
||||
mod = mod.WhereNot(columns.CreatorUserId, user.UserId).Where("("+columns.HandlerUserId+" = ? OR ("+columns.HandlerDeptId+" = ? AND ? > 0))", user.UserId, user.DeptId, user.DeptId)
|
||||
}
|
||||
if param.CurrentStatus < 0 || param.CurrentStatus > 5 {
|
||||
return nil, 0, gerror.New("工单状态不正确")
|
||||
}
|
||||
if param.CurrentStatus > 0 {
|
||||
mod = mod.Where(dao.TWoMain.Columns().CurrentStatus, param.CurrentStatus)
|
||||
}
|
||||
if param.WoType > 0 {
|
||||
mod = mod.Where(dao.TWoMain.Columns().WoType, param.WoType)
|
||||
if param.WoType != nil {
|
||||
if *param.WoType < 0 || *param.WoType > 5 {
|
||||
return nil, 0, gerror.New("工单类型不正确")
|
||||
}
|
||||
mod = mod.Where(dao.TWoMain.Columns().WoType, *param.WoType)
|
||||
}
|
||||
|
||||
keyword := strings.TrimSpace(param.Keyword)
|
||||
@@ -142,17 +194,59 @@ func (s *sAppWorkOrder) Detail(ctx context.Context, param *model.AppWorkOrderDet
|
||||
|
||||
res = appWorkOrderToModel(row)
|
||||
var communications []*entity.TWoCommunication
|
||||
if err = dao.TWoCommunication.Ctx(ctx).
|
||||
communicationModel := dao.TWoCommunication.Ctx(ctx).
|
||||
Where(dao.TWoCommunication.Columns().TenantId, user.TenantId).
|
||||
Where(dao.TWoCommunication.Columns().WoNo, row.WoNo).
|
||||
OrderAsc(dao.TWoCommunication.Columns().Id).
|
||||
Where(dao.TWoCommunication.Columns().WoNo, row.WoNo)
|
||||
if param.BeforeId > 0 {
|
||||
communicationModel = communicationModel.WhereLT(dao.TWoCommunication.Columns().Id, param.BeforeId)
|
||||
}
|
||||
if err = communicationModel.OrderDesc(dao.TWoCommunication.Columns().Id).Limit(21).
|
||||
Scan(&communications); err != nil {
|
||||
return nil, gerror.Wrap(err, "查询工单沟通记录失败")
|
||||
}
|
||||
res.HasMoreCommunications = len(communications) > 20
|
||||
if res.HasMoreCommunications {
|
||||
communications = communications[:20]
|
||||
}
|
||||
for left, right := 0, len(communications)-1; left < right; left, right = left+1, right-1 {
|
||||
communications[left], communications[right] = communications[right], communications[left]
|
||||
}
|
||||
res.Communications = appWorkOrderCommunicationsToModels(communications)
|
||||
urls := append([]string{}, res.AttachmentUrls...)
|
||||
for _, communication := range communications {
|
||||
if communication != nil && communication.AttachmentUrls != nil {
|
||||
urls = append(urls, communication.AttachmentUrls.Var().Strings()...)
|
||||
}
|
||||
}
|
||||
res.AttachmentNames, err = appWorkOrderAttachmentNames(ctx, user.TenantId, urls)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res.Actions = appAvailableWorkOrderActions(ctx, row, user)
|
||||
res.IsCreator = row.CreatorUserId == user.UserId
|
||||
var records []*entity.TWoRecord
|
||||
if err = dao.TWoRecord.Ctx(ctx).Where(dao.TWoRecord.Columns().TenantId, user.TenantId).Where(dao.TWoRecord.Columns().WoNo, row.WoNo).OrderAsc(dao.TWoRecord.Columns().Id).Scan(&records); err != nil {
|
||||
return nil, gerror.Wrap(err, "查询工单进度失败")
|
||||
}
|
||||
for _, record := range records {
|
||||
res.Records = append(res.Records, &model.AppWorkOrderProgressModel{Id: record.Id, OperationType: record.OperationType, OperationText: appWorkOrderOperationText(record), BeforeStatus: record.BeforeStatus, AfterStatus: record.AfterStatus, CreatedAt: record.CreatedAt})
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
var appWorkOrderPhonePattern = regexp.MustCompile(`^1[3-9]\d{9}$`)
|
||||
|
||||
func appWorkOrderContactPhone(phone string) (string, error) {
|
||||
value := strings.TrimSpace(phone)
|
||||
if value == "" {
|
||||
return "", gerror.New("请输入创建人手机号")
|
||||
}
|
||||
if !appWorkOrderPhonePattern.MatchString(value) {
|
||||
return "", gerror.New("请输入正确的手机号")
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (s *sAppWorkOrder) Create(ctx context.Context, param *model.AppWorkOrderCreateParam) (res *model.AppWorkOrderModel, err error) {
|
||||
if err = appEnsureFeatureAccess(ctx, "workorder:create"); err != nil {
|
||||
return nil, err
|
||||
@@ -178,6 +272,22 @@ func (s *sAppWorkOrder) Create(ctx context.Context, param *model.AppWorkOrderCre
|
||||
return nil, err
|
||||
}
|
||||
|
||||
creatorPhone, err := appWorkOrderContactPhone(param.CreatorPhone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if utf8.RuneCountInString(title) > 100 || utf8.RuneCountInString(content) > 2000 {
|
||||
return nil, gerror.New("标题最多100字,问题描述最多2000字")
|
||||
}
|
||||
if err = s.validateRelatedWorkOrder(ctx, user, param); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = appValidateWorkOrderAttachments(param.AttachmentUrls); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = s.validateAttachmentOwnership(ctx, user, param.AttachmentUrls); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
now := gtime.Now()
|
||||
woNo := appCardBatchNo("WO", user.UserId, now)
|
||||
createdDept := user.DeptId
|
||||
@@ -194,6 +304,7 @@ func (s *sAppWorkOrder) Create(ctx context.Context, param *model.AppWorkOrderCre
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var created *entity.TWoMain
|
||||
err = dao.TWoMain.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
||||
_, err := dao.TWoMain.Ctx(ctx).TX(tx).Data(do.TWoMain{
|
||||
WoNo: woNo,
|
||||
@@ -201,12 +312,12 @@ func (s *sAppWorkOrder) Create(ctx context.Context, param *model.AppWorkOrderCre
|
||||
RelatedId: param.RelatedId,
|
||||
Title: title,
|
||||
Content: content,
|
||||
Attachment: firstAttachment(param.AttachmentUrls),
|
||||
Attachment: appWorkOrderEncodeAttachments(param.AttachmentUrls),
|
||||
CreatorType: creatorType,
|
||||
CreatorDeptId: createdDept,
|
||||
CreatorUserId: user.UserId,
|
||||
CreatorName: creatorName,
|
||||
CreatorPhone: strings.TrimSpace(user.Phonenumber),
|
||||
CreatorPhone: creatorPhone,
|
||||
AssignDeptId: handlerDeptId,
|
||||
AssignUserId: handlerUserId,
|
||||
CurrentStatus: appWorkOrderStatusProcessing,
|
||||
@@ -260,73 +371,110 @@ func (s *sAppWorkOrder) Create(ctx context.Context, param *model.AppWorkOrderCre
|
||||
}).Insert(); err != nil {
|
||||
return gerror.Wrap(err, "创建工单操作记录失败")
|
||||
}
|
||||
if err := dao.TWoMain.Ctx(ctx).TX(tx).
|
||||
Where(dao.TWoMain.Columns().TenantId, user.TenantId).
|
||||
Where(dao.TWoMain.Columns().CreatorUserId, user.UserId).
|
||||
Where(dao.TWoMain.Columns().WoNo, woNo).
|
||||
Scan(&created); err != nil {
|
||||
return gerror.Wrap(err, "读取新建工单失败")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.Detail(ctx, &model.AppWorkOrderDetailParam{WoNo: woNo})
|
||||
return appWorkOrderToModel(created), nil
|
||||
}
|
||||
|
||||
func (s *sAppWorkOrder) ownerModel(ctx context.Context, user *entity.SysUser) *gdb.Model {
|
||||
columns := dao.TWoMain.Columns()
|
||||
mod := dao.TWoMain.Ctx(ctx).
|
||||
Where(columns.TenantId, user.TenantId)
|
||||
if appIsTerminalUser(ctx, user) {
|
||||
terminal, identityErr := appidentity.IsTerminalUser(ctx, user)
|
||||
if identityErr != nil {
|
||||
g.Log().Errorf(ctx, "工单用户身份查询失败: %v", identityErr)
|
||||
return mod.Where("1 = 0")
|
||||
}
|
||||
if terminal {
|
||||
return mod.Where(columns.CreatorUserId, user.UserId)
|
||||
}
|
||||
return appApplyEnterpriseDataScope(
|
||||
ctx,
|
||||
user,
|
||||
mod,
|
||||
columns.CreatorDeptId,
|
||||
columns.CreatorUserId,
|
||||
func(legacyMod *gdb.Model) *gdb.Model {
|
||||
return legacyMod.Where(
|
||||
"("+columns.CreatorDeptId+" = ? OR "+columns.CreatorUserId+" = ?)",
|
||||
user.DeptId,
|
||||
user.UserId,
|
||||
)
|
||||
},
|
||||
)
|
||||
scope, err := appResolveEnterpriseDataScope(ctx, user)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "work order data scope: %v", err)
|
||||
return mod.Where("1 = 0")
|
||||
}
|
||||
if scope.All {
|
||||
return mod
|
||||
}
|
||||
condition := ""
|
||||
args := []any{}
|
||||
if !scope.Configured {
|
||||
condition = columns.CreatorDeptId + " = ? OR " + columns.CreatorUserId + " = ?"
|
||||
args = append(args, user.DeptId, user.UserId)
|
||||
} else {
|
||||
if len(scope.DeptIds) > 0 {
|
||||
condition = columns.CreatorDeptId + " IN (?)"
|
||||
args = append(args, scope.DeptIds)
|
||||
}
|
||||
if len(scope.UserIds) > 0 {
|
||||
if condition != "" {
|
||||
condition += " OR "
|
||||
}
|
||||
condition += columns.CreatorUserId + " IN (?)"
|
||||
args = append(args, scope.UserIds)
|
||||
}
|
||||
}
|
||||
if condition != "" {
|
||||
condition += " OR "
|
||||
}
|
||||
condition += columns.HandlerUserId + " = ?"
|
||||
args = append(args, user.UserId)
|
||||
if user.DeptId > 0 {
|
||||
condition += " OR " + columns.HandlerDeptId + " = ?"
|
||||
args = append(args, user.DeptId)
|
||||
}
|
||||
return mod.Where("("+condition+")", args...)
|
||||
}
|
||||
|
||||
func appWorkOrderHandler(ctx context.Context, user *entity.SysUser, createdDept int64) (deptId int64, userId int64, err error) {
|
||||
if user == nil {
|
||||
return createdDept, 0, nil
|
||||
if user == nil || strings.TrimSpace(user.TenantId) == "" || createdDept <= 0 {
|
||||
return 0, 0, gerror.New("当前账号未配置有效的工单所属部门")
|
||||
}
|
||||
|
||||
var topDept *entity.SysDept
|
||||
columns := dao.SysDept.Columns()
|
||||
var currentDept *entity.SysDept
|
||||
if err = dao.SysDept.Ctx(ctx).
|
||||
Where(dao.SysDept.Columns().TenantId, user.TenantId).
|
||||
Where(dao.SysDept.Columns().ParentId, 0).
|
||||
OrderAsc(dao.SysDept.Columns().OrderNum).
|
||||
OrderAsc(dao.SysDept.Columns().DeptId).
|
||||
Fields(columns.DeptId, columns.ParentId, columns.Leader, columns.Status).
|
||||
Where(columns.TenantId, user.TenantId).
|
||||
Where(columns.DeptId, createdDept).
|
||||
WhereNull(columns.DeletedAt).
|
||||
Limit(1).
|
||||
Scan(&topDept); err != nil {
|
||||
return 0, 0, gerror.Wrap(err, "查询顶级工单处理部门失败")
|
||||
Scan(¤tDept); err != nil {
|
||||
return 0, 0, gerror.Wrap(err, "查询工单所属部门失败")
|
||||
}
|
||||
if topDept != nil && topDept.DeptId > 0 {
|
||||
return topDept.DeptId, topDept.Leader, nil
|
||||
if currentDept == nil || currentDept.DeptId <= 0 || currentDept.Status != "0" {
|
||||
return 0, 0, gerror.New("工单所属部门不存在或已停用")
|
||||
}
|
||||
|
||||
deptId = createdDept
|
||||
if deptId <= 0 {
|
||||
deptId = appUserDeptOrDefault(user)
|
||||
if currentDept.ParentId == 0 {
|
||||
return currentDept.DeptId, currentDept.Leader, nil
|
||||
}
|
||||
var dept *entity.SysDept
|
||||
if currentDept.ParentId == currentDept.DeptId {
|
||||
return 0, 0, gerror.New("工单所属部门的上级配置异常")
|
||||
}
|
||||
var parentDept *entity.SysDept
|
||||
if err = dao.SysDept.Ctx(ctx).
|
||||
Where(dao.SysDept.Columns().TenantId, user.TenantId).
|
||||
Where(dao.SysDept.Columns().DeptId, deptId).
|
||||
Fields(columns.DeptId, columns.Leader, columns.Status).
|
||||
Where(columns.TenantId, user.TenantId).
|
||||
Where(columns.DeptId, currentDept.ParentId).
|
||||
WhereNull(columns.DeletedAt).
|
||||
Limit(1).
|
||||
Scan(&dept); err != nil {
|
||||
return 0, 0, gerror.Wrap(err, "查询工单处理部门失败")
|
||||
Scan(&parentDept); err != nil {
|
||||
return 0, 0, gerror.Wrap(err, "查询上级工单处理部门失败")
|
||||
}
|
||||
if dept != nil && dept.Leader > 0 {
|
||||
userId = dept.Leader
|
||||
if parentDept == nil || parentDept.DeptId <= 0 || parentDept.Status != "0" {
|
||||
return 0, 0, gerror.New("上级工单处理部门不存在或已停用,请联系管理员")
|
||||
}
|
||||
return deptId, userId, nil
|
||||
return parentDept.DeptId, parentDept.Leader, nil
|
||||
}
|
||||
|
||||
func appWorkOrderToModel(row *entity.TWoMain) *model.AppWorkOrderModel {
|
||||
@@ -335,6 +483,12 @@ func appWorkOrderToModel(row *entity.TWoMain) *model.AppWorkOrderModel {
|
||||
}
|
||||
return &model.AppWorkOrderModel{
|
||||
Id: row.Id,
|
||||
Actions: []string{},
|
||||
ResolveTime: row.ResolveTime,
|
||||
CloseTime: row.CloseTime,
|
||||
SatisfactionLevel: row.SatisfactionLevel,
|
||||
EvalContent: row.EvalContent,
|
||||
EvalTime: row.EvalTime,
|
||||
WoNo: row.WoNo,
|
||||
WoType: row.WoType,
|
||||
WoTypeText: appWorkOrderTypeText(row.WoType),
|
||||
@@ -373,20 +527,13 @@ func appWorkOrderCommunicationsToModels(rows []*entity.TWoCommunication) []*mode
|
||||
return items
|
||||
}
|
||||
|
||||
func firstAttachment(urls []string) string {
|
||||
if len(urls) == 0 {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(urls[0])
|
||||
}
|
||||
|
||||
func decodeAttachmentUrls(value string) []string {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" {
|
||||
return nil
|
||||
}
|
||||
var urls []string
|
||||
if err := gjson.DecodeTo(value, &urls); err == nil && len(urls) > 0 {
|
||||
if err := gjson.DecodeTo(value, &urls); err == nil && (strings.HasPrefix(value, "[") || value == "null") {
|
||||
return urls
|
||||
}
|
||||
return []string{value}
|
||||
|
||||
Reference in New Issue
Block a user