作者 tangxvhui
1 -FROM golang:latest 1 +FROM 192.168.0.243:5000/mmm/performance-back:20221121test
2 #FROM 192.168.0.243:5000/mmm/digital-platform:20220831 2 #FROM 192.168.0.243:5000/mmm/digital-platform:20220831
3 ENV APP_DIR $GOPATH/src/performance 3 ENV APP_DIR $GOPATH/src/performance
4 RUN mkdir -p $APP_DIR 4 RUN mkdir -p $APP_DIR
  1 +#!/bin/bash
  2 +export PATH=/root/local/bin:$PATH
  3 +kubectl -n mmm-suplus-prd get pods | grep -q performance-back
  4 +if [ "$?" == "1" ];then
  5 + kubectl create -f /tmp/prd/performance-back/performance-back.yaml --record
  6 + kubectl -n mmm-suplus-prd get svc | grep -q performance-back
  7 + if [ "$?" == "0" ];then
  8 + echo "performance-back service install success!"
  9 + else
  10 + echo "performance-back service install fail!"
  11 + fi
  12 + kubectl -n mmm-suplus-prd get pods | grep -q performance-back
  13 + if [ "$?" == "0" ];then
  14 + echo "performance-back deployment install success!"
  15 + else
  16 + echo "performance-back deployment install fail!"
  17 + fi
  18 +else
  19 + kubectl delete -f /tmp/prd/performance-back/performance-back.yaml
  20 + kubectl -n mmm-suplus-prd get svc | grep -q performance-back
  21 + while [ "$?" == "0" ]
  22 + do
  23 + kubectl -n mmm-suplus-prd get svc | grep -q performance-back
  24 + done
  25 + kubectl -n mmm-suplus-prd get pods | grep -q performance-back
  26 + while [ "$?" == "0" ]
  27 + do
  28 + kubectl -n mmm-suplus-prd get pods | grep -q performance-back
  29 + done
  30 + kubectl create -f /tmp/prd/performance-back/performance-back.yaml --record
  31 + kubectl -n mmm-suplus-prd get svc | grep -q performance-back
  32 + if [ "$?" == "0" ];then
  33 + echo "performance-back service update success!"
  34 + else
  35 + echo "performance-back service update fail!"
  36 + fi
  37 + kubectl -n mmm-suplus-prd get pods | grep -q performance-back
  38 + if [ "$?" == "0" ];then
  39 + echo "performance-back deployment update success!"
  40 + else
  41 + echo "performance-back deployment update fail!"
  42 + fi
  43 +fi
  1 +apiVersion: v1
  2 +kind: Service
  3 +metadata:
  4 + name: performance-back
  5 + namespace: mmm-suplus-prd
  6 + labels:
  7 + k8s-app: performance-back
  8 +spec:
  9 + ports:
  10 + - name: "http"
  11 + port: 80
  12 + targetPort: 8082
  13 + - name: "https"
  14 + port: 443
  15 + targetPort: 443
  16 + selector:
  17 + k8s-app: performance-back
  18 +---
  19 +apiVersion: extensions/v1beta1
  20 +kind: Deployment
  21 +metadata:
  22 + name: performance-back
  23 + namespace: mmm-suplus-prd
  24 + labels:
  25 + k8s-app: performance-back
  26 +spec:
  27 + replicas: 1
  28 + template:
  29 + metadata:
  30 + labels:
  31 + k8s-app: performance-back
  32 + spec:
  33 + affinity:
  34 + nodeAffinity:
  35 + preferredDuringSchedulingIgnoredDuringExecution:
  36 + - preference: {}
  37 + weight: 100
  38 + requiredDuringSchedulingIgnoredDuringExecution:
  39 + nodeSelectorTerms:
  40 + - matchExpressions:
  41 + - key: kubernetes.io/hostname
  42 + operator: In
  43 + values:
  44 + - cn-hangzhou.i-bp1djh1xn7taumbue1ze
  45 + - cn-hangzhou.i-bp1djh1xn7taumbue1zd
  46 + - cn-hangzhou.i-bp1euf5u1ph9kbhtndhb
  47 + - cn-hangzhou.i-bp1hyp5oips9cdwxxgxy
  48 + containers:
  49 + - name: performance-back
  50 + image: 192.168.0.243:5000/mmm/performance-back:master
  51 + imagePullPolicy: Always
  52 + ports:
  53 + - containerPort: 8082
  54 + - containerPort: 443
  55 + volumeMounts:
  56 + - mountPath: /opt/logs
  57 + name: accesslogs
  58 + env:
  59 + - name: LOG_LEVEL
  60 + value: "debug"
  61 + - name: LOG_FILE
  62 + value: "true"
  63 + - name: ERROR_BASE_CODE
  64 + value: "1"
  65 + - name: ERROR_BASE_CODE_MULTIPLE
  66 + value: "1000"
  67 + - name: POSTGRESQL_DB_NAME
  68 + value: "performance_prd"
  69 + - name: ENABLE_HTTPS
  70 + value: "true"
  71 + - name: POSTGRESQL_USER
  72 + valueFrom:
  73 + configMapKeyRef:
  74 + name: suplus-config
  75 + key: postgresql.user
  76 + - name: POSTGRESQL_PASSWORD
  77 + valueFrom:
  78 + configMapKeyRef:
  79 + name: suplus-config
  80 + key: postgresql.password
  81 + - name: POSTGRESQL_HOST
  82 + valueFrom:
  83 + configMapKeyRef:
  84 + name: suplus-config
  85 + key: postgresql.host
  86 + - name: POSTGRESQL_PORT
  87 + valueFrom:
  88 + configMapKeyRef:
  89 + name: suplus-config
  90 + key: postgresql.port
  91 + - name: REDIS_HOST
  92 + valueFrom:
  93 + configMapKeyRef:
  94 + name: suplus-config
  95 + key: redis.ip
  96 + - name: REDIS_PORT
  97 + valueFrom:
  98 + configMapKeyRef:
  99 + name: suplus-config
  100 + key: redis.port
  101 + - name: KAFKA_HOSTS
  102 + valueFrom:
  103 + configMapKeyRef:
  104 + name: suplus-config
  105 + key: kafka.host
  106 + - name: KAFKA_PERFORMANCE_ID
  107 + valueFrom:
  108 + configMapKeyRef:
  109 + name: suplus-config
  110 + key: kafkaperformance.id
  111 + - name: KAFKA_BUSINESS_TOPIC
  112 + value: "mmm_business_prd"
  113 + - name: UCENTER_SERVICE_HOST
  114 + value: "https://suplus-ucenter-prd.fjmaimaimai.com"
  115 + - name: BUSINESS_ADMIN_SERVICE_HOST
  116 + value: "https://suplus-business-admin-prd.fjmaimaimai.com"
  117 + volumes:
  118 + - name: accesslogs
  119 + emptyDir: {}
  120 +
@@ -88,16 +88,20 @@ func (rs *EvaluationCycleService) Create(in *command.CreateCycleCommand) (interf @@ -88,16 +88,20 @@ func (rs *EvaluationCycleService) Create(in *command.CreateCycleCommand) (interf
88 } 88 }
89 } 89 }
90 } 90 }
  91 +
  92 + ruleMap := map[int64]*domain.EvaluationRule{}
91 ruleIds := make([]int64, 0) 93 ruleIds := make([]int64, 0)
92 for k := range ruleIdsMap { 94 for k := range ruleIdsMap {
93 ruleIds = append(ruleIds, k) 95 ruleIds = append(ruleIds, k)
94 } 96 }
95 -  
96 - _, rules, err := ruleRepository.Find(map[string]interface{}{"ids": ruleIds, "companyId": in.CompanyId})  
97 -  
98 - ruleMap := map[int64]*domain.EvaluationRule{}  
99 - for i := range rules {  
100 - ruleMap[rules[i].Id] = rules[i] 97 + if len(ruleIds) > 0 {
  98 + if _, rules, err := ruleRepository.Find(map[string]interface{}{"ids": ruleIds, "companyId": in.CompanyId}); err != nil {
  99 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  100 + } else {
  101 + for i := range rules {
  102 + ruleMap[rules[i].Id] = rules[i]
  103 + }
  104 + }
101 } 105 }
102 106
103 ctAdapter := &adapter.CycleTemplateAdapter{} 107 ctAdapter := &adapter.CycleTemplateAdapter{}
@@ -307,7 +311,10 @@ func (rs *EvaluationCycleService) Remove(in *command.DeleteCycleCommand) (interf @@ -307,7 +311,10 @@ func (rs *EvaluationCycleService) Remove(in *command.DeleteCycleCommand) (interf
307 311
308 cycleRepository := factory.CreateEvaluationCycleRepository(map[string]interface{}{"transactionContext": transactionContext}) 312 cycleRepository := factory.CreateEvaluationCycleRepository(map[string]interface{}{"transactionContext": transactionContext})
309 cycleTemplateRepository := factory.CreateEvaluationCycleTemplateRepository(map[string]interface{}{"transactionContext": transactionContext}) 313 cycleTemplateRepository := factory.CreateEvaluationCycleTemplateRepository(map[string]interface{}{"transactionContext": transactionContext})
  314 + projectRepository := factory.CreateEvaluationProjectRepository(map[string]interface{}{"transactionContext": transactionContext})
  315 + taskRepository := factory.CreateNodeTaskRepository(map[string]interface{}{"transactionContext": transactionContext})
310 316
  317 + // 删除周期
311 cycle, err := cycleRepository.FindOne(map[string]interface{}{"id": in.Id}) 318 cycle, err := cycleRepository.FindOne(map[string]interface{}{"id": in.Id})
312 if err != nil { 319 if err != nil {
313 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 320 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
@@ -316,11 +323,34 @@ func (rs *EvaluationCycleService) Remove(in *command.DeleteCycleCommand) (interf @@ -316,11 +323,34 @@ func (rs *EvaluationCycleService) Remove(in *command.DeleteCycleCommand) (interf
316 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 323 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
317 } 324 }
318 325
319 - // FIXME 删除周期关联的所有模板... 还需要删除关联的定时内容 326 + // 删除周期关联的所有模板,真删
320 if err := cycleTemplateRepository.BatchDeleteByCycleId(cycle.Id); err != nil { 327 if err := cycleTemplateRepository.BatchDeleteByCycleId(cycle.Id); err != nil {
321 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 328 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
322 } 329 }
323 330
  331 + // 删除周期下的所有项目
  332 + _, projects, err := projectRepository.Find(map[string]interface{}{"cycleId": in.Id}, "template")
  333 + if err != nil {
  334 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  335 + }
  336 + for i := range projects {
  337 + if _, err := projectRepository.Remove(projects[i]); err != nil {
  338 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  339 + }
  340 + }
  341 +
  342 + // 删除周期下的所有任务
  343 + tasks, err := taskRepository.Find(map[string]interface{}{"cycleId": in.Id})
  344 + if err != nil {
  345 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  346 + }
  347 +
  348 + for i := range tasks {
  349 + if _, err := taskRepository.Remove(tasks[i]); err != nil {
  350 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  351 + }
  352 + }
  353 +
324 if err := transactionContext.CommitTransaction(); err != nil { 354 if err := transactionContext.CommitTransaction(); err != nil {
325 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 355 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
326 } 356 }
@@ -17,16 +17,14 @@ type UpdateProjectCommand struct { @@ -17,16 +17,14 @@ type UpdateProjectCommand struct {
17 } 17 }
18 18
19 type UpdateProjectTemplateCommand struct { 19 type UpdateProjectTemplateCommand struct {
20 - CompanyId int64 `cname:"公司ID" json:"companyId"`  
21 - CycleId int64 `cname:"周期ID" json:"cycleId,string" valid:"Required"`  
22 - Id int64 `cname:"项目ID" json:"id,string" valid:"Required"`  
23 - TemplateId int64 `cname:"模板ID" json:"templateId,string"`  
24 - Recipients []string `cname:"被评估人ID" json:"recipients"`  
25 - TimeStart string `cname:"自评起始时间" json:"timeStart" valid:"Required"`  
26 - TimeEnd string `cname:"自评截止时间" json:"timeEnd" valid:"Required"`  
27 - KpiCycle int `cname:"评估周期" json:"kpiCycle" valid:"Required"`  
28 - KpiResultStart string `cname:"绩效结果开始查看时间" json:"kpiResultStart"`  
29 - Activate int `cname:"启动项目" json:"activate"` 20 + CompanyId int64 `cname:"公司ID" json:"companyId"`
  21 + CycleId int64 `cname:"周期ID" json:"cycleId,string" valid:"Required"`
  22 + Id int64 `cname:"项目ID" json:"id,string" valid:"Required"`
  23 + TemplateId int64 `cname:"模板ID" json:"templateId,string"`
  24 + Recipients []string `cname:"被评估人ID" json:"recipients"`
  25 + TimeStart string `cname:"自评起始时间" json:"timeStart" valid:"Required"`
  26 + TimeEnd string `cname:"自评截止时间" json:"timeEnd" valid:"Required"`
  27 + KpiCycle int `cname:"评估周期" json:"kpiCycle" valid:"Required"`
30 } 28 }
31 29
32 type CheckRecipientCommand struct { 30 type CheckRecipientCommand struct {
@@ -135,110 +135,169 @@ func (rs *EvaluationProjectService) UpdateTemplate(in *command.UpdateProjectTemp @@ -135,110 +135,169 @@ func (rs *EvaluationProjectService) UpdateTemplate(in *command.UpdateProjectTemp
135 cycleRepository := factory.CreateEvaluationCycleRepository(map[string]interface{}{"transactionContext": transactionContext}) 135 cycleRepository := factory.CreateEvaluationCycleRepository(map[string]interface{}{"transactionContext": transactionContext})
136 cycleTemplateRepository := factory.CreateEvaluationCycleTemplateRepository(map[string]interface{}{"transactionContext": transactionContext}) 136 cycleTemplateRepository := factory.CreateEvaluationCycleTemplateRepository(map[string]interface{}{"transactionContext": transactionContext})
137 137
138 - _, projects, err := projectRepository.Find(map[string]interface{}{"companyId": in.CompanyId, "cycleId": in.CycleId}, "template") 138 + project, err := projectRepository.FindOne(map[string]interface{}{"id": in.Id})
139 if err != nil { 139 if err != nil {
140 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 140 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
141 } 141 }
142 142
143 - cycle, err := cycleRepository.FindOne(map[string]interface{}{"id": in.CycleId})  
144 - if err != nil {  
145 - return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())  
146 - } 143 + // 如果是已经启用的项目,只能编辑环节的截至时间
  144 + if project.State == domain.ProjectStateEnable {
  145 + end, err := time.ParseInLocation("2006-01-02 15:04:05", in.TimeEnd, time.Local)
  146 + if err != nil {
  147 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  148 + }
147 149
148 - // 周期内的所有项目,员工不能重复被评估  
149 - rids := map[string]bool{}  
150 - for i := range projects {  
151 - // 排除当前项目  
152 - if in.Id != projects[i].Id {  
153 - ids := projects[i].Recipients  
154 - for j := range ids {  
155 - rids[ids[j]] = true 150 + cycle, err := cycleRepository.FindOne(map[string]interface{}{"id": in.CycleId})
  151 + if err != nil {
  152 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  153 + }
  154 + maxTime := cycle.TimeEnd.Local()
  155 + if end.After(maxTime) {
  156 + return nil, application.ThrowError(application.BUSINESS_ERROR, "评估截至时间不能超出周期截至时间")
  157 + }
  158 + if project.Template != nil {
  159 + for i := range project.Template.LinkNodes {
  160 + node := project.Template.LinkNodes[i]
  161 + node.TimeEnd = &end
156 } 162 }
157 } 163 }
158 - }  
159 - repeatNum := 0  
160 - for i := range in.Recipients {  
161 - id := in.Recipients[i]  
162 - if _, ok := rids[id]; ok {  
163 - repeatNum++ 164 + // 项目起始截止时间(暂时环节中的时间未分开)
  165 + project.EndTime = end
  166 + project, err = projectRepository.Insert(project)
  167 + if err != nil {
  168 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
164 } 169 }
165 - }  
166 - if repeatNum > 0 {  
167 - return nil, application.ThrowError(application.BUSINESS_ERROR, fmt.Sprintf("有%d人已经在本周期其他项目内,需要将他们移除", repeatNum))  
168 - }  
169 170
170 - project, err := projectRepository.FindOne(map[string]interface{}{"id": in.Id})  
171 - if err != nil {  
172 - return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())  
173 - } 171 + // 查看任务过程,重新日计算任务截至期
  172 + taskRepository := factory.CreateNodeTaskRepository(map[string]interface{}{"transactionContext": transactionContext})
  173 + tasks, err := taskRepository.Find(map[string]interface{}{"projectId": in.Id})
  174 + if err != nil {
  175 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  176 + }
174 177
175 - cycleTemplate, err := cycleTemplateRepository.FindOne(map[string]interface{}{"id": in.TemplateId, "includeDeleted": true})  
176 - if err != nil {  
177 - return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())  
178 - } 178 + now := time.Now().Local()
  179 + nowO := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local) // 当前时间0点0分0秒时刻
  180 +
  181 + for i := range tasks {
  182 + task := tasks[i]
  183 + task.TimeEnd = &end
  184 +
  185 + // 重新计算
  186 + if task.NextSentAt == nil {
  187 + // 环节起始和截止本地时间
  188 + startLocal := task.TimeStart.Local()
  189 + endLocal := task.TimeEnd.Local()
  190 +
  191 + // 在当前时间之前,则计算下一个周期时间
  192 + if startLocal.Before(now) {
  193 + nextTime := utils.NextTime(nowO, startLocal, task.KpiCycle)
  194 + task.NextSentAt = &nextTime
  195 + } else {
  196 + task.NextSentAt = &startLocal
  197 + }
  198 + // 如果超出截至时间,则周期置空
  199 + if task.NextSentAt.After(endLocal) {
  200 + task.NextSentAt = nil
  201 + }
  202 + } else {
  203 + // 新的截止时间在下一次发送周期任务之前,则结束
  204 + if end.Before(task.NextSentAt.Local()) {
  205 + task.NextSentAt = nil
  206 + } else {
  207 + // do nothing
  208 + }
  209 + }
  210 + }
179 211
180 - if cycleTemplate == nil || cycleTemplate.Template == nil {  
181 - return nil, application.ThrowError(application.BUSINESS_ERROR, "请添加模板")  
182 - } 212 + if err := transactionContext.CommitTransaction(); err != nil {
  213 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  214 + }
  215 + return project, nil
183 216
184 - if len(in.Recipients) == 0 {  
185 - return nil, application.ThrowError(application.BUSINESS_ERROR, "请添加被评估人")  
186 - } 217 + } else {
  218 + _, projects, err := projectRepository.Find(map[string]interface{}{"companyId": in.CompanyId, "cycleId": in.CycleId}, "template")
  219 + if err != nil {
  220 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  221 + }
  222 + // 周期内的所有项目,员工不能重复被评估
  223 + rids := map[string]bool{}
  224 + for i := range projects {
  225 + // 排除当前项目
  226 + if in.Id != projects[i].Id {
  227 + ids := projects[i].Recipients
  228 + for j := range ids {
  229 + rids[ids[j]] = true
  230 + }
  231 + }
  232 + }
  233 + repeatNum := 0
  234 + for i := range in.Recipients {
  235 + id := in.Recipients[i]
  236 + if _, ok := rids[id]; ok {
  237 + repeatNum++
  238 + }
  239 + }
  240 + if repeatNum > 0 {
  241 + return nil, application.ThrowError(application.BUSINESS_ERROR, fmt.Sprintf("有%d人已经在本周期其他项目内,需要将他们移除", repeatNum))
  242 + }
187 243
188 - start, err := time.ParseInLocation("2006-01-02 15:04:05", in.TimeStart, time.Local)  
189 - if err != nil {  
190 - return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())  
191 - }  
192 - end, err := time.ParseInLocation("2006-01-02 15:04:05", in.TimeEnd, time.Local)  
193 - if err != nil {  
194 - return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())  
195 - }  
196 - kpiStart, err := time.ParseInLocation("2006-01-02 15:04:05", in.KpiResultStart, time.Local)  
197 - if err != nil {  
198 - return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())  
199 - } 244 + cycleTemplate, err := cycleTemplateRepository.FindOne(map[string]interface{}{"id": in.TemplateId, "includeDeleted": true})
  245 + if err != nil {
  246 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  247 + }
  248 + if cycleTemplate == nil || cycleTemplate.Template == nil {
  249 + return nil, application.ThrowError(application.BUSINESS_ERROR, "请添加模板")
  250 + }
200 251
201 - minTime := cycle.TimeStart.Local()  
202 - maxTime := cycle.TimeEnd.Local() 252 + start, err := time.ParseInLocation("2006-01-02 15:04:05", in.TimeStart, time.Local)
  253 + if err != nil {
  254 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  255 + }
  256 + end, err := time.ParseInLocation("2006-01-02 15:04:05", in.TimeEnd, time.Local)
  257 + if err != nil {
  258 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  259 + }
203 260
204 - if start.Before(minTime) {  
205 - return nil, application.ThrowError(application.BUSINESS_ERROR, "评估起始时间不能超出周期起始时间")  
206 - } 261 + cycle, err := cycleRepository.FindOne(map[string]interface{}{"id": in.CycleId})
  262 + if err != nil {
  263 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  264 + }
  265 + minTime := cycle.TimeStart.Local()
  266 + maxTime := cycle.TimeEnd.Local()
207 267
208 - if end.After(maxTime) {  
209 - return nil, application.ThrowError(application.BUSINESS_ERROR, "评估截至时间不能超出周期截至时间")  
210 - } 268 + if start.Before(minTime) {
  269 + return nil, application.ThrowError(application.BUSINESS_ERROR, "评估起始时间不能超出周期起始时间")
  270 + }
211 271
212 - //// FIXME 启动时,需要激活定时任务  
213 - //if in.Activate == 1 {  
214 - // project.State = domain.ProjectStateEnable  
215 - //} else {  
216 - // project.State = domain.ProjectStateWaitActive  
217 - //}  
218 - project.State = domain.ProjectStateWaitActive 272 + if end.After(maxTime) {
  273 + return nil, application.ThrowError(application.BUSINESS_ERROR, "评估截至时间不能超出周期截至时间")
  274 + }
219 275
220 - project.Recipients = in.Recipients  
221 - project.Template = cycleTemplate.Template  
222 - for i := range project.Template.LinkNodes {  
223 - node := project.Template.LinkNodes[i]  
224 - node.KpiCycle = in.KpiCycle // 设置周期  
225 - if node.Type == domain.LinkNodeViewResult {  
226 - node.TimeStart = &kpiStart  
227 - node.TimeEnd = &maxTime // 绩效查看时间跟随周期截止时间  
228 - } else { 276 + if project.State == domain.ProjectStateWaitConfig {
  277 + project.State = domain.ProjectStateWaitActive
  278 + }
  279 + project.Recipients = in.Recipients
  280 + project.Template = cycleTemplate.Template
  281 +
  282 + // 项目起始截止时间(环节中的时间暂未分开计算)
  283 + project.BeginTime = start
  284 + project.EndTime = end
  285 + for i := range project.Template.LinkNodes {
  286 + node := project.Template.LinkNodes[i]
  287 + node.KpiCycle = in.KpiCycle // 设置周期
229 node.TimeStart = &start 288 node.TimeStart = &start
230 node.TimeEnd = &end 289 node.TimeEnd = &end
231 } 290 }
232 - }  
233 291
234 - project, err = projectRepository.Insert(project)  
235 - if err != nil {  
236 - return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())  
237 - }  
238 - if err := transactionContext.CommitTransaction(); err != nil {  
239 - return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 292 + project, err = projectRepository.Insert(project)
  293 + if err != nil {
  294 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  295 + }
  296 + if err := transactionContext.CommitTransaction(); err != nil {
  297 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  298 + }
  299 + return project, nil
240 } 300 }
241 - return project, nil  
242 } 301 }
243 302
244 func (rs *EvaluationProjectService) Get(in *command.GetProjectCommand) (interface{}, error) { 303 func (rs *EvaluationProjectService) Get(in *command.GetProjectCommand) (interface{}, error) {
@@ -285,6 +344,7 @@ func (rs *EvaluationProjectService) Remove(in *command.DeleteProjectCommand) (in @@ -285,6 +344,7 @@ func (rs *EvaluationProjectService) Remove(in *command.DeleteProjectCommand) (in
285 }() 344 }()
286 345
287 projectRepository := factory.CreateEvaluationProjectRepository(map[string]interface{}{"transactionContext": transactionContext}) 346 projectRepository := factory.CreateEvaluationProjectRepository(map[string]interface{}{"transactionContext": transactionContext})
  347 + taskRepository := factory.CreateNodeTaskRepository(map[string]interface{}{"transactionContext": transactionContext})
288 348
289 project, err := projectRepository.FindOne(map[string]interface{}{"id": in.Id}) 349 project, err := projectRepository.FindOne(map[string]interface{}{"id": in.Id})
290 if err != nil { 350 if err != nil {
@@ -294,6 +354,17 @@ func (rs *EvaluationProjectService) Remove(in *command.DeleteProjectCommand) (in @@ -294,6 +354,17 @@ func (rs *EvaluationProjectService) Remove(in *command.DeleteProjectCommand) (in
294 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 354 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
295 } 355 }
296 356
  357 + // 查看任务过程,移除项目关联的所有任务
  358 + tasks, err := taskRepository.Find(map[string]interface{}{"projectId": in.Id})
  359 + if err != nil {
  360 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  361 + }
  362 + for i := range tasks {
  363 + if _, err := taskRepository.Remove(tasks[i]); err != nil {
  364 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  365 + }
  366 + }
  367 +
297 if err := transactionContext.CommitTransaction(); err != nil { 368 if err := transactionContext.CommitTransaction(); err != nil {
298 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 369 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
299 } 370 }
@@ -314,6 +385,8 @@ func (rs *EvaluationProjectService) List(in *command.QueryProjectCommand) (inter @@ -314,6 +385,8 @@ func (rs *EvaluationProjectService) List(in *command.QueryProjectCommand) (inter
314 if err != nil { 385 if err != nil {
315 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 386 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
316 } 387 }
  388 +
  389 + now := time.Now().Unix()
317 pmpUsers := make([]*domain.User, 0) 390 pmpUsers := make([]*domain.User, 0)
318 pmpUserIds := make([]int64, 0) 391 pmpUserIds := make([]int64, 0)
319 for i := range projects { 392 for i := range projects {
@@ -322,7 +395,13 @@ func (rs *EvaluationProjectService) List(in *command.QueryProjectCommand) (inter @@ -322,7 +395,13 @@ func (rs *EvaluationProjectService) List(in *command.QueryProjectCommand) (inter
322 userId, _ := strconv.ParseInt(project.PmpIds[j], 10, 64) 395 userId, _ := strconv.ParseInt(project.PmpIds[j], 10, 64)
323 pmpUserIds = append(pmpUserIds, userId) 396 pmpUserIds = append(pmpUserIds, userId)
324 } 397 }
  398 +
  399 + // 当前时间超过截至时间显示【已结束】
  400 + if now > project.EndTime.Unix() {
  401 + project.State = domain.ProjectStateDisable
  402 + }
325 } 403 }
  404 +
326 if len(pmpUserIds) > 0 { 405 if len(pmpUserIds) > 0 {
327 userRepository := factory.CreateUserRepository(map[string]interface{}{"transactionContext": transactionContext}) 406 userRepository := factory.CreateUserRepository(map[string]interface{}{"transactionContext": transactionContext})
328 _, users, _ := userRepository.Find(map[string]interface{}{"ids": pmpUserIds, "limit": len(pmpUserIds)}) 407 _, users, _ := userRepository.Find(map[string]interface{}{"ids": pmpUserIds, "limit": len(pmpUserIds)})
@@ -342,29 +421,20 @@ func (rs *EvaluationProjectService) Activate(in *command.ActivateProjectCommand) @@ -342,29 +421,20 @@ func (rs *EvaluationProjectService) Activate(in *command.ActivateProjectCommand)
342 }() 421 }()
343 422
344 projectRepository := factory.CreateEvaluationProjectRepository(map[string]interface{}{"transactionContext": transactionContext}) 423 projectRepository := factory.CreateEvaluationProjectRepository(map[string]interface{}{"transactionContext": transactionContext})
345 - //cycleRepository := factory.CreateEvaluationCycleRepository(map[string]interface{}{"transactionContext": transactionContext})  
346 424
347 project, err := projectRepository.FindOne(map[string]interface{}{"id": in.Id}) 425 project, err := projectRepository.FindOne(map[string]interface{}{"id": in.Id})
348 if err != nil { 426 if err != nil {
349 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 427 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
350 } 428 }
351 -  
352 if project.Template == nil { 429 if project.Template == nil {
353 return nil, application.ThrowError(application.BUSINESS_ERROR, "请添加评估模板") 430 return nil, application.ThrowError(application.BUSINESS_ERROR, "请添加评估模板")
354 } 431 }
355 -  
356 if len(project.Recipients) == 0 { 432 if len(project.Recipients) == 0 {
357 return nil, application.ThrowError(application.BUSINESS_ERROR, "请添加被评估人") 433 return nil, application.ThrowError(application.BUSINESS_ERROR, "请添加被评估人")
358 } 434 }
359 if project.State == domain.TemplateStateEnable { 435 if project.State == domain.TemplateStateEnable {
360 return nil, application.ThrowError(application.BUSINESS_ERROR, "项目已启动") 436 return nil, application.ThrowError(application.BUSINESS_ERROR, "项目已启动")
361 } 437 }
362 - //cycle, err := cycleRepository.FindOne(map[string]interface{}{"id": project.CycleId})  
363 - //if err != nil {  
364 - // return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())  
365 - //}  
366 - //startMin := cycle.TimeStart  
367 - //maxTime := cycle.TimeEnd  
368 438
369 project.State = domain.TemplateStateEnable 439 project.State = domain.TemplateStateEnable
370 project, err = projectRepository.Insert(project) 440 project, err = projectRepository.Insert(project)
@@ -422,42 +492,6 @@ func (rs *EvaluationProjectService) Activate(in *command.ActivateProjectCommand) @@ -422,42 +492,6 @@ func (rs *EvaluationProjectService) Activate(in *command.ActivateProjectCommand)
422 return project, nil 492 return project, nil
423 } 493 }
424 494
425 -//  
426 -//// 0点时刻为标准计算  
427 -//func (rs *EvaluationProjectService) nextTime(now0 time.Time, start *time.Time, kpiCycle int) time.Time {  
428 -// // 起始时间0点时刻  
429 -// start0 := time.Date(start.Year(), start.Month(), start.Day(), 0, 0, 0, 0, time.Local)  
430 -//  
431 -// var nextTime time.Time  
432 -// switch kpiCycle {  
433 -// case domain.KpiCycleDay:  
434 -// nextTime = timeconv.AddDate(now0, 0, 0, 1) // 当前时间的下一天开始发送  
435 -// break  
436 -// case domain.KpiCycleWeek:  
437 -// offsetSeconds := int64(now0.Sub(start0).Seconds())  
438 -// offsetDay := offsetSeconds / (24 * 60 * 60)  
439 -// cycleCount := int(offsetDay)/7 + 1  
440 -// nextTime = timeconv.AddDate(start0, 0, 0, cycleCount*7)  
441 -// break  
442 -// case domain.KpiCycleOneMonth:  
443 -// nextTime = timeconv.AddDate(start0, 0, 1, 0)  
444 -// break  
445 -// case domain.KpiCycleTwoMonth:  
446 -// nextTime = timeconv.AddDate(start0, 0, 2, 0)  
447 -// break  
448 -// case domain.KpiCycleThreeMonth:  
449 -// nextTime = timeconv.AddDate(start0, 0, 3, 0)  
450 -// break  
451 -// case domain.KpiCycleSixMonth:  
452 -// nextTime = timeconv.AddDate(start0, 0, 6, 0)  
453 -// break  
454 -// case domain.KpiCycleYear:  
455 -// nextTime = timeconv.AddDate(start0, 1, 0, 0)  
456 -// break  
457 -// }  
458 -// return nextTime  
459 -//}  
460 -  
461 func (rs *EvaluationProjectService) Copy(in *command.CopyProjectCommand) (interface{}, error) { 495 func (rs *EvaluationProjectService) Copy(in *command.CopyProjectCommand) (interface{}, error) {
462 transactionContext, err := factory.ValidateStartTransaction(in) 496 transactionContext, err := factory.ValidateStartTransaction(in)
463 if err != nil { 497 if err != nil {
@@ -8,7 +8,7 @@ const ( @@ -8,7 +8,7 @@ const (
8 ProjectStateWaitConfig int = 0 // 项目状态-待完成配置 8 ProjectStateWaitConfig int = 0 // 项目状态-待完成配置
9 ProjectStateWaitActive int = 1 // 项目状态-待启用 9 ProjectStateWaitActive int = 1 // 项目状态-待启用
10 ProjectStateEnable int = 2 // 项目状态-启用 10 ProjectStateEnable int = 2 // 项目状态-启用
11 - ProjectStateDisable int = 3 // 项目状态-停用 11 + ProjectStateDisable int = 3 // 项目状态-停用(假状态)
12 ) 12 )
13 13
14 // 项目的评估内容配置 14 // 项目的评估内容配置
@@ -25,6 +25,8 @@ type EvaluationProject struct { @@ -25,6 +25,8 @@ type EvaluationProject struct {
25 PmpIds []string `json:"pmpIds" comment:"项目管理员ID"` 25 PmpIds []string `json:"pmpIds" comment:"项目管理员ID"`
26 Recipients []string `json:"recipients" comment:"被评估人ID"` 26 Recipients []string `json:"recipients" comment:"被评估人ID"`
27 Template *EvaluationTemplate `json:"template" comment:"评估模板"` 27 Template *EvaluationTemplate `json:"template" comment:"评估模板"`
  28 + BeginTime time.Time `json:"beginTime" comment:"项目起始时间"`
  29 + EndTime time.Time `json:"endTime" comment:"项目截至时间"`
28 CreatedAt time.Time `json:"createdAt" comment:"创建时间"` 30 CreatedAt time.Time `json:"createdAt" comment:"创建时间"`
29 UpdatedAt time.Time `json:"updatedAt" comment:"更新时间"` 31 UpdatedAt time.Time `json:"updatedAt" comment:"更新时间"`
30 DeletedAt *time.Time `json:"deletedAt" comment:"删除时间"` 32 DeletedAt *time.Time `json:"deletedAt" comment:"删除时间"`
@@ -19,6 +19,8 @@ type EvaluationProject struct { @@ -19,6 +19,8 @@ type EvaluationProject struct {
19 PmpIds []string `comment:"项目管理员ID"` 19 PmpIds []string `comment:"项目管理员ID"`
20 Recipients []string `comment:"被评估人ID"` 20 Recipients []string `comment:"被评估人ID"`
21 Template *domain.EvaluationTemplate `comment:"评估模板"` 21 Template *domain.EvaluationTemplate `comment:"评估模板"`
  22 + BeginTime time.Time `comment:"项目起始时间"`
  23 + EndTime time.Time `comment:"项目截至时间 "`
22 CreatedAt time.Time `comment:"创建时间"` 24 CreatedAt time.Time `comment:"创建时间"`
23 UpdatedAt time.Time `comment:"更新时间"` 25 UpdatedAt time.Time `comment:"更新时间"`
24 DeletedAt *time.Time `comment:"删除时间"` 26 DeletedAt *time.Time `comment:"删除时间"`
1 -package models  
2 -  
3 -import (  
4 - "time"  
5 -)  
6 -  
7 -type NodeTimerTask struct {  
8 - tableName struct{} `pg:"node_timer_task" comment:"流程节点定时任务"`  
9 - Id int64 `comment:"ID"`  
10 - CompanyId int64 `comment:"公司ID"`  
11 - CycleId int64 `comment:"周期ID"`  
12 - ProjectId int64 `comment:"项目ID"`  
13 - NodeId int64 `comment:"流程ID"`  
14 - LastSentAt *time.Time `comment:"最后一次发送时间"`  
15 - NextSentAt *time.Time `comment:"下一次发送时间"`  
16 - CreatedAt time.Time `comment:"创建时间"`  
17 - UpdatedAt time.Time `comment:"更新时间"`  
18 - DeletedAt *time.Time `comment:"删除时间"`  
19 -}  
@@ -148,6 +148,9 @@ func (repo *EvaluationCycleRepository) Find(queryOptions map[string]interface{}) @@ -148,6 +148,9 @@ func (repo *EvaluationCycleRepository) Find(queryOptions map[string]interface{})
148 query.Where("time_end>=?", t) 148 query.Where("time_end>=?", t)
149 } 149 }
150 150
  151 + // 按创建时间降序
  152 + query.Order("created_at DESC")
  153 +
151 count, err := query.SelectAndCount() 154 count, err := query.SelectAndCount()
152 if err != nil { 155 if err != nil {
153 return 0, nil, err 156 return 0, nil, err
@@ -34,6 +34,8 @@ func (repo *EvaluationProjectRepository) TransformToDomain(m *models.EvaluationP @@ -34,6 +34,8 @@ func (repo *EvaluationProjectRepository) TransformToDomain(m *models.EvaluationP
34 PmpIds: m.PmpIds, 34 PmpIds: m.PmpIds,
35 Recipients: m.Recipients, 35 Recipients: m.Recipients,
36 Template: m.Template, 36 Template: m.Template,
  37 + BeginTime: m.BeginTime,
  38 + EndTime: m.EndTime,
37 CreatedAt: m.CreatedAt, 39 CreatedAt: m.CreatedAt,
38 UpdatedAt: m.UpdatedAt, 40 UpdatedAt: m.UpdatedAt,
39 DeletedAt: m.DeletedAt, 41 DeletedAt: m.DeletedAt,
@@ -54,6 +56,8 @@ func (repo *EvaluationProjectRepository) TransformToModel(d *domain.EvaluationPr @@ -54,6 +56,8 @@ func (repo *EvaluationProjectRepository) TransformToModel(d *domain.EvaluationPr
54 PmpIds: d.PmpIds, 56 PmpIds: d.PmpIds,
55 Recipients: d.Recipients, 57 Recipients: d.Recipients,
56 Template: d.Template, 58 Template: d.Template,
  59 + BeginTime: d.BeginTime,
  60 + EndTime: d.EndTime,
57 CreatedAt: d.CreatedAt, 61 CreatedAt: d.CreatedAt,
58 UpdatedAt: d.UpdatedAt, 62 UpdatedAt: d.UpdatedAt,
59 DeletedAt: d.DeletedAt, 63 DeletedAt: d.DeletedAt,
@@ -166,6 +170,8 @@ func (repo *EvaluationProjectRepository) Find(queryOptions map[string]interface{ @@ -166,6 +170,8 @@ func (repo *EvaluationProjectRepository) Find(queryOptions map[string]interface{
166 if v, ok := queryOptions["offset"].(int64); ok { 170 if v, ok := queryOptions["offset"].(int64); ok {
167 query.Offset(int(v)) 171 query.Offset(int(v))
168 } 172 }
  173 + // 按创建时间降序
  174 + query.Order("created_at DESC")
169 175
170 count, err := query.SelectAndCount() 176 count, err := query.SelectAndCount()
171 if err != nil { 177 if err != nil {
@@ -21,8 +21,6 @@ func (controller *ProjectController) CreateProject() { @@ -21,8 +21,6 @@ func (controller *ProjectController) CreateProject() {
21 ua := middlewares.GetUser(controller.Ctx) 21 ua := middlewares.GetUser(controller.Ctx)
22 in.CompanyId = ua.CompanyId 22 in.CompanyId = ua.CompanyId
23 in.CreatorId = ua.UserId 23 in.CreatorId = ua.UserId
24 - //in.CompanyId = middlewares.GetCompanyId(controller.Ctx)  
25 - //in.CreatorId = middlewares.GetUserId(controller.Ctx)  
26 controller.Response(ruService.Create(in)) 24 controller.Response(ruService.Create(in))
27 } 25 }
28 } 26 }
@@ -35,7 +33,6 @@ func (controller *ProjectController) UpdateProject() { @@ -35,7 +33,6 @@ func (controller *ProjectController) UpdateProject() {
35 } else { 33 } else {
36 ua := middlewares.GetUser(controller.Ctx) 34 ua := middlewares.GetUser(controller.Ctx)
37 in.CompanyId = ua.CompanyId 35 in.CompanyId = ua.CompanyId
38 - //in.CompanyId = middlewares.GetCompanyId(controller.Ctx)  
39 controller.Response(ruService.Update(in)) 36 controller.Response(ruService.Update(in))
40 } 37 }
41 } 38 }
@@ -48,7 +45,6 @@ func (controller *ProjectController) UpdateProjectForTemplate() { @@ -48,7 +45,6 @@ func (controller *ProjectController) UpdateProjectForTemplate() {
48 } else { 45 } else {
49 ua := middlewares.GetUser(controller.Ctx) 46 ua := middlewares.GetUser(controller.Ctx)
50 in.CompanyId = ua.CompanyId 47 in.CompanyId = ua.CompanyId
51 - //in.CompanyId = middlewares.GetCompanyId(controller.Ctx)  
52 controller.Response(ruService.UpdateTemplate(in)) 48 controller.Response(ruService.UpdateTemplate(in))
53 } 49 }
54 } 50 }
@@ -86,7 +82,6 @@ func (controller *ProjectController) ListProject() { @@ -86,7 +82,6 @@ func (controller *ProjectController) ListProject() {
86 } 82 }
87 ua := middlewares.GetUser(controller.Ctx) 83 ua := middlewares.GetUser(controller.Ctx)
88 in.CompanyId = ua.CompanyId 84 in.CompanyId = ua.CompanyId
89 - //in.CompanyId = middlewares.GetCompanyId(controller.Ctx)  
90 controller.Response(ruService.List(in)) 85 controller.Response(ruService.List(in))
91 } 86 }
92 } 87 }
@@ -5,6 +5,7 @@ import ( @@ -5,6 +5,7 @@ import (
5 timeconv "github.com/Andrew-M-C/go.timeconv" 5 timeconv "github.com/Andrew-M-C/go.timeconv"
6 "github.com/beego/beego/v2/core/validation" 6 "github.com/beego/beego/v2/core/validation"
7 "gitlab.fjmaimaimai.com/allied-creation/performance/pkg/domain" 7 "gitlab.fjmaimaimai.com/allied-creation/performance/pkg/domain"
  8 + "math"
8 "reflect" 9 "reflect"
9 "strings" 10 "strings"
10 "time" 11 "time"
@@ -53,24 +54,92 @@ func NextTime(now0 time.Time, start time.Time, kpiCycle int) time.Time { @@ -53,24 +54,92 @@ func NextTime(now0 time.Time, start time.Time, kpiCycle int) time.Time {
53 nextTime = timeconv.AddDate(start0, 0, 0, cycleCount*7) 54 nextTime = timeconv.AddDate(start0, 0, 0, cycleCount*7)
54 break 55 break
55 case domain.KpiCycleOneMonth: 56 case domain.KpiCycleOneMonth:
56 - nextTime = timeconv.AddDate(start0, 0, 1, 0) 57 + offsetMonth := SubMonth(now0, start0)
  58 + nextTime = timeconv.AddDate(start0, 0, offsetMonth, 0)
  59 + if nextTime.Before(now0) {
  60 + nextTime = timeconv.AddDate(nextTime, 0, 1, 0)
  61 + }
57 break 62 break
58 case domain.KpiCycleTwoMonth: 63 case domain.KpiCycleTwoMonth:
59 - nextTime = timeconv.AddDate(start0, 0, 2, 0) 64 + offsetMonth := SubMonth(now0, start0)
  65 + multiple := float64(offsetMonth) / 2
  66 + if multiple == 0 {
  67 + multiple = 1
  68 + } else {
  69 + multiple = math.Ceil(multiple)
  70 + }
  71 + nextTime = timeconv.AddDate(start0, 0, int(multiple)*2, 0)
  72 + if nextTime.Before(now0) {
  73 + nextTime = timeconv.AddDate(nextTime, 0, 2, 0)
  74 + }
60 break 75 break
61 case domain.KpiCycleThreeMonth: 76 case domain.KpiCycleThreeMonth:
62 - nextTime = timeconv.AddDate(start0, 0, 3, 0) 77 + offsetMonth := SubMonth(now0, start0)
  78 + multiple := float64(offsetMonth) / 3
  79 + if multiple == 0 {
  80 + multiple = 1
  81 + } else {
  82 + multiple = math.Ceil(multiple)
  83 + }
  84 + nextTime = timeconv.AddDate(start0, 0, int(multiple)*3, 0)
  85 + if nextTime.Before(now0) {
  86 + nextTime = timeconv.AddDate(nextTime, 0, 3, 0)
  87 + }
63 break 88 break
64 case domain.KpiCycleSixMonth: 89 case domain.KpiCycleSixMonth:
65 - nextTime = timeconv.AddDate(start0, 0, 6, 0) 90 + offsetMonth := SubMonth(now0, start0)
  91 + multiple := float64(offsetMonth) / 6
  92 + if multiple == 0 {
  93 + multiple = 1
  94 + } else {
  95 + multiple = math.Ceil(multiple)
  96 + }
  97 + nextTime = timeconv.AddDate(start0, 0, int(multiple)*6, 0)
  98 + if nextTime.Before(now0) {
  99 + nextTime = timeconv.AddDate(nextTime, 0, 6, 0)
  100 + }
66 break 101 break
67 case domain.KpiCycleYear: 102 case domain.KpiCycleYear:
68 - nextTime = timeconv.AddDate(start0, 1, 0, 0) 103 + offsetMonth := SubMonth(now0, start0)
  104 + multiple := float64(offsetMonth) / 12
  105 + if multiple == 0 {
  106 + multiple = 1
  107 + } else {
  108 + multiple = math.Ceil(multiple)
  109 + }
  110 + nextTime = timeconv.AddDate(start0, 0, int(multiple)*12, 0)
  111 + if nextTime.Before(now0) {
  112 + nextTime = timeconv.AddDate(nextTime, 0, 12, 0)
  113 + }
69 break 114 break
70 } 115 }
71 return nextTime 116 return nextTime
72 } 117 }
73 118
  119 +// SubMonth 计算日期相差多少月
  120 +func SubMonth(t1, t2 time.Time) (month int) {
  121 + y1 := t1.Year()
  122 + y2 := t2.Year()
  123 + m1 := int(t1.Month())
  124 + m2 := int(t2.Month())
  125 + d1 := t1.Day()
  126 + d2 := t2.Day()
  127 +
  128 + yearInterval := y1 - y2
  129 + // 如果 d1的 月-日 小于 d2的 月-日 那么 yearInterval-- 这样就得到了相差的年数
  130 + if m1 < m2 || (m1 == m2 && d1 < d2) {
  131 + yearInterval--
  132 + }
  133 + // 获取月数差值
  134 + monthInterval := (m1 + 12) - m2
  135 + if d1 < d2 {
  136 + monthInterval--
  137 + }
  138 + monthInterval %= 12
  139 + month = yearInterval*12 + monthInterval
  140 + return
  141 +}
  142 +
74 // NextTimeInc 0点时刻为标准计算 143 // NextTimeInc 0点时刻为标准计算
75 func NextTimeInc(start time.Time, kpiCycle int) time.Time { 144 func NextTimeInc(start time.Time, kpiCycle int) time.Time {
76 year, month, day := start.Date() 145 year, month, day := start.Date()