Explorar o código

add:添加CNAS实验室、验证方案,验证报告回款后盖章

zoie hai 2 meses
pai
achega
93bb069771

+ 9 - 7
conf/app.conf

@@ -6,20 +6,20 @@ EnableDocs = true
 copyrequestbody = true
 
 # Nats
-NatsServer_Url = "182.44.114.34:4222"
+NatsServer_Url = "203.34.49.130:4222"
 NatsForbidden = true
 
-MysqlServer_UrlPort = "182.44.114.34:3306"
+MysqlServer_UrlPort = "203.34.49.130:3306"
 MysqlServer_Database = "coldverify"
-MysqlServer_Username = "root"
-MysqlServer_Password = "mysql_Ks7WAX"
+MysqlServer_Username = "coldverify"
+MysqlServer_Password = "Bd3d34yJ7aibiEi"
 MysqlServer_MaxIdleConnections = 100
 MysqlServer_MaxOpenConnections = 200
 
 
 # Redis
-Redis_address = "182.44.114.34:6379"
-Redis_password = "redis_F2tj7p"
+Redis_address = "203.34.49.130:6379"
+Redis_password = "redis_JJ56d5"
 Redis_dbNum = "2"
 
 
@@ -41,4 +41,6 @@ BoosUuid = "fa5be10f-5be1-42be-a8dc-8d142e006266"
 VdelUuid = "1c13436c-4511-4030-8b26-baadad88445a"
 
 OpenApi_Key = "coldverify"
-OpenApi_Secret = "H3L9OPQR2VX8ZZYN7STKFG5JMWB1CV4D"
+OpenApi_Secret = "H3L9OPQR2VX8ZZYN7STKFG5JMWB1CV4D"
+
+PdfProcessingHost = "https://coldverify-u.coldbaozhida.com/PdfProcessing"

+ 3 - 1
conf/app_prod.conf

@@ -41,4 +41,6 @@ BoosUuid = "fa5be10f-5be1-42be-a8dc-8d142e006266"
 VdelUuid = "1c13436c-4511-4030-8b26-baadad88445a"
 
 OpenApi_Key = "coldverify"
-OpenApi_Secret = "H3L9OPQR2VX8ZZYN7STKFG5JMWB1CV4D"
+OpenApi_Secret = "H3L9OPQR2VX8ZZYN7STKFG5JMWB1CV4D"
+
+PdfProcessingHost = "https://coldverify-u.coldbaozhida.com/PdfProcessing"

+ 3 - 1
conf/app_test.conf

@@ -41,4 +41,6 @@ BoosUuid = "fa5be10f-5be1-42be-a8dc-8d142e006266"
 VdelUuid = "1c13436c-4511-4030-8b26-baadad88445a"
 
 OpenApi_Key = "coldverify"
-OpenApi_Secret = "H3L9OPQR2VX8ZZYN7STKFG5JMWB1CV4D"
+OpenApi_Secret = "H3L9OPQR2VX8ZZYN7STKFG5JMWB1CV4D"
+
+PdfProcessingHost = "https://coldverify-u.coldbaozhida.com/PdfProcessing"

+ 2 - 0
conf/config.go

@@ -43,3 +43,5 @@ var VdelUuid, _ = beego.AppConfig.String("VdelUuid")
 
 var OpenApi_Key, _ = beego.AppConfig.String("OpenApi_Key")
 var OpenApi_Secret, _ = beego.AppConfig.String("OpenApi_Secret")
+
+var PdfProcessingHost, _ = beego.AppConfig.String("PdfProcessingHost")

+ 7 - 1
controllers/Account.go

@@ -170,6 +170,7 @@ func (c *AccountController) Add() {
 	T_pass := c.GetString("T_pass")
 	T_wxname := c.GetString("T_wxname")
 	T_Distributor_id := c.GetString("T_Distributor_id")
+	T_signature_img := c.GetString("T_signature_img")
 	if len(T_Distributor_id) == 0 {
 		T_Distributor_id = User_r.T_Distributor_id
 	}
@@ -188,6 +189,7 @@ func (c *AccountController) Add() {
 		T_wxname:         T_wxname,
 		T_State:          1,
 		T_Distributor_id: T_Distributor_id, // 分销商id,内部管理员为空
+		T_signature_img:  T_signature_img,
 	}
 
 	if err, _ := Account.Read_Admin_ByT_user(T_user); err == nil {
@@ -231,6 +233,7 @@ func (c *AccountController) Up() {
 	T_user := c.GetString("T_user")
 	T_pass := c.GetString("T_pass")
 	T_wxname := c.GetString("T_wxname")
+	T_signature_img := c.GetString("T_signature_img")
 
 	err, r := Account.Read_Admin_ByT_uuid(T_uuid)
 	if err != nil {
@@ -259,8 +262,11 @@ func (c *AccountController) Up() {
 	if len(T_wxname) > 0 {
 		r.T_wxname = T_wxname
 	}
+	if len(T_signature_img) > 0 {
+		r.T_signature_img = T_signature_img
+	}
 
-	if !Account.Update_Admin(r, "T_power", "T_name", "T_user", "T_pass", "T_wxname") {
+	if !Account.Update_Admin(r, "T_power", "T_name", "T_user", "T_pass", "T_wxname", "T_signature_img") {
 		c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败!"}
 		c.ServeJSON()
 		return

+ 397 - 11
controllers/Task.go

@@ -658,6 +658,7 @@ func (c *TaskController) Add() {
 	T_report_number := c.GetString("T_report_number")     // 报告编号
 	T_report_type := c.GetString("T_report_type")         // 报告类型
 	T_device_quantity, _ := c.GetInt("T_device_quantity") // 终端数量
+	T_cnas, _ := c.GetInt("T_cnas")                       // cnas实验室
 
 	// 查询信息采集信息
 	infoCollection, is := InfoCollection.Read_InfoCollection(T_InfoCollection_id)
@@ -708,6 +709,7 @@ func (c *TaskController) Add() {
 		T_report_number:   T_report_number,
 		T_report_type:     T_report_type,
 		T_device_quantity: T_device_quantity,
+		T_cnas:            T_cnas,
 	}
 	if T_report_number != "/" {
 		_, exist := Task.Read_TaskbyT_report_number(T_report_number)
@@ -1027,6 +1029,8 @@ func (c *TaskController) Up() {
 	T_doc3 := c.GetString("T_doc3")
 	T_pdf3 := c.GetString("T_pdf3")
 	T_pdf4 := c.GetString("T_pdf4") // 验证标识
+	T_pdf5 := c.GetString("T_pdf5") // 检测报告
+	T_pdf6 := c.GetString("T_pdf6") // 原始记录
 
 	T_VerifyDeviceDataStartTime := c.GetString("T_VerifyDeviceDataStartTime") // 验证设备数据开始时间
 	T_VerifyDeviceDataEndTime := c.GetString("T_VerifyDeviceDataEndTime")     // 验证设备数据开始时间
@@ -1051,6 +1055,7 @@ func (c *TaskController) Up() {
 	T_report_number := c.GetString("T_report_number")     // 报告编号
 	T_report_type := c.GetString("T_report_type")         // 报告编号
 	T_device_quantity, _ := c.GetInt("T_device_quantity") // 报告编号
+	T_cnas, _ := c.GetInt("T_cnas")                       // cnas实验室
 
 	T_task_id := c.GetString("T_task_id")
 	r, is := Task.Read_Task(T_task_id)
@@ -1260,6 +1265,66 @@ func (c *TaskController) Up() {
 		r.T_marking_state = 1
 		clos = append(clos, "T_marking_state")
 	}
+	if len(T_pdf5) > 0 {
+		r.T_pdf5 = T_pdf5
+		clos = append(clos, "T_pdf5")
+		r.T_examining_report_state = 1
+		clos = append(clos, "T_examining_report_state")
+		// 添加已提交状态 检测报告记录
+		auditRecordJson, err := Task.Add_AuditRecord(r.T_examining_report_audit_record, "", User_r.T_uuid, r.T_examining_report_state, "", "")
+		if err == nil {
+			r.T_examining_report_audit_record = auditRecordJson
+			clos = append(clos, "T_examining_report_audit_record")
+			r.T_examining_report_end_time = time.Now().Format("2006-01-02 15:04:05")
+			clos = append(clos, "T_examining_report_end_time")
+			if len(r.T_examining_report_start_time) > 0 {
+				r.T_examining_report_time_interval, _ = lib.MinutesDifference(r.T_examining_report_start_time, r.T_examining_report_end_time)
+				clos = append(clos, "T_examining_report_time_interval")
+				// 扣除暂停时间
+				Task_Compute := Task.Read_TaskTime_Compute(r.T_task_id, 3)
+				if Task_Compute > 0 {
+					r.T_examining_report_time_interval -= float64(Task_Compute)
+				}
+				clos = append(clos, "T_examining_report_time_interval")
+
+			}
+		}
+
+		// 通知 报告人员
+		_, company_r := Account.Read_User_ByT_uuid(r.T_uuid)
+		System.Add_News(r.T_delivery, fmt.Sprintf("【%s-%s】检测报告 已提交", company_r.T_name, r.T_name), "")
+		go wx.WxSend(r.T_delivery, fmt.Sprintf("【%s-%s】检测报告 已提交", company_r.T_name, r.T_name))
+	}
+	if len(T_pdf6) > 0 {
+		r.T_pdf6 = T_pdf6
+		clos = append(clos, "T_pdf6")
+		r.T_examining_report_state = 1
+		clos = append(clos, "T_original_record_state")
+		// 添加已提交状态 原始记录 记录
+		auditRecordJson, err := Task.Add_AuditRecord(r.T_original_record_audit_record, "", User_r.T_uuid, r.T_original_record_state, "", "")
+		if err == nil {
+			r.T_original_record_audit_record = auditRecordJson
+			clos = append(clos, "T_original_record_audit_record")
+			r.T_original_record_end_time = time.Now().Format("2006-01-02 15:04:05")
+			clos = append(clos, "T_original_record_end_time")
+			if len(r.T_reporting_start_time) > 0 {
+				r.T_original_record_time_interval, _ = lib.MinutesDifference(r.T_original_record_start_time, r.T_original_record_end_time)
+				clos = append(clos, "T_original_record_time_interval")
+				// 扣除暂停时间
+				Task_Compute := Task.Read_TaskTime_Compute(r.T_task_id, 2)
+				if Task_Compute > 0 {
+					r.T_original_record_time_interval -= float64(Task_Compute)
+				}
+				clos = append(clos, "T_original_record_time_interval")
+
+			}
+		}
+
+		// 通知 报告人员
+		_, company_r := Account.Read_User_ByT_uuid(r.T_uuid)
+		System.Add_News(r.T_delivery, fmt.Sprintf("【%s-%s】原始记录 已提交", company_r.T_name, r.T_name), "")
+		go wx.WxSend(r.T_delivery, fmt.Sprintf("【%s-%s】原始记录 已提交", company_r.T_name, r.T_name))
+	}
 
 	if len(T_VerifyDeviceDataStartTime) > 0 {
 		r.T_VerifyDeviceDataStartTime = T_VerifyDeviceDataStartTime
@@ -1369,6 +1434,9 @@ func (c *TaskController) Up() {
 		clos = append(clos, "T_device_quantity")
 	}
 
+	r.T_cnas = T_cnas
+	clos = append(clos, "T_cnas")
+
 	if !Task.Update_Task(r, clos...) {
 		c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败!"}
 		c.ServeJSON()
@@ -1665,6 +1733,218 @@ func (c *TaskController) UpReportingState() {
 	return
 }
 
+// 修改检测报告状态
+func (c *TaskController) UpExaminingReportState() {
+	Admin_r, Admin_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
+
+	User_r, User_is := Account.Verification(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
+	if !Admin_is && !User_is {
+		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
+		c.ServeJSON()
+		return
+	}
+	operate_uuid := ""
+	if Admin_is {
+		operate_uuid = Admin_r.T_uuid
+	}
+	if User_is {
+		operate_uuid = User_r.T_uuid
+	}
+
+	T_examining_report_state, _ := c.GetInt("T_examining_report_state") // 1 已完成(客户通过) 5已退回(客户) 3已通过(报告负责人) 4已退回(报告负责人)
+	T_reason := c.GetString("T_reason")                                 // 退回原因
+	T_signature := c.GetString("T_signature")                           // 通过后客户签名图片链接
+
+	T_task_id := c.GetString("T_task_id")
+	r, is := Task.Read_Task(T_task_id)
+	if !is {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "Id 错误!"}
+		c.ServeJSON()
+		return
+	}
+	_, company_r := Account.Read_User_ByT_uuid(r.T_uuid)
+
+	clos := make([]string, 0)
+	if T_examining_report_state > 0 {
+		r.T_examining_report_state = T_examining_report_state
+		clos = append(clos, "T_examining_report_state")
+	}
+	if len(T_signature) > 0 {
+		r.T_examining_report_signature = T_signature
+		clos = append(clos, "T_examining_report_signature")
+	}
+
+	if T_examining_report_state == Task.TaskExaminingReportStateClientReturn || T_examining_report_state == Task.TaskExaminingReportStateReturn {
+		r.T_examining_report_return_times += 1
+		clos = append(clos, "T_examining_report_return_times")
+		// 客户退回时新增驳回次数和驳回记录
+		if T_examining_report_state == Task.TaskExaminingReportStateClientReturn {
+			r.T_reject_times += 1
+			var rejectRecordList []Task.AuditRecord
+			if len(r.T_reject_record) > 0 {
+				err := json.Unmarshal([]byte(r.T_reject_record), &rejectRecordList)
+				if err != nil {
+					logs.Error("JSON 反序列化失败:", err)
+					return
+				}
+			}
+
+			rejectRecordList = append(rejectRecordList, Task.AuditRecord{
+				T_uuid:   User_r.T_uuid,
+				T_state:  T_examining_report_state,
+				T_reason: T_reason,
+				T_time:   time.Now().Format("2006-01-02 15:04:05"),
+				T_type:   "examining_report",
+			})
+			rejectRecordJson, err := json.Marshal(rejectRecordList)
+			if err != nil {
+				logs.Error("JSON 反序列化失败:", err)
+				return
+			}
+			r.T_reject_record = string(rejectRecordJson)
+			clos = append(clos, "T_reject_times")
+			clos = append(clos, "T_reject_record")
+		}
+
+	}
+
+	auditRecordJson, err := Task.Add_AuditRecord(r.T_examining_report_audit_record, User_r.T_uuid, Admin_r.T_uuid, T_examining_report_state, T_reason, "")
+	if err != nil {
+		return
+	}
+	r.T_examining_report_audit_record = auditRecordJson
+	clos = append(clos, "T_examining_report_audit_record")
+
+	if !Task.Update_Task(r, clos...) {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	// 已提交
+	if T_examining_report_state == Task.TaskExaminingReportStateSubmitted {
+		System.Add_News(r.T_collection, fmt.Sprintf("【%s-%s】检测报告 %s,请尽快与客户沟通确定", company_r.T_name, r.T_name, Task.TaskExaminingReportStateMap[T_examining_report_state]), "")
+		go wx.WxSend(r.T_collection, fmt.Sprintf("【%s-%s】检测报告 %s,请尽快与客户沟通确定", company_r.T_name, r.T_name, Task.TaskExaminingReportStateMap[T_examining_report_state]))
+	}
+
+	// 已通过
+	if T_examining_report_state == Task.TaskExaminingReportStatePass {
+		infoCollection, _ := InfoCollection.Read_InfoCollection(r.T_InfoCollection_id)
+		System.Add_News(infoCollection.T_submit_uuid, fmt.Sprintf("【%s-%s】检测报告 %s,请尽快与客户沟通确定", company_r.T_name, r.T_name, Task.TaskExaminingReportStateMap[T_examining_report_state]), "")
+		go wx.WxSend(infoCollection.T_submit_uuid, fmt.Sprintf("【%s-%s】检测报告 %s,请尽快与客户沟通确定", company_r.T_name, r.T_name, Task.TaskExaminingReportStateMap[T_examining_report_state]))
+	}
+
+	// 已退回(负责人)
+	if T_examining_report_state == Task.TaskExaminingReportStateReturn {
+		System.Add_News(r.T_scheme, fmt.Sprintf("【%s-%s】检测报告 %s,%s", company_r.T_name, r.T_name, Task.TaskExaminingReportStateMap[T_examining_report_state], T_reason), "")
+		go wx.WxSend(r.T_scheme, fmt.Sprintf("【%s-%s】检测报告 %s,%s", company_r.T_name, r.T_name, Task.TaskExaminingReportStateMap[T_examining_report_state], T_reason))
+	}
+
+	//  已退回(客户)
+	if T_examining_report_state == Task.TaskExaminingReportStateClientReturn {
+		System.Add_News(r.T_scheme, fmt.Sprintf("!!!【%s-%s】检测报告 %s,%s", company_r.T_name, r.T_name, Task.TaskExaminingReportStateMap[T_examining_report_state], T_reason), "")
+		go wx.WxSend(r.T_scheme, fmt.Sprintf("!!!【%s-%s】检测报告 %s,%s", company_r.T_name, r.T_name, Task.TaskExaminingReportStateMap[T_examining_report_state], T_reason))
+
+		System.Add_News(conf.VdelUuid, fmt.Sprintf("!!!【%s-%s】检测报告 %s,%s", company_r.T_name, r.T_name, Task.TaskExaminingReportStateMap[T_examining_report_state], T_reason), "")
+		go wx.WxSend(conf.VdelUuid, fmt.Sprintf("!!!【%s-%s】检测报告 %s,%s", company_r.T_name, r.T_name, Task.TaskExaminingReportStateMap[T_examining_report_state], T_reason))
+
+		go wx.WxSend(conf.BoosUuid, fmt.Sprintf("!!!【%s-%s】检测报告 %s,%s", company_r.T_name, r.T_name, Task.TaskExaminingReportStateMap[T_examining_report_state], T_reason))
+	}
+
+	// 添加任务操作日志
+	Task.Add_TaskLogs_T(operate_uuid, T_task_id, "任务管理", "修改检测报告状态", r)
+	System.Add_UserLogs_T(operate_uuid, "任务管理", "修改检测报告状态", r)
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
+	c.ServeJSON()
+	return
+}
+
+// 修改原始数据状态
+func (c *TaskController) UpOriginalRecordState() {
+	Admin_r, Admin_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
+
+	User_r, User_is := Account.Verification(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
+	if !Admin_is && !User_is {
+		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
+		c.ServeJSON()
+		return
+	}
+	operate_uuid := ""
+	if Admin_is {
+		operate_uuid = Admin_r.T_uuid
+	}
+	if User_is {
+		operate_uuid = User_r.T_uuid
+	}
+
+	T_original_record_state, _ := c.GetInt("T_original_record_state") // 1 已完成(客户通过) 5已退回(客户) 3已通过(报告负责人) 4已退回(报告负责人)
+	T_reason := c.GetString("T_reason")                               // 退回原因
+	T_signature := c.GetString("T_signature")                         // 通过后客户签名图片链接
+
+	T_task_id := c.GetString("T_task_id")
+	r, is := Task.Read_Task(T_task_id)
+	if !is {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "Id 错误!"}
+		c.ServeJSON()
+		return
+	}
+	_, company_r := Account.Read_User_ByT_uuid(r.T_uuid)
+
+	clos := make([]string, 0)
+	if T_original_record_state > 0 {
+		r.T_original_record_state = T_original_record_state
+		clos = append(clos, "T_original_record_state")
+	}
+	if len(T_signature) > 0 {
+		r.T_original_record_signature = T_signature
+		clos = append(clos, "T_original_record_signature")
+	}
+
+	if T_original_record_state == Task.TaskOriginalRecordStateReturn {
+		r.T_original_record_return_times += 1
+		clos = append(clos, "T_original_record_return_times")
+	}
+
+	auditRecordJson, err := Task.Add_AuditRecord(r.T_original_record_audit_record, User_r.T_uuid, Admin_r.T_uuid, T_original_record_state, T_reason, "")
+	if err != nil {
+		return
+	}
+	r.T_original_record_audit_record = auditRecordJson
+	clos = append(clos, "T_original_record_audit_record")
+
+	if !Task.Update_Task(r, clos...) {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	// 已提交
+	if T_original_record_state == Task.TaskOriginalRecordStateSubmitted {
+		System.Add_News(r.T_collection, fmt.Sprintf("【%s-%s】原始数据 %s", company_r.T_name, r.T_name, Task.TaskOriginalRecordStateMap[T_original_record_state]), "")
+		go wx.WxSend(r.T_collection, fmt.Sprintf("【%s-%s】原始数据 %s", company_r.T_name, r.T_name, Task.TaskOriginalRecordStateMap[T_original_record_state]))
+	}
+
+	// 已通过
+	if T_original_record_state == Task.TaskOriginalRecordStatePass {
+		infoCollection, _ := InfoCollection.Read_InfoCollection(r.T_InfoCollection_id)
+		System.Add_News(infoCollection.T_submit_uuid, fmt.Sprintf("【%s-%s】原始数据 %s", company_r.T_name, r.T_name, Task.TaskOriginalRecordStateMap[T_original_record_state]), "")
+		go wx.WxSend(infoCollection.T_submit_uuid, fmt.Sprintf("【%s-%s】原始数据 %s", company_r.T_name, r.T_name, Task.TaskOriginalRecordStateMap[T_original_record_state]))
+	}
+
+	// 已退回(负责人)
+	if T_original_record_state == Task.TaskOriginalRecordStateReturn {
+		System.Add_News(r.T_scheme, fmt.Sprintf("【%s-%s】原始数据 %s,%s", company_r.T_name, r.T_name, Task.TaskOriginalRecordStateMap[T_original_record_state], T_reason), "")
+		go wx.WxSend(r.T_scheme, fmt.Sprintf("【%s-%s】原始数据 %s,%s", company_r.T_name, r.T_name, Task.TaskOriginalRecordStateMap[T_original_record_state], T_reason))
+	}
+
+	// 添加任务操作日志
+	Task.Add_TaskLogs_T(operate_uuid, T_task_id, "任务管理", "修改原始数据状态", r)
+	System.Add_UserLogs_T(operate_uuid, "任务管理", "修改原始数据状态", r)
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
+	c.ServeJSON()
+	return
+}
+
 // 进场  改成 方案开始
 func (c *TaskController) EnterArea() {
 	// 验证登录 User_is, User_r
@@ -1998,6 +2278,22 @@ func (c *TaskController) AuditRecordList() {
 				return
 			}
 		}
+	case "T_examining_report":
+		if len(r.T_examining_report_audit_record) > 0 {
+			err := json.Unmarshal([]byte(r.T_examining_report_audit_record), &auditRecordList)
+			if err != nil {
+				logs.Error("JSON 反序列化失败:", err)
+				return
+			}
+		}
+	case "T_original_record":
+		if len(r.T_original_record_audit_record) > 0 {
+			err := json.Unmarshal([]byte(r.T_original_record_audit_record), &auditRecordList)
+			if err != nil {
+				logs.Error("JSON 反序列化失败:", err)
+				return
+			}
+		}
 	}
 
 	AdminMap := Account.AdminListToMap(Account.Read_Admin_List_ALL_1())
@@ -2259,7 +2555,7 @@ func randomColor(i int) color.RGBA {
 }
 
 // 获取加完水印的pdf
-func GetWatermarkPdf(task Task.Task, pdfURL string, flag string) (pdf string) {
+func GetWatermarkPdf_command(task Task.Task, pdfURL string, flag string) (pdf string) {
 	if len(pdfURL) == 0 {
 		return
 	}
@@ -2304,6 +2600,95 @@ func GetWatermarkPdf(task Task.Task, pdfURL string, flag string) (pdf string) {
 
 	return
 }
+func GetSignaturePdf_command(task Task.Task, pdfURL string, flag string) (pdf string) {
+	if len(pdfURL) == 0 {
+		return
+	}
+
+	currentDirectory := lib.GetCurrentDirectory()
+	scriptPath := currentDirectory + "/script"
+	pdf_file_out_name := uuid.New().String() + ".pdf"
+	pdfFilename := currentDirectory + "/ofile/" + uuid.New().String() + ".pdf"
+	pdf_file_out := currentDirectory + "/ofile/signature" + pdf_file_out_name
+	signature_img := currentDirectory + "/script/报告专用章.png"
+
+	// 执行Python脚本
+	cmd := exec.Command("python3", "add_signature.py", pdfURL, pdfFilename, signature_img, pdf_file_out)
+	cmd.Dir = scriptPath
+	// 获取命令输出
+	_, err := cmd.CombinedOutput()
+	if err != nil {
+		logs.Error("执行python脚本添加公章错误:", err)
+		return
+	}
+
+	_, err = os.Stat(pdf_file_out)
+	if os.IsNotExist(err) {
+		return ""
+	}
+
+	lib.Pload_qiniu(pdf_file_out, pdf_file_out_name)
+	if !lib.Pload_qiniu(pdf_file_out, pdf_file_out) {
+		err = errors.New("上传水印pdf失败")
+		return
+	}
+	defer func() {
+		os.Remove(pdfFilename)
+		os.Remove(pdf_file_out)
+	}()
+
+	pdf = "https://bzdcoldverifyoss.baozhida.cn/" + pdf_file_out_name
+
+	switch flag {
+	case "T_pdf1":
+		task.T_pdf1_signature = pdf
+		Task.Update_Task(task, "T_pdf1_signature")
+	case "T_pdf2":
+		task.T_pdf2_signature = pdf
+		Task.Update_Task(task, "T_pdf2_signature")
+	}
+
+	return
+}
+
+func GetWatermarkPdf(task Task.Task, pdfURL string, flag string) (pdf string) {
+	if len(pdfURL) == 0 {
+		return
+	}
+
+	// 添加公章 T_pdf5为CNAS实验室 ,不添加公章
+	var signaturePdf, watermarkPdf string
+	var err error
+	if flag != "T_pdf5" {
+		signaturePdf, err = lib.GetSignaturePdf(pdfURL)
+		if err != nil {
+			logs.Error("获取加报告章pdf失败:", err)
+			return
+		}
+	}
+
+	// 添加水印
+	watermarkPdf, err = lib.GetWatermarkPdf(pdfURL)
+	if err != nil {
+		logs.Error("获取加水印pdf失败:", err)
+		return
+	}
+	switch flag {
+	case "T_pdf1":
+		task.T_pdf1_watermark = watermarkPdf
+		task.T_pdf1_signature = signaturePdf
+		Task.Update_Task(task, "T_pdf1_watermark", "T_pdf1_signature")
+	case "T_pdf2":
+		task.T_pdf2_watermark = watermarkPdf
+		task.T_pdf2_signature = signaturePdf
+		Task.Update_Task(task, "T_pdf2_watermark", "T_pdf2_signature")
+	case "T_pdf5":
+		task.T_pdf5_watermark = watermarkPdf
+		Task.Update_Task(task, "T_pdf5_watermark")
+	}
+
+	return
+}
 
 // 暂停申请
 // 列表 -
@@ -2320,7 +2705,7 @@ func (c *TaskController) TaskTimeList() {
 	var r_jsons lib.R_JSONS
 
 	T_task_id := c.GetString("T_task_id")
-	T_task_type, _ := c.GetInt("T_task_type", 0) // 公司名称
+	T_task_type, _ := c.GetInt("T_task_type", 0)
 
 	var cnt int64
 	List, cnt := Task.Read_TaskTime_List(T_task_id, T_task_type)
@@ -2600,7 +2985,7 @@ func (c *TaskController) Copy() {
 		return
 	}
 	var_ := Task.Task{
-		T_Distributor_id:       User_r.T_Distributor_id,
+		T_Distributor_id:       r.T_Distributor_id,
 		T_InfoCollection_id:    r.T_InfoCollection_id,
 		T_InfoTemplate_id:      infoCollection.T_InfoTemplate_id,
 		T_start_time:           infoCollection.T_start_time, // 项目开始时间使用信息采集开始时间
@@ -2632,6 +3017,7 @@ func (c *TaskController) Copy() {
 		T_temp_range:      r.T_temp_range,
 		T_report_type:     r.T_report_type,
 		T_device_quantity: r.T_device_quantity,
+		T_cnas:            r.T_cnas,
 	}
 	var_.T_report_number, _ = Task.GenerateNextT_report_number(var_.T_device_type)
 	T_paste_task_id, is := Task.Add_Task(var_)
@@ -2953,14 +3339,14 @@ func (c *TaskController) TaskData_Stat() {
 
 // SyncPDFWatermark 同步水印
 func (c *TaskController) SyncPDFWatermark() {
-	//List, _ := Task.Read_Task_List_For_Watermark("pdf1")
-	//for _, task := range List {
-	//	GetWatermarkPdf(task, task.T_pdf1, "T_pdf1")
-	//}
-	//List2, _ := Task.Read_Task_List_For_Watermark("pdf2")
-	//for _, task := range List2 {
-	//	GetWatermarkPdf(task, task.T_pdf2, "T_pdf2")
-	//}
+	List, _ := Task.Read_Task_List_For_Watermark("pdf1")
+	for _, task := range List {
+		GetSignaturePdf_command(task, task.T_pdf1, "T_pdf1")
+	}
+	List2, _ := Task.Read_Task_List_For_Watermark("pdf2")
+	for _, task := range List2 {
+		GetSignaturePdf_command(task, task.T_pdf2, "T_pdf2")
+	}
 	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
 	c.ServeJSON()
 	return

+ 9 - 1
controllers/VerifyTemplate.go

@@ -167,6 +167,8 @@ func (c *VerifyTemplateController) Up() {
 	T_marking := c.GetString("T_marking")
 	T_cover := c.GetString("T_cover")
 	T_deploy := c.GetString("T_deploy")
+	T_examining_report := c.GetString("T_examining_report")
+	T_original_record := c.GetString("T_original_record")
 
 	r, is := VerifyTemplate.Read_VerifyTemplate(T_VerifyTemplate_id)
 	if !is {
@@ -194,6 +196,12 @@ func (c *VerifyTemplateController) Up() {
 	if len(T_cover) > 0 {
 		r.T_cover = T_cover
 	}
+	if len(T_examining_report) > 0 {
+		r.T_examining_report = T_examining_report
+	}
+	if len(T_original_record) > 0 {
+		r.T_original_record = T_original_record
+	}
 	if len(T_deploy) > 0 {
 
 		var deployList []VerifyTemplate.VerifyTemplateDeploy
@@ -223,7 +231,7 @@ func (c *VerifyTemplateController) Up() {
 	}
 
 	// .......
-	if !VerifyTemplate.Update_VerifyTemplate(r, "T_name", "T_sort", "T_scheme", "T_reporting", "T_inspect", "T_marking", "T_cover", "T_deploy") {
+	if !VerifyTemplate.Update_VerifyTemplate(r, "T_name", "T_sort", "T_scheme", "T_reporting", "T_inspect", "T_marking", "T_cover", "T_deploy", "T_examining_report", "T_original_record") {
 		c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败!"}
 		c.ServeJSON()
 		return

+ 1 - 1
lib/Qiniu.go

@@ -86,7 +86,7 @@ func UploadToken(T_suffix string) string {
 		//{"key":"` + conf.Oss + `/$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}
 		ForceSaveKey: true,
 		SaveKey:      "UpImage/" + Tokey + "." + T_suffix,
-		FsizeLimit:   1024 * 1024 * 30,
+		FsizeLimit:   1024 * 1024 * 50,
 		MimeLimit:    "image/*;application/pdf",
 	}
 

+ 87 - 1
lib/lib.go

@@ -7,7 +7,9 @@ import (
 	"github.com/beego/beego/v2/core/logs"
 	"github.com/nats-io/nats.go"
 	"github.com/signintech/gopdf"
+	"io"
 	"math/rand"
+	"net/http"
 	"os"
 	"path/filepath"
 	"runtime"
@@ -453,7 +455,8 @@ func ConvertMinutesToDHM(minutes int) string {
 
 	return fmt.Sprintf("%dd%dh%dm", days, hours, remainingMinutes)
 }
-//  判断是否是本月的
+
+// 判断是否是本月的
 func IsInCurrentMonth(dateStr string) (bool, error) {
 	// 定义时间格式
 	layout := "2006-01-02 15:04:05"
@@ -470,3 +473,86 @@ func IsInCurrentMonth(dateStr string) (bool, error) {
 	// 判断年份和月份是否相同
 	return parsedTime.Year() == now.Year() && parsedTime.Month() == now.Month(), nil
 }
+
+func GetWatermarkPdf(pdfURL string) (string, error) {
+	url := conf.PdfProcessingHost + "/add_watermark"
+	method := "POST"
+
+	payload := strings.NewReader(fmt.Sprintf(`{"pdf_url": "%s"}`, pdfURL))
+
+	client := &http.Client{}
+	req, err := http.NewRequest(method, url, payload)
+
+	if err != nil {
+		return "", err
+	}
+	req.Header.Add("Content-Type", "application/json")
+
+	res, err := client.Do(req)
+	if err != nil {
+		return "", err
+	}
+	defer res.Body.Close()
+
+	body, err := io.ReadAll(res.Body)
+	if err != nil {
+		return "", err
+	}
+
+	// 解析JSON响应
+	var result struct {
+		Success         bool   `json:"success"`
+		Error           string `json:"error"`
+		WatermarkPdfURL string `json:"watermark_pdf_url"`
+	}
+
+	if err = json.Unmarshal(body, &result); err != nil {
+		return "", err
+	}
+
+	if !result.Success {
+		return "", fmt.Errorf(result.Error)
+	}
+	return result.WatermarkPdfURL, nil
+}
+func GetSignaturePdf(pdfURL string) (string, error) {
+	url := conf.PdfProcessingHost + "/add_signature"
+	method := "POST"
+
+	payload := strings.NewReader(fmt.Sprintf(`{"pdf_url": "%s"}`, pdfURL))
+
+	client := &http.Client{}
+	req, err := http.NewRequest(method, url, payload)
+
+	if err != nil {
+		return "", err
+	}
+	req.Header.Add("Content-Type", "application/json")
+
+	res, err := client.Do(req)
+	if err != nil {
+		return "", err
+	}
+	defer res.Body.Close()
+
+	body, err := io.ReadAll(res.Body)
+	if err != nil {
+		return "", err
+	}
+
+	// 解析JSON响应
+	var result struct {
+		Success         bool   `json:"success"`
+		Error           string `json:"error"`
+		SignaturePdfURL string `json:"signature_pdf_url"`
+	}
+
+	if err = json.Unmarshal(body, &result); err != nil {
+		return "", err
+	}
+
+	if !result.Success {
+		return "", fmt.Errorf(result.Error)
+	}
+	return result.SignaturePdfURL, nil
+}

+ 10 - 7
models/Account/Admin.go

@@ -9,13 +9,14 @@ import (
 )
 
 type Admin struct {
-	Id       int    `orm:"column(ID);size(11);auto;pk"`
-	T_uuid   string `orm:"size(256);null"`      //
-	T_power  int    `orm:"size(2);;default(0)"` // 权限  0
-	T_name   string `orm:"size(256);null"`      // 姓名
-	T_user   string `orm:"size(256);null"`      // 用户名
-	T_pass   string `orm:"size(256);null"`      // 密码
-	T_wxname string `orm:"size(256);null"`      // 微信name
+	Id              int    `orm:"column(ID);size(11);auto;pk"`
+	T_uuid          string `orm:"size(256);null"`      //
+	T_power         int    `orm:"size(2);;default(0)"` // 权限  0
+	T_name          string `orm:"size(256);null"`      // 姓名
+	T_user          string `orm:"size(256);null"`      // 用户名
+	T_pass          string `orm:"size(256);null"`      // 密码
+	T_wxname        string `orm:"size(256);null"`      // 微信name
+	T_signature_img string `orm:"size(256);null"`      // 签名图片
 
 	T_State          int       `orm:"size(200);default(1)"`                                  //  0删除  1 正常
 	T_Distributor_id string    `orm:"size(256);null"`                                        // 分销商
@@ -31,6 +32,7 @@ type Admin_R struct {
 	T_user           string // 用户名
 	T_wxname         string // 企业微信
 	T_Distributor_id string // 经销商id
+	T_signature_img  string // 签名图片
 }
 
 func (t *Admin) TableName() string {
@@ -50,6 +52,7 @@ func AdminToAdmin_R(T Admin, powerMap map[int]string) (T_r Admin_R) {
 	T_r.T_wxname = T.T_wxname
 	T_r.T_power_name = powerMap[T.T_power]
 	T_r.T_Distributor_id = T.T_Distributor_id
+	T_r.T_signature_img = T.T_signature_img
 	return T_r
 }
 

+ 157 - 80
models/Task/Task.go

@@ -67,6 +67,32 @@ var (
 		TaskReportingStateReturn:       "已退回",
 	}
 
+	TaskExaminingReportStateWaitSubmit   = 0 // 待提交
+	TaskExaminingReportStateSubmitted    = 5 // 已提交
+	TaskExaminingReportStateClientPass   = 1 // 已通过(客户)
+	TaskExaminingReportStateClientReturn = 2 // 已退回(客户)
+	TaskExaminingReportStatePass         = 3 // 已通过
+	TaskExaminingReportStateReturn       = 4 // 已退回
+	TaskExaminingReportStateMap          = map[int]string{
+		TaskExaminingReportStateWaitSubmit:   "待提交",
+		TaskExaminingReportStateSubmitted:    "已提交",
+		TaskExaminingReportStateClientPass:   "已通过(客户)",
+		TaskExaminingReportStateClientReturn: "已驳回(客户)",
+		TaskExaminingReportStatePass:         "已通过",
+		TaskExaminingReportStateReturn:       "已退回",
+	}
+
+	TaskOriginalRecordStateWaitSubmit = 0 // 待提交
+	TaskOriginalRecordStateSubmitted  = 5 // 已提交
+	TaskOriginalRecordStatePass       = 3 // 已通过
+	TaskOriginalRecordStateReturn     = 4 // 已退回
+	TaskOriginalRecordStateMap        = map[int]string{
+		TaskOriginalRecordStateWaitSubmit: "待提交",
+		TaskOriginalRecordStateSubmitted:  "已提交",
+		TaskOriginalRecordStatePass:       "已通过",
+		TaskOriginalRecordStateReturn:     "已退回",
+	}
+
 	TaskDeliveryStateUnfinished = 0 // 未完成
 	TaskDeliveryStateFinished   = 1 // 已完成
 	TaskDeliveryStateGoing      = 2 // 进行中
@@ -142,22 +168,24 @@ type Task struct {
 	T_InfoCollection_id string `orm:"size(256);null"`       // 信息采集ID
 	T_InfoTemplate_id   string `orm:"size(256);null"`       // 信息采集模版ID
 
-	T_task_id              string `orm:"size(256);null"`     // 任务ID
-	T_uuid                 string `orm:"size(256);null"`     // 用户 UUID
-	T_name                 string `orm:"size(256);null"`     // 标题
-	T_VerifyTemplate_class string `orm:"size(256);null"`     // 模版id
-	T_VerifyTemplate_id    string `orm:"size(256);null"`     // 模版id
-	T_deadline             string `orm:"size(256);null"`     // 截止时间
-	T_scheme               string `orm:"size(256);null"`     // 实施方案 负责人UUID
-	T_collection           string `orm:"size(256);null"`     // 数据采集 负责人UUID
-	T_reporting            string `orm:"size(256);null"`     // 报告编写 负责人UUID
-	T_delivery             string `orm:"size(256);null"`     // 交付审核 负责人UUID
-	T_scheme_state         int    `orm:"size(2);default(0)"` // 实施方案 状态 0 未完成 1 已完成(客户通过) 2已退回(客户) 3已通过(负责人) 4已退回(负责人) 5已提交
-	T_collection_state     int    `orm:"size(2);default(0)"` // 数据采集 状态 0 未完成 1 数据来源已完成 2 处理中 3 已采集-无数据 4-数据编辑已完成(已提交) 5已通过(负责人) 6已退回(负责人)
-	T_reporting_state      int    `orm:"size(2);default(0)"` // 报告编写 状态 0 未完成 1 已完成(客户通过) 2已退回(客户) 3已通过(负责人) 4已退回(负责人) 5已提交
-	T_delivery_state       int    `orm:"size(2);default(0)"` // 交付审核 状态 0 未完成 1 已完成 2 处理中
-	T_marking_state        int    `orm:"size(2);default(0)"` // 验证标识 状态 0 未完成 1 已完成
-	T_record               string `orm:"type(text)"`         // 领导备注
+	T_task_id                string `orm:"size(256);null"`     // 任务ID
+	T_uuid                   string `orm:"size(256);null"`     // 用户 UUID
+	T_name                   string `orm:"size(256);null"`     // 标题
+	T_VerifyTemplate_class   string `orm:"size(256);null"`     // 模版id
+	T_VerifyTemplate_id      string `orm:"size(256);null"`     // 模版id
+	T_deadline               string `orm:"size(256);null"`     // 截止时间
+	T_scheme                 string `orm:"size(256);null"`     // 实施方案 负责人UUID
+	T_collection             string `orm:"size(256);null"`     // 数据采集 负责人UUID
+	T_reporting              string `orm:"size(256);null"`     // 报告编写 负责人UUID
+	T_delivery               string `orm:"size(256);null"`     // 交付审核 负责人UUID
+	T_scheme_state           int    `orm:"size(2);default(0)"` // 实施方案 状态 0 未完成 1 已完成(客户通过) 2已退回(客户) 3已通过(负责人) 4已退回(负责人) 5已提交
+	T_collection_state       int    `orm:"size(2);default(0)"` // 数据采集 状态 0 未完成 1 数据来源已完成 2 处理中 3 已采集-无数据 4-数据编辑已完成(已提交) 5已通过(负责人) 6已退回(负责人)
+	T_reporting_state        int    `orm:"size(2);default(0)"` // 报告编写 状态 0 未完成 1 已完成(客户通过) 2已退回(客户) 3已通过(负责人) 4已退回(负责人) 5已提交
+	T_delivery_state         int    `orm:"size(2);default(0)"` // 交付审核 状态 0 未完成 1 已完成 2 处理中
+	T_marking_state          int    `orm:"size(2);default(0)"` // 验证标识 状态 0 未完成 1 已完成
+	T_examining_report_state int    `orm:"size(2);default(0)"` // 检测报告 状态 0 未完成 1 已完成(客户通过) 2已退回(客户) 3已通过(负责人) 4已退回(负责人) 5已提交
+	T_original_record_state  int    `orm:"size(2);default(0)"` // 原始记录 状态 0 未完成 3 已通过(负责人) 4已退回(负责人) 5已提交
+	T_record                 string `orm:"type(text)"`         // 领导备注
 
 	T_VerifyDeviceDataStartTime string `orm:"size(256);null"` // 验证设备数据开始时间
 	T_VerifyDeviceDataEndTime   string `orm:"size(256);null"` // 验证设备数据开始时间
@@ -167,12 +195,17 @@ type Task struct {
 	T_doc1           string `orm:"type(text);null"` // 封面
 	T_pdf1           string `orm:"type(text);null"` // 验证方案
 	T_pdf1_watermark string `orm:"type(text);null"` // 验证方案 带水印
+	T_pdf1_signature string `orm:"type(text);null"` // 验证方案 带公章
 	T_doc2           string `orm:"type(text);null"` // 报告
 	T_pdf2           string `orm:"type(text);null"` // 验证报告
 	T_pdf2_watermark string `orm:"type(text);null"` // 验证报告 带水印
+	T_pdf2_signature string `orm:"type(text);null"` // 验证报告 带公章
 	T_doc3           string `orm:"type(text);null"` // 证书
 	T_pdf3           string `orm:"type(text);null"` // 证书
 	T_pdf4           string `orm:"type(text);null"` // 验证标识
+	T_pdf5           string `orm:"type(text);null"` // 检测报告
+	T_pdf5_watermark string `orm:"type(text);null"` // 检测报告 带水印
+	T_pdf6           string `orm:"type(text);null"` // 原始记录
 
 	T_Show  int `orm:"size(2);default(1)"`   // 0 隐藏   1 公开
 	T_Visit int `orm:"size(200);default(0)"` // 浏览量
@@ -234,51 +267,74 @@ type Task struct {
 	T_reporting_audit_record  string  `orm:"type(text);null"` // 验证报告审核记录
 	T_reporting_pass_time     string  `orm:"size(256);null"`  // 验证报告负责人通过时间
 
-	T_device_quantity int `orm:"size(20);default(0)"` //  终端数量 T_device_type=WZ 必填
+	// 检测报告
+	T_examining_report_start_time    string  `orm:"size(256);null"`  // 检测报告开始时间 接收信息采集表的时间
+	T_examining_report_end_time      string  `orm:"size(256);null"`  // 检测报告结束时间 负责人审核通过前最后一次上传时间
+	T_examining_report_time_interval float64 `orm:"size(256);null"`  // 时间间隔 单位分钟
+	T_examining_report_signature     string  `orm:"type(text)"`      // 检测报告客户签字确认图片
+	T_examining_report_return_times  int     `orm:"size(256);null"`  // 检测报告退回次数
+	T_examining_report_audit_record  string  `orm:"type(text);null"` // 检测报告审核记录
+
+	// 原始记录
+	T_original_record_start_time    string  `orm:"size(256);null"`  // 原始记录开始时间 接收信息采集表的时间
+	T_original_record_end_time      string  `orm:"size(256);null"`  // 原始记录结束时间 负责人审核通过前最后一次上传时间
+	T_original_record_time_interval float64 `orm:"size(256);null"`  // 时间间隔 单位分钟
+	T_original_record_signature     string  `orm:"type(text)"`      // 原始记录客户签字确认图片
+	T_original_record_return_times  int     `orm:"size(256);null"`  // 原始记录退回次数
+	T_original_record_audit_record  string  `orm:"type(text);null"` // 原始记录审核记录
+
+	T_device_quantity int `orm:"size(20);default(0)"`  //  终端数量 T_device_type=WZ 必填
+	T_cnas            int `orm:"size(256);default(0)"` // 0-否 1-是
 
 	CreateTime time.Time `orm:"column(create_time);type(timestamp);null;auto_now_add"` //auto_now_add 第一次保存时才设置时间
 	UpdateTime time.Time `orm:"column(update_time);type(timestamp);null;auto_now"`     //auto_now 每次 model 保存时都会对时间自动更新
 }
 
 type Task_ struct {
-	Id                     int
-	T_Distributor_id       string    // 信息采集ID
-	T_class                int       // 分类ID
-	T_InfoCollection_id    string    // 信息采集ID
-	T_task_id              string    // 任务ID
-	T_uuid                 string    // 用户 UUID
-	T_user_name            string    // 用户 UUID
-	T_name                 string    // 标题
-	T_VerifyTemplate_class string    // 任务模版id
-	T_VerifyTemplate_id    string    // 任务模版id
-	T_deadline             string    // 截止时间
-	T_scheme               string    // 实施方案 负责人UUID
-	T_collection           string    // 数据采集 负责人UUID
-	T_reporting            string    // 报告编写 负责人UUID
-	T_delivery             string    // 交付审核 负责人UUID
-	T_scheme_state         int       // 实施方案 状态 0 未完成 1 已完成(客户通过) 2已退回(客户) 3已通过(负责人) 4已退回(负责人) 5已提交
-	T_collection_state     int       // 数据采集 状态 0 未完成 1 数据来源已完成 2 处理中 3 已采集-无数据 4-数据编辑已完成(已提交) 5已通过(负责人) 6已退回(负责人)
-	T_reporting_state      int       // 报告编写 状态 0 未完成 1 已完成(客户通过) 2已退回(客户) 3已通过(负责人) 4已退回(负责人) 5已提交
-	T_delivery_state       int       // 交付审核 状态 0 未完成 1 已完成 2 处理中
-	T_marking_state        int       // 验证标识 状态 0 未完成 1 已完成
-	T_scheme_state_str     string    // 实施方案 状态 字符串
-	T_collection_state_str string    // 数据采集 状态 字符串
-	T_reporting_state_str  string    // 报告编写 状态 字符串
-	T_delivery_state_str   string    // 交付审核 状态 字符串
-	T_marking_state_str    string    // 验证标识 状态 字符串
-	T_scheme_name          string    // 实施方案 负责人姓名
-	T_collection_name      string    // 数据采集 负责人姓名
-	T_reporting_name       string    // 报告编写 负责人姓名
-	T_delivery_name        string    // 交付审核 负责人姓名
-	T_VerifyDeviceDataTime [2]string // 验证设备数据开始-结束时间
-	T_BindDeviceDataTime   [2]string // 绑定设备数据开始-结束时间
-	T_doc1                 string    // 封面
-	T_pdf1                 string    // 验证方案
-	T_doc2                 string    // 报告
-	T_pdf2                 string    // 报告
-	T_doc3                 string    // 证书
-	T_pdf3                 string    // 证书
-	T_pdf4                 string    // 验证标识
+	Id                       int
+	T_Distributor_id         string // 信息采集ID
+	T_class                  int    // 分类ID
+	T_InfoCollection_id      string // 信息采集ID
+	T_task_id                string // 任务ID
+	T_uuid                   string // 用户 UUID
+	T_user_name              string // 用户 UUID
+	T_name                   string // 标题
+	T_VerifyTemplate_class   string // 任务模版id
+	T_VerifyTemplate_id      string // 任务模版id
+	T_deadline               string // 截止时间
+	T_scheme                 string // 实施方案 负责人UUID
+	T_collection             string // 数据采集 负责人UUID
+	T_reporting              string // 报告编写 负责人UUID
+	T_delivery               string // 交付审核 负责人UUID
+	T_scheme_state           int    // 实施方案 状态 0 未完成 1 已完成(客户通过) 2已退回(客户) 3已通过(负责人) 4已退回(负责人) 5已提交
+	T_collection_state       int    // 数据采集 状态 0 未完成 1 数据来源已完成 2 处理中 3 已采集-无数据 4-数据编辑已完成(已提交) 5已通过(负责人) 6已退回(负责人)
+	T_reporting_state        int    // 报告编写 状态 0 未完成 1 已完成(客户通过) 2已退回(客户) 3已通过(负责人) 4已退回(负责人) 5已提交
+	T_delivery_state         int    // 交付审核 状态 0 未完成 1 已完成 2 处理中
+	T_marking_state          int    // 验证标识 状态 0 未完成 1 已完成
+	T_examining_report_state int    // 检测报告 状态 0 未完成 1 已完成(客户通过) 2已退回(客户) 3已通过(负责人) 4已退回(负责人) 5已提交
+	T_original_record_state  int    // 原始记录 状态 0 未完成 3 已通过(负责人) 4已退回(负责人) 5已提交
+
+	T_scheme_state_str           string    // 实施方案 状态 字符串
+	T_collection_state_str       string    // 数据采集 状态 字符串
+	T_reporting_state_str        string    // 报告编写 状态 字符串
+	T_delivery_state_str         string    // 交付审核 状态 字符串
+	T_marking_state_str          string    // 验证标识 状态 字符串
+	T_examining_report_state_str string    // 检测报告 状态 字符串
+	T_original_record_state_str  string    // 原始记录 状态 字符串
+	T_scheme_name                string    // 实施方案 负责人姓名
+	T_collection_name            string    // 数据采集 负责人姓名
+	T_reporting_name             string    // 报告编写 负责人姓名
+	T_delivery_name              string    // 交付审核 负责人姓名
+	T_VerifyDeviceDataTime       [2]string // 验证设备数据开始-结束时间
+	T_BindDeviceDataTime         [2]string // 绑定设备数据开始-结束时间
+	T_doc1                       string    // 封面
+	T_pdf1                       string    // 验证方案
+	T_doc2                       string    // 报告
+	T_pdf2                       string    // 报告
+	T_doc3                       string    // 证书
+	T_pdf3                       string    // 证书
+	T_pdf4                       string    // 验证标识
+	T_pdf5                       string    // 检测报告
 
 	T_Show                      int    // 0 公开 1 隐藏
 	T_Visit                     int    // 浏览量
@@ -302,6 +358,8 @@ type Task_ struct {
 	T_reporting_pass_time string
 
 	T_device_quantity int
+	T_cnas            int // cnas实验室
+
 }
 
 type Task_Stat struct {
@@ -311,31 +369,33 @@ type Task_Stat struct {
 	T_InfoCollection_id string // 信息采集ID
 	T_InfoTemplate_id   string // 信息采集模版ID
 
-	T_task_id              string // 任务ID
-	T_uuid                 string // 用户 UUID
-	T_user_name            string // 用户 UUID
-	T_name                 string // 标题
-	T_VerifyTemplate_class string // 任务模版id
-	T_VerifyTemplate_id    string // 任务模版id
-	T_deadline             string // 截止时间
-	T_scheme               string // 实施方案 负责人UUID
-	T_collection           string // 数据采集 负责人UUID
-	T_reporting            string // 报告编写 负责人UUID
-	T_delivery             string // 交付审核 负责人UUID
-	T_scheme_state         int    // 实施方案 状态 0 未完成 1 已完成(客户通过) 2已退回(客户) 3已通过(负责人) 4已退回(负责人) 5已提交
-	T_collection_state     int    // 数据采集 状态 0 未完成 1 数据来源已完成 2 处理中 3 已采集-无数据 4-数据编辑已完成(已提交) 5已通过(负责人) 6已退回(负责人)
-	T_reporting_state      int    // 报告编写 状态 0 未完成 1 已完成(客户通过) 2已退回(客户) 3已通过(负责人) 4已退回(负责人) 5已提交
-	T_delivery_state       int    // 交付审核 状态 0 未完成 1 已完成 2 处理中
-	T_marking_state        int    // 验证标识 状态 0 未完成 1 已完成
-	T_scheme_state_str     string // 实施方案 状态 字符串
-	T_collection_state_str string // 数据采集 状态 字符串
-	T_reporting_state_str  string // 报告编写 状态 字符串
-	T_delivery_state_str   string // 交付审核 状态 字符串
-	T_marking_state_str    string // 验证标识 状态 字符串
-	T_scheme_name          string // 实施方案 负责人姓名
-	T_collection_name      string // 数据采集 负责人姓名
-	T_reporting_name       string // 报告编写 负责人姓名
-	T_delivery_name        string // 交付审核 负责人姓名
+	T_task_id                    string // 任务ID
+	T_uuid                       string // 用户 UUID
+	T_user_name                  string // 用户 UUID
+	T_name                       string // 标题
+	T_VerifyTemplate_class       string // 任务模版id
+	T_VerifyTemplate_id          string // 任务模版id
+	T_deadline                   string // 截止时间
+	T_scheme                     string // 实施方案 负责人UUID
+	T_collection                 string // 数据采集 负责人UUID
+	T_reporting                  string // 报告编写 负责人UUID
+	T_delivery                   string // 交付审核 负责人UUID
+	T_scheme_state               int    // 实施方案 状态 0 未完成 1 已完成(客户通过) 2已退回(客户) 3已通过(负责人) 4已退回(负责人) 5已提交
+	T_collection_state           int    // 数据采集 状态 0 未完成 1 数据来源已完成 2 处理中 3 已采集-无数据 4-数据编辑已完成(已提交) 5已通过(负责人) 6已退回(负责人)
+	T_reporting_state            int    // 报告编写 状态 0 未完成 1 已完成(客户通过) 2已退回(客户) 3已通过(负责人) 4已退回(负责人) 5已提交
+	T_delivery_state             int    // 交付审核 状态 0 未完成 1 已完成 2 处理中
+	T_marking_state              int    // 验证标识 状态 0 未完成 1 已完成
+	T_scheme_state_str           string // 实施方案 状态 字符串
+	T_collection_state_str       string // 数据采集 状态 字符串
+	T_reporting_state_str        string // 报告编写 状态 字符串
+	T_delivery_state_str         string // 交付审核 状态 字符串
+	T_marking_state_str          string // 验证标识 状态 字符串
+	T_examining_report_state_str string // 检测报告 状态 字符串
+	T_original_record_state_str  string // 原始记录 状态 字符串
+	T_scheme_name                string // 实施方案 负责人姓名
+	T_collection_name            string // 数据采集 负责人姓名
+	T_reporting_name             string // 报告编写 负责人姓名
+	T_delivery_name              string // 交付审核 负责人姓名
 
 	T_VerifyDeviceDataTime [2]string // 验证设备数据开始-结束时间
 	T_BindDeviceDataTime   [2]string // 绑定设备数据开始-结束时间
@@ -407,6 +467,8 @@ type Task_Stat struct {
 	T_record string //
 
 	T_device_quantity int
+	T_cnas            int // cnas实验室
+
 }
 
 func (t *Task) TableName() string {
@@ -463,6 +525,8 @@ func TaskToTask_(T Task, userMap, adminMap map[string]string) (T_ Task_) {
 	T_.T_reporting_state_str = TaskReportingStateMap[T.T_reporting_state]
 	T_.T_delivery_state_str = TaskDeliveryStateMap[T.T_delivery_state]
 	T_.T_marking_state_str = TaskMarkingStateMap[T.T_marking_state]
+	T_.T_examining_report_state_str = TaskExaminingReportStateMap[T.T_examining_report_state]
+	T_.T_original_record_state_str = TaskOriginalRecordStateMap[T.T_original_record_state]
 	T_.T_scheme_name = adminMap[T.T_scheme]
 	T_.T_collection_name = adminMap[T.T_collection]
 	T_.T_reporting_name = adminMap[T.T_reporting]
@@ -476,13 +540,22 @@ func TaskToTask_(T Task, userMap, adminMap map[string]string) (T_ Task_) {
 	T_.T_pdf1 = T.T_pdf1_watermark
 	if T_.InfoCollection.T_status == InfoCollection.InfoCollectionStatusReturnedMoney || len(T.T_InfoCollection_id) == 0 || len(T.T_pdf1_watermark) == 0 {
 		T_.T_pdf1 = T.T_pdf1
+		if len(T.T_pdf1_signature) > 0 {
+			T_.T_pdf1 = T.T_pdf1_signature
+		}
 	}
 	T_.T_pdf2 = T.T_pdf2_watermark
 	if T_.InfoCollection.T_status == InfoCollection.InfoCollectionStatusReturnedMoney || len(T.T_InfoCollection_id) == 0 || len(T.T_pdf2_watermark) == 0 {
 		T_.T_pdf2 = T.T_pdf2
+		if len(T.T_pdf1_signature) > 0 {
+			T_.T_pdf2 = T.T_pdf2_signature
+		}
 	}
 	T_.T_pdf3 = T.T_pdf3
 	T_.T_pdf4 = T.T_pdf4
+	T_.T_pdf5 = T.T_pdf5_watermark
+	if T_.InfoCollection.T_status == InfoCollection.InfoCollectionStatusReturnedMoney || len(T.T_InfoCollection_id) == 0 || len(T.T_pdf2_watermark) == 0 {
+	}
 	T_.T_Show = T.T_Show
 	T_.T_Visit = T.T_Visit
 	T_.T_State = T.T_State
@@ -495,6 +568,7 @@ func TaskToTask_(T Task, userMap, adminMap map[string]string) (T_ Task_) {
 	T_.T_verify_type = T.T_verify_type
 	T_.T_reporting_pass_time = T.T_reporting_pass_time
 	T_.T_device_quantity = T.T_device_quantity
+	T_.T_cnas = T.T_cnas
 
 	return T_
 }
@@ -529,6 +603,8 @@ func TaskToTask_Stat(T Task, userMap, adminMap map[string]string) (T_ Task_Stat)
 	T_.T_reporting_state_str = TaskReportingStateMap[T.T_reporting_state]
 	T_.T_delivery_state_str = TaskDeliveryStateMap[T.T_delivery_state]
 	T_.T_marking_state_str = TaskMarkingStateMap[T.T_marking_state]
+	T_.T_examining_report_state_str = TaskExaminingReportStateMap[T.T_examining_report_state]
+	T_.T_original_record_state_str = TaskOriginalRecordStateMap[T.T_original_record_state]
 
 	T_.T_project_name = adminMap[T.T_project]
 	T_.T_scheme_name = adminMap[T.T_scheme]
@@ -626,6 +702,7 @@ func TaskToTask_Stat(T Task, userMap, adminMap map[string]string) (T_ Task_Stat)
 	T_.T_reporting_audit_record = T.T_reporting_audit_record
 	T_.T_record = T.T_record
 	T_.T_device_quantity = T.T_device_quantity
+	T_.T_cnas = T.T_cnas
 
 	return T_
 }

+ 2 - 2
models/Task/TaskTime.go

@@ -15,7 +15,7 @@ type TaskTime struct {
 	Id int `orm:"column(ID);size(11);auto;pk"`
 
 	T_task_id    string `orm:"size(256);"`     // 任务ID
-	T_task_type  int    `orm:"size(256);"`     // 任务类型 方案0 实施1 报告2
+	T_task_type  int    `orm:"size(256);"`     // 任务类型 方案0 实施1 报告2 检测报告3 原始记录4
 	T_uuid       string `orm:"size(256);null"` // 用户 UUID
 	T_start_time string `orm:"size(256);null"` // 开始时间
 	T_end_time   string `orm:"size(256);null"` // 结束时间
@@ -38,7 +38,7 @@ func init() {
 type TaskTime_R struct {
 	Id           int
 	T_task_id    string // 任务ID
-	T_task_type  int    // 任务类型 方案0 实施1 报告2
+	T_task_type  int    // 任务类型 方案0 实施1 报告2 检测报告3 原始记录4
 	T_uuid       string // 用户 UUID
 	T_uuid_name  string // 用户 UUID
 	T_start_time string // 开始时间

+ 18 - 12
models/VerifyTemplate/VerifyTemplate.go

@@ -20,11 +20,13 @@ type VerifyTemplate struct {
 	T_name              string `orm:"size(256);null"`     // 标题
 	T_sort              int    `orm:"size(2);default(1)"` // 排
 
-	T_scheme    string `orm:"size(256);null"` // 方案模版
-	T_reporting string `orm:"size(256);null"` // 报告模版
-	T_marking   string `orm:"size(256);null"` // 标识模版
-	T_inspect   string `orm:"size(256);null"` // 自检
-	T_cover     string `orm:"size(256);null"` // 封面
+	T_scheme           string `orm:"size(256);null"` // 方案模版
+	T_reporting        string `orm:"size(256);null"` // 报告模版
+	T_marking          string `orm:"size(256);null"` // 标识模版
+	T_inspect          string `orm:"size(256);null"` // 自检
+	T_cover            string `orm:"size(256);null"` // 封面
+	T_examining_report string `orm:"size(256);null"` // 检测报告
+	T_original_record  string `orm:"size(256);null"` // 原始记录
 
 	T_deploy string `orm:"type(text);null"` // 布点选项  格式 布点内容1/布点范围1|布点内容2|布点内容3
 
@@ -43,13 +45,15 @@ type VerifyTemplate_R struct {
 	T_name              string `orm:"size(256);null"` // 标题
 	T_sort              int    `orm:"size(200);null"` // 分类
 
-	T_scheme      string                 // 方案模版
-	T_reporting   string                 // 报告模版
-	T_inspect     string                 // 自检
-	T_marking     string                 // 标识模版
-	T_cover       string                 // 封面
-	T_deploy      string                 // 布点选项  格式 布点内容1|布点内容2|布点内容3
-	T_deploy_list []VerifyTemplateDeploy // 布点选项  格式 布点内容1|布点内容2|布点内容3
+	T_scheme           string                 // 方案模版
+	T_reporting        string                 // 报告模版
+	T_inspect          string                 // 自检
+	T_marking          string                 // 标识模版
+	T_cover            string                 // 封面
+	T_examining_report string                 // 检测报告
+	T_original_record  string                 // 原始记录
+	T_deploy           string                 // 布点选项  格式 布点内容1|布点内容2|布点内容3
+	T_deploy_list      []VerifyTemplateDeploy // 布点选项  格式 布点内容1|布点内容2|布点内容3
 }
 
 func (t *VerifyTemplate) TableName() string {
@@ -73,6 +77,8 @@ func VerifyTemplateToVerifyTemplate_R(T VerifyTemplate) (T_r VerifyTemplate_R) {
 	T_r.T_inspect = T.T_inspect
 	T_r.T_marking = T.T_marking
 	T_r.T_cover = T.T_cover
+	T_r.T_original_record = T.T_examining_report
+	T_r.T_original_record = T.T_original_record
 	var deployList []VerifyTemplateDeploy
 	if len(T.T_deploy) > 0 {
 		if strings.Contains(strings.Trim(T.T_deploy, "|"), "|") {

+ 27 - 7
models/VerifyTemplate/VerifyTemplateMap.go

@@ -17,7 +17,7 @@ type VerifyTemplateMap struct {
 	T_id                string `orm:"index,size(256);null"` //
 	T_VerifyTemplate_id string `orm:"size(256);null"`       // 验证模版id
 	T_label             int    `orm:"size(2);default(1)"`   // 数据类型
-	T_source            int    `orm:"size(2);default(0)"`   // 来源 0-所有 1-方案 2-报告 3-表单
+	T_source            int    `orm:"size(2);default(0)"`   // 来源 0-所有 1-方案 2-报告 3-表单(包含报告) 4-验证标识 5-检测报告 6-原始记录 7-方案/报告 8-实验室(检测报告,原始记录)
 
 	//1:文本
 	//2:数值
@@ -200,18 +200,38 @@ func Read_VerifyTemplateMap_List(T_VerifyTemplate_id string, T_sort, T_flow_sort
 	return VerifyTemplateMap_r, cnt
 }
 
+// 0-所有
+// 1-方案
+// 2-报告
+// 3-表单(包含报告)
+// 4-验证标识
+// 5-检测报告
+// 6-原始记录
+// 7-方案/报告
+// 8-实验室(检测报告,原始记录)
+// 1-方案 0,1,7
+// 2-报告 0,2,3,7
+// 3-表单 3
+// 4-检测报告 0,5,8
+// 5-原始记录 0,6,8
 func Read_VerifyTemplateMap_List_For_Data(T_VerifyTemplate_id string, T_source, T_flow int) []VerifyTemplateMap {
 
 	o := orm.NewOrm()
 	// 也可以直接使用 Model 结构体作为表名
 	var r []VerifyTemplateMap
 	qs := o.QueryTable(new(VerifyTemplateMap))
-	source := []int{T_source}
-	if T_source == 2 {
-		source = append(source, 3)
-	}
-	if T_source != 3 {
-		source = append(source, 0)
+	var source []int
+	switch T_source {
+	case 1:
+		source = []int{0, 1, 7}
+	case 2:
+		source = []int{0, 2, 3, 7}
+	case 3:
+		source = []int{3}
+	case 4:
+		source = []int{0, 5, 8}
+	case 5:
+		source = []int{0, 6, 8}
 	}
 
 	cond := orm.NewCondition()

+ 2 - 2
models/VerifyTemplate/VerifyTemplateMapDataHistory.go

@@ -178,8 +178,8 @@ func Read_VerifyTemplateMapDataHistory_History_List(T_task_id string, T_source i
 	o := orm.NewOrm()
 
 	var pl_lists []VerifyTemplateMapDataHistory_History_List_Res
-	//_, err := o.Raw("SELECT DISTINCT t_uuid,t_time FROM verify_template_map_data_history where t_task_id = ? and t_submit_source = ? order by t_time desc LIMIT 0,1000 ", T_task_id, T_source).
-	_, err := o.Raw("SELECT DISTINCT t_uuid,t_time FROM verify_template_map_data_history where t_task_id = ? order by t_time desc LIMIT 0,1000 ", T_task_id, T_source).
+	//_, err := o.Raw("SELECT DISTINCT t_uuid,t_time FROM verify_template_map_data_history where t_task_id = ? and t_source = ? order by t_time desc LIMIT 0,1000 ", T_task_id, T_source).
+	_, err := o.Raw("SELECT DISTINCT t_uuid,t_time FROM verify_template_map_data_history where t_task_id = ? order by t_time desc LIMIT 0,1000 ", T_task_id).
 		QueryRows(&pl_lists)
 	if err != nil {
 		logs.Error(lib.FuncName(), err)

+ 24 - 22
routers/Task.go

@@ -9,28 +9,30 @@ func init() {
 
 	beego.Router("/UpFileToken", &controllers.UpFileController{}, "*:ConfigUpFileToken") // 上传文件
 
-	beego.Router("/Task/List", &controllers.TaskController{}, "*:List")                                   // 任务列表
-	beego.Router("/Task/Get", &controllers.TaskController{}, "*:Get")                                     // 获取任务
-	beego.Router("/Task/Add", &controllers.TaskController{}, "*:Add")                                     // 添加任务
-	beego.Router("/Task/Up", &controllers.TaskController{}, "*:Up")                                       // 编辑任务
-	beego.Router("/Task/Del", &controllers.TaskController{}, "*:Del")                                     // 删除任务
-	beego.Router("/Task/Copy", &controllers.TaskController{}, "*:Copy")                                   // 复制任务
-	beego.Router("/Task/UpCollectionState", &controllers.TaskController{}, "*:UpCollectionState")         // 修改任务状态
-	beego.Router("/Task/UpDeliveryState", &controllers.TaskController{}, "*:UpDeliveryState")             // 修改交付审核状态
-	beego.Router("/Task/AddData_Tool", &controllers.TaskController{}, "*:AddData_Tool")                   // 1.0 添加任务数据
-	beego.Router("/Task/ReceiptInfoCollection", &controllers.TaskController{}, "*:ReceiptInfoCollection") // 接收信息采集
-	beego.Router("/Task/SyncInfoCollection", &controllers.TaskController{}, "*:SyncInfoCollection")       // 同步信息采集
-	beego.Router("/Task/UpSchemeState", &controllers.TaskController{}, "*:UpSchemeState")                 // 修改验证方案状态
-	beego.Router("/Task/EnterArea", &controllers.TaskController{}, "*:EnterArea")                         // 进场
-	beego.Router("/Task/StartVerify", &controllers.TaskController{}, "*:StartVerify")                     // 开始验证-实施开始时间
-	beego.Router("/Task/UpReportingState", &controllers.TaskController{}, "*:UpReportingState")           // 修改验证报告状态
-	beego.Router("/Task/AuditRecordList", &controllers.TaskController{}, "*:AuditRecordList")             // 审核记录
-	beego.Router("/Task/GetTaskUserList", &controllers.TaskController{}, "*:GetTaskUserList")             // 获取任务负责人列表
-	beego.Router("/Task/Stat", &controllers.TaskController{}, "*:Stat")                                   // 报告统计
-	beego.Router("/Task/Stat_Excel", &controllers.TaskController{}, "*:Stat_Excel")                       // 报告统计-excel
-	beego.Router("/Task/StatisticalRanking", &controllers.TaskController{}, "*:StatisticalRanking")       // 报告统计-excel
-	beego.Router("/Task/GenT_report_number", &controllers.TaskController{}, "*:GenT_report_number")       // 生成报告编号
-	beego.Router("/Task/SyncPDFWatermark", &controllers.TaskController{}, "*:SyncPDFWatermark")           // 生成报告编号
+	beego.Router("/Task/List", &controllers.TaskController{}, "*:List")                                     // 任务列表
+	beego.Router("/Task/Get", &controllers.TaskController{}, "*:Get")                                       // 获取任务
+	beego.Router("/Task/Add", &controllers.TaskController{}, "*:Add")                                       // 添加任务
+	beego.Router("/Task/Up", &controllers.TaskController{}, "*:Up")                                         // 编辑任务
+	beego.Router("/Task/Del", &controllers.TaskController{}, "*:Del")                                       // 删除任务
+	beego.Router("/Task/Copy", &controllers.TaskController{}, "*:Copy")                                     // 复制任务
+	beego.Router("/Task/UpCollectionState", &controllers.TaskController{}, "*:UpCollectionState")           // 修改任务状态
+	beego.Router("/Task/UpDeliveryState", &controllers.TaskController{}, "*:UpDeliveryState")               // 修改交付审核状态
+	beego.Router("/Task/UpExaminingReportState", &controllers.TaskController{}, "*:UpExaminingReportState") // 修改交付审核状态
+	beego.Router("/Task/UpOriginalRecordState", &controllers.TaskController{}, "*:UpOriginalRecordState")   // 修改交付审核状态
+	beego.Router("/Task/AddData_Tool", &controllers.TaskController{}, "*:AddData_Tool")                     // 1.0 添加任务数据
+	beego.Router("/Task/ReceiptInfoCollection", &controllers.TaskController{}, "*:ReceiptInfoCollection")   // 接收信息采集
+	beego.Router("/Task/SyncInfoCollection", &controllers.TaskController{}, "*:SyncInfoCollection")         // 同步信息采集
+	beego.Router("/Task/UpSchemeState", &controllers.TaskController{}, "*:UpSchemeState")                   // 修改验证方案状态
+	beego.Router("/Task/EnterArea", &controllers.TaskController{}, "*:EnterArea")                           // 进场
+	beego.Router("/Task/StartVerify", &controllers.TaskController{}, "*:StartVerify")                       // 开始验证-实施开始时间
+	beego.Router("/Task/UpReportingState", &controllers.TaskController{}, "*:UpReportingState")             // 修改验证报告状态
+	beego.Router("/Task/AuditRecordList", &controllers.TaskController{}, "*:AuditRecordList")               // 审核记录
+	beego.Router("/Task/GetTaskUserList", &controllers.TaskController{}, "*:GetTaskUserList")               // 获取任务负责人列表
+	beego.Router("/Task/Stat", &controllers.TaskController{}, "*:Stat")                                     // 报告统计
+	beego.Router("/Task/Stat_Excel", &controllers.TaskController{}, "*:Stat_Excel")                         // 报告统计-excel
+	beego.Router("/Task/StatisticalRanking", &controllers.TaskController{}, "*:StatisticalRanking")         // 报告统计-excel
+	beego.Router("/Task/GenT_report_number", &controllers.TaskController{}, "*:GenT_report_number")         // 生成报告编号
+	beego.Router("/Task/SyncPDFWatermark", &controllers.TaskController{}, "*:SyncPDFWatermark")             // 生成报告编号
 
 	// 日志
 	beego.Router("/TaskLogs/List", &controllers.TaskController{}, "*:Logs_List")

+ 120 - 0
script/add_signature.py

@@ -0,0 +1,120 @@
+import io
+import logging
+import os
+import sys
+
+import pdfplumber
+import requests
+from PIL import Image
+from PyPDF2 import PdfReader, PdfWriter
+from reportlab.lib.pagesizes import A4
+from reportlab.pdfgen import canvas
+
+# 配置日志
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+
+def find_signature_positions(pdf_path, target_texts=["签字或盖章", "技术支持单位(盖章)"]):
+    """查找所有签名位置"""
+    positions = []
+    with pdfplumber.open(pdf_path) as pdf:
+        for i, page in enumerate(pdf.pages):
+            for word in page.extract_words():
+                for target in target_texts:
+                    if target in word["text"]:
+                        x, y = word["x0"], word["top"]
+                        positions.append((i, int(x), int(y), target))
+                        logger.info(f"找到签名位置: 第{i}页, {target} at ({x}, {y})")
+
+    # 返回结果:所有"签字或盖章"和"技术支持单位(盖章)"的位置
+    if len(positions) == 0 or positions == []:
+        return None
+        # 返回结果:第二个"签字或盖章"和技术支持单位位置
+    result = []
+    if len(positions) >= 2:
+        result.append(positions[1])
+        # 第二个出现的位置(索引1)
+    else:
+        result.append(positions[0])
+
+    return result
+
+
+def add_signature_to_pdf(input_pdf, output_pdf, signature_img, positions, offset_x=30, offset_y=-10):
+    """添加签名到PDF"""
+    reader = PdfReader(input_pdf)
+    writer = PdfWriter()
+    a4_width, a4_height = A4  # (595.2, 841.68)
+    for page_index in range(len(reader.pages)):
+        page = reader.pages[page_index]
+        for pos in positions:
+            if pos[0] == page_index:
+                packet = io.BytesIO()
+                can = canvas.Canvas(packet, pagesize=A4)
+                img = Image.open(signature_img)
+                img_width, img_height = img.size
+                aspect_ratio = img_height / img_width
+                new_width = 43 * (72 / 25.4)  # 40mm ≈ 113.39点
+                new_height = new_width * aspect_ratio
+                x, y = pos[1], a4_height - pos[2]
+                if pos[3] == "技术支持单位(盖章)":
+                    y = y - new_height / 2
+                else:
+                    y = y - new_height / 3 * 2
+                x = max(0, min(x, a4_width - new_width))
+                y = max(0, min(y, a4_height - new_height))
+                can.drawImage(signature_img, x, y, width=new_width, height=new_height, mask='auto')
+                can.save()
+                packet.seek(0)
+                overlay_pdf = PdfReader(packet)
+                page.merge_page(overlay_pdf.pages[0])
+        writer.add_page(page)
+
+    with open(output_pdf, "wb") as f:
+        writer.write(f)
+
+
+def download_file(url, local_filename):
+    """下载文件到临时目录"""
+    with requests.get(url, stream=True) as r:
+        r.raise_for_status()
+        with open(local_filename, 'wb') as f:
+            for chunk in r.iter_content(chunk_size=8192):
+                f.write(chunk)
+    return local_filename
+
+
+def add_signature(url, pdfFilename, signature_img, signature_pdf):
+    """把水印添加到pdf中"""
+
+    # 下载PDF文件
+    local_pdf = download_file(url, pdfFilename)
+    # 查找签名位置(使用默认公章图片)
+    positions = find_signature_positions(local_pdf)
+    if len(positions) == 0:
+        os.remove(local_pdf)
+        return
+
+    # 生成带公章的PDF
+    add_signature_to_pdf(local_pdf, signature_pdf, signature_img, positions)
+
+
+if __name__ == '__main__':
+    if len(sys.argv) < 3:
+        print("Usage: add_watermark.py <url> <pdf_file_in> <signature_img> <signature_pdf>")
+        sys.exit(1)
+
+    pdf_file_url = sys.argv[1]
+    pdfFilename = sys.argv[2]  # 要加水印的文件名
+    signature_img = sys.argv[3]  # 要加水印的文件名
+    signature_pdf = sys.argv[4]  # 加好水印的结果文件
+
+    # name = str(uuid.uuid4()) + ".pdf"
+    # pdf_file_url = "https://bzdcoldverifyoss.baozhida.cn/UpImage/1754036272edee05b2-6032-430c-a39b-c83490764dd9.pdf"
+    # pdfFilename = "/Users/zoie/work/bzd_project/ColdVerify_server/ofile/" + name
+    # signature_img = "/Users/zoie/work/bzd_project/ColdVerify_server/script/报告专用章.png"
+    # signature_pdf = "/Users/zoie/work/bzd_project/ColdVerify_server/ofile/signature" + name
+
+    add_signature(pdf_file_url, pdfFilename, signature_img, signature_pdf)
+    print(signature_pdf)

BIN=BIN
script/报告专用章.png


BIN=BIN
标签来源对应关系表.xlsx