Browse Source

2023-08-17 满意度调查

zoie 1 year ago
parent
commit
0ed415cc4c

+ 18 - 9
conf/app.conf

@@ -5,10 +5,10 @@ Graceful = true
 EnableDocs = true
 copyrequestbody = true
 
-NatsServer_Url = "175.178.229.79:4222"
+NatsServer_Url = "127.0.0.1:4223"
 
 # Mysql 线上
-MysqlServer_UrlPort = "192.168.192.251:3306"
+MysqlServer_UrlPort = "127.0.0.1:3316"
 MysqlServer_Database = "follow_up_notice"
 MysqlServer_Username = "follow_up_notice"
 MysqlServer_Password = "CKRjxTzr3jCcsJFX"
@@ -17,11 +17,11 @@ MysqlServer_MaxOpenConnections = 200
 
 
 # Redis
-Redis_address = "192.168.192.251:6379"
+Redis_address = "127.0.0.1:6378"
 Redis_password = ""
 Redis_dbNum = "3"
 
-FilterExcludeURL = /Login_verification,/receivecallstatus
+FilterExcludeURL = /Login_verification,/receivecallstatus,/Patient/ExportTemplate
 FilterOnlyLoginCheckURL =
 
 # 静态资源
@@ -30,17 +30,26 @@ Qiniu_SecretKey = "KFhkYxTAJ2ZPN3ZS3euTsfWk8-C92rKgkhAMkDRN"
 Qiniu_BUCKET = "coldoss"
 Qiniu_Url = "https://coldoss.coldbaozhida.com/"
 
-Sms_Appid = "95559"
-Sms_Signature = "f8e63844edd79d5bd2ab4a3d92c3b820"
-Sms_Fee = 0.8
-
+SUBMAIL_Sms_Appid = "95559"
+SUBMAIL_Sms_Signature = "f8e63844edd79d5bd2ab4a3d92c3b820"
+SUBMAIL_Voice_Appid = "22184"
+SUBMAIL_Voice_Signature = "c3e29e10daeea889cd72dd6375b4347e"
+SUBMAIL_Sms_Fee = 0.08
+Voice_Project = "vTHhS1"
 
 VoiceCall_BaseUrl = "https://rtccall.cn-north-1.myhuaweicloud.cn:443"
 VoiceCall_AppKey = "Zy8539Sa61Iv5fo5iGNWLcV24KI1"
 VoiceCall_AppSecret = "KNZ3OFv8eVF7zO5smbr0160WS4Az"
 VoiceCall_Template = "1101dc0ebc154a5a9e7c4e5f11bfdb41"
 VoiceCall_Phone = "+8651668971369"
-VoiceCall_Fee = 1.2
+VoiceCall_Fee = 0.12
+
+# 满意度调查
+VoiceCall_Satisfaction_Template1 = "756c9d79a36b4dd4a38c7758cc8becc8"
+VoiceCall_Satisfaction_Template2 = "d11d9d30b19c4d9f92e946698001ec2a"
+VoiceCall_Satisfaction_Template3 = "a3e39b2241c3474ab254513be708d9c3"
+VoiceCall_Satisfaction_Template4 = "a205ebf9f471492691bbcb8266a12a8c"
+VoiceCall_Satisfaction_Template5 = "db19cfdc2c474c1f95864db1ff45f66e"
 
 Weixin_PwdKey = "oKk5Bbq4Cf1u2AJXjvj1a0h9tqk8sdfg"
 Weixin_Notify = "https://follow.baozhida.cn/api/Wx/Notify"

+ 12 - 3
conf/config.go

@@ -32,9 +32,12 @@ var OssQiniu, _ = beego.AppConfig.String("OssQiniu")
 var ContractApprovalUrl, _ = beego.AppConfig.String("ContractApprovalUrl")
 var VerifyContractUrl, _ = beego.AppConfig.String("VerifyContractUrl")
 
-var Sms_Appid, _ = beego.AppConfig.String("Sms_Appid")
-var Sms_Signature, _ = beego.AppConfig.String("Sms_Signature")
-var Sms_Fee, _ = beego.AppConfig.Float("Sms_Fee")
+var SUBMAIL_Sms_Appid, _ = beego.AppConfig.String("SUBMAIL_Sms_Appid")
+var SUBMAIL_Sms_Signature, _ = beego.AppConfig.String("SUBMAIL_Sms_Signature")
+var SUBMAIL_Voice_Appid, _ = beego.AppConfig.String("SUBMAIL_Voice_Appid")
+var SUBMAIL_Voice_Signature, _ = beego.AppConfig.String("SUBMAIL_Voice_Signature")
+var SUBMAIL_Sms_Fee, _ = beego.AppConfig.Float("SUBMAIL_Sms_Fee")
+var Voice_Project, _ = beego.AppConfig.String("Voice_Project")
 
 var VoiceCall_BaseUrl, _ = beego.AppConfig.String("VoiceCall_BaseUrl")
 var VoiceCall_AppKey, _ = beego.AppConfig.String("VoiceCall_AppKey")
@@ -42,5 +45,11 @@ var VoiceCall_AppSecret, _ = beego.AppConfig.String("VoiceCall_AppSecret")
 var VoiceCall_Template, _ = beego.AppConfig.String("VoiceCall_Template")
 var VoiceCall_Phone, _ = beego.AppConfig.String("VoiceCall_Phone")
 var VoiceCall_Fee, _ = beego.AppConfig.Float("VoiceCall_Fee")
+var VoiceCall_Satisfaction_Template1, _ = beego.AppConfig.String("VoiceCall_Satisfaction_Template1")
+var VoiceCall_Satisfaction_Template2, _ = beego.AppConfig.String("VoiceCall_Satisfaction_Template2")
+var VoiceCall_Satisfaction_Template3, _ = beego.AppConfig.String("VoiceCall_Satisfaction_Template3")
+var VoiceCall_Satisfaction_Template4, _ = beego.AppConfig.String("VoiceCall_Satisfaction_Template4")
+var VoiceCall_Satisfaction_Template5, _ = beego.AppConfig.String("VoiceCall_Satisfaction_Template5")
+
 var Weixin_PwdKey, _ = beego.AppConfig.String("Weixin_PwdKey")
 var Weixin_Notify, _ = beego.AppConfig.String("Weixin_Notify")

+ 527 - 22
controllers/Patient.go

@@ -1,8 +1,10 @@
 package controllers
 
 import (
+	"FollowUp_Notice/Nats/NatsServer"
 	"FollowUp_Notice/conf"
 	"FollowUp_Notice/http"
+	"FollowUp_Notice/http/submail"
 	"FollowUp_Notice/lib"
 	"FollowUp_Notice/logs"
 	"FollowUp_Notice/models/Account"
@@ -12,9 +14,14 @@ import (
 	"FollowUp_Notice/models/System"
 	"FollowUp_Notice/models/Tag"
 	"encoding/json"
+	"fmt"
 	beego "github.com/beego/beego/v2/server/web"
 	"github.com/robfig/cron/v3"
+	"github.com/signintech/gopdf"
+	"github.com/signintech/gopdf/fontmaker/core"
+	"log"
 	"math"
+	"os"
 	"strconv"
 	"strings"
 	"time"
@@ -76,7 +83,7 @@ func (c *PatientController) Patient_List() {
 	return
 }
 
-// 添加患者信息
+// 导入患者信息
 func (c *PatientController) Patient_Add() {
 
 	T_number := c.GetString("T_number")
@@ -267,7 +274,7 @@ func (c *PatientController) Patient_Del() {
 		c.ServeJSON()
 		return
 	}
-	if c.User.Id != 1 || c.User.Id != patient.T_uid {
+	if c.User.Id != 1 && c.User.Id != patient.T_uid {
 		c.Data["json"] = lib.JSONS{Code: 202, Msg: "无权删除!"}
 		c.ServeJSON()
 		return
@@ -285,6 +292,56 @@ func (c *PatientController) Patient_Del() {
 
 }
 
+// 发送患者满意度调查
+func (c *PatientController) Patient_Send_Satisfaction() {
+	T_pid := c.GetString("T_pid")
+	if len(T_pid) == 0 {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_pid Err!"}
+		c.ServeJSON()
+		return
+	}
+	pidList := strings.Split(T_pid, ",")
+
+	go func() {
+
+		for _, v := range pidList {
+			pid, _ := strconv.Atoi(v)
+			patient, err := Patient.Read_Patient_ById(pid)
+			playInfoList := http.GetSatisfactionPlayInfoList([]string{patient.T_name, c.User.T_user})
+			res, err := http.VoiceNotifyAPI(conf.VoiceCall_Phone, "+86"+patient.T_phone, playInfoList)
+			if err != nil {
+				c.Data["json"] = lib.JSONS{Code: 202, Msg: "电话通知失败!"}
+				c.ServeJSON()
+				return
+			}
+
+			// 保存电话通知发送记录
+			send := Patient.PatientSend{
+				T_uid:   c.User.Id,
+				T_pid:   patient.Id,
+				T_phone: patient.T_phone,
+				T_type:  3,
+				T_id:    res.SessionId,
+				T_code:  res.Resultcode,
+				T_State: 0,
+			}
+
+			_, err = Patient.Add_PatientSend(send)
+			if err != nil {
+				System.Add_SysLogs_T("复诊通知", "添加发送记录失败", send)
+			}
+
+			if res.Resultcode != "0" {
+				System.Add_SysLogs_T("复诊通知", "添加发送记录失败", send)
+			}
+		}
+
+	}()
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "发送成功!"}
+	c.ServeJSON()
+	return
+}
+
 func (c *PatientController) VoiceCall_Status() {
 	// {"eventType":"callout","statusInfo":{"sessionId":"1201_14852_4294967295_20230529072219@callenabler245.huaweicaas.com","timestamp":"2023-05-29 07:22:19","caller":"+8651668971369","called":"+8618086869080"}}
 	logs.Println("VoiceCall RequestBody-", string(c.Ctx.Input.RequestBody))
@@ -298,6 +355,7 @@ func (c *PatientController) VoiceCall_Status() {
 			Called    string `json:"called"`
 			StateCode int    `json:"stateCode"`
 			StateDesc string `json:"stateDesc"`
+			DigitInfo string `json:"digitInfo"`
 		} `json:"statusInfo"`
 	}
 
@@ -308,18 +366,18 @@ func (c *PatientController) VoiceCall_Status() {
 		c.Data["json"] = lib.JSONS{Code: 202, Msg: "json.Unmarshal is err:" + err.Error()}
 		c.ServeJSON()
 	}
+	r, err := Patient.Read_PatientSend_ByT_id(body.StatusInfo.SessionId)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "SessionId Err!"}
+		c.ServeJSON()
+		return
+	}
 
 	if body.EventType == "disconnect" {
-		r, err := Patient.Read_PatientSend_ByT_id(body.StatusInfo.SessionId)
-		if err != nil {
-			c.Data["json"] = lib.JSONS{Code: 202, Msg: "SessionId Err!"}
-			c.ServeJSON()
-			return
-		}
 		if body.StatusInfo.StateCode == 0 {
 			r.T_State = 1
 		}
-		r.T_code = body.StatusInfo.StateCode
+		r.T_code = strconv.Itoa(body.StatusInfo.StateCode)
 		r.T_remark = body.StatusInfo.StateDesc
 		err = Patient.Update_PatientSend(r, "T_State", "T_remark", "T_code")
 		if err != nil {
@@ -327,14 +385,424 @@ func (c *PatientController) VoiceCall_Status() {
 			c.ServeJSON()
 			return
 		}
+	}
 
+	if body.EventType == "collectInfo" {
+		// 放音收号回调
+		r.T_type = 3
+		r.T_code = strconv.Itoa(body.StatusInfo.StateCode)
+		if len(r.T_digitInfo) == 0 {
+			r.T_digitInfo = body.StatusInfo.DigitInfo
+		} else if len(r.T_digitInfo) > 0 {
+			r.T_digitInfo += "," + body.StatusInfo.DigitInfo
+		}
+		err = Patient.Update_PatientSend(r, "T_type", "T_digitInfo")
+		if err != nil {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改放音收号结果失败!"}
+			c.ServeJSON()
+			return
+		}
+	}
+
+	if r.T_type == 3 {
+		go Add_PatientSatisfaction(body.StatusInfo.SessionId)
 	}
+
 	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
 	c.ServeJSON()
 	return
 
 }
 
+func Add_PatientSatisfaction(SessionId string) {
+	r, err := Patient.Read_PatientSend_ByT_id(SessionId)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+	//if len(r.T_digitInfo) == 0 {
+	//	return
+	//}
+	var T_digitInfo []string
+	if len(r.T_digitInfo) > 0 {
+		T_digitInfo = strings.Split(r.T_digitInfo, ",")
+	}
+	// 补齐长度为5
+	for len(T_digitInfo) < 5 {
+		T_digitInfo = append(T_digitInfo, "0")
+	}
+
+	satis := Patient.PatientSatisfaction{
+		T_id:        SessionId,
+		T_uid:       r.T_uid,
+		T_pid:       r.T_pid,
+		T_question1: T_digitInfo[0],
+		T_question2: T_digitInfo[1],
+		T_question3: T_digitInfo[2],
+		T_question4: T_digitInfo[3],
+		T_question5: T_digitInfo[4],
+	}
+	Patient.Add_PatientSatisfaction(satis)
+}
+
+// 导入患者信息
+func (c *PatientController) Patient_Import() {
+
+	T_number := c.GetString("T_number")
+	T_name := c.GetString("T_name")
+	T_age, _ := c.GetInt("T_age")
+
+	T_tag := c.GetString("T_tag")
+
+	T_tag_list := strings.Split(strings.Trim(T_tag, " "), "、")
+	tagIdList := []string{}
+	for _, t := range T_tag_list {
+		id, err := Tag.ReadOrCreate_Tag(Tag.Tag{
+			T_uid:   c.User.Id,
+			T_name:  t,
+			T_State: 1,
+		})
+
+		if err != nil {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "添加标签失败!"}
+			c.ServeJSON()
+			return
+		}
+		tagIdList = append(tagIdList, strconv.Itoa(int(id)))
+	}
+
+	T_illness := c.GetString("T_illness")
+	illnesslId, err := Illness.ReadOrCreate_Illness(Illness.Illness{
+		T_uid:   c.User.Id,
+		T_name:  T_illness,
+		T_State: 1,
+	})
+	T_surgical := c.GetString("T_surgical")
+	surgicalId, err := Surgical.ReadOrCreate_Surgical(Surgical.Surgical{
+		T_uid:   c.User.Id,
+		T_name:  T_surgical,
+		T_State: 1,
+	})
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "添加术式失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	T_phone := c.GetString("T_phone")
+	T_notice_phone := c.GetString("T_notice_phone")
+	phone := 0
+	if strings.Contains(T_notice_phone, "是") {
+		phone = 1
+	}
+	T_notice_message := c.GetString("T_notice_message")
+	message := 0
+	if strings.Contains(T_notice_message, "是") {
+		message = 1
+	}
+	// 下次复诊间隔天数
+	T_next_interval := c.GetString("T_next_interval")
+	T_record := time.Now().Format("2006-01-02") + "," + T_next_interval + "|"
+	var_ := Patient.Patient{
+		T_uid:             c.User.Id,
+		T_number:          T_number,
+		T_name:            T_name,
+		T_age:             T_age,
+		T_tag:             "|" + strings.Join(tagIdList, "|") + "|",
+		T_illness:         int(illnesslId),
+		T_surgical:        int(surgicalId),
+		T_phone:           T_phone,
+		T_notice_phone:    phone,
+		T_notice_message:  message,
+		T_notice_interval: "1,3",
+		T_record:          T_record,
+		T_State:           1,
+	}
+	T_record_list := strings.Split(strings.Trim(T_record, "|"), "|")
+	var T_time string  // 复诊时间
+	var T_interval int // 复诊间隔
+	if len(T_record_list) > 0 {
+		temp := T_record_list[len(T_record_list)-1]
+		T_time = strings.Split(temp, ",")[0]
+		T_interval, _ = strconv.Atoi(strings.Split(temp, ",")[1])
+		t, _ := lib.DateStrToTime(T_time)
+		nextTime := t.AddDate(0, 0, T_interval)
+		// 复诊状态 1正常 2超时 3结束
+		var_.T_follow_up = 1
+		if nextTime.Before(time.Now()) {
+			var_.T_follow_up = 2
+		}
+		if T_interval == 0 {
+			var_.T_follow_up = 3
+		}
+		var_.T_next_time = nextTime.Format("2006-01-02")
+		var_.T_notice = 1
+	}
+
+	_, err = Patient.Add_Patient(var_)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 209, Msg: "添加失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	System.Add_UserLogs_T(c.User.T_uuid, "患者", "导入", var_)
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
+	c.ServeJSON()
+	return
+
+}
+
+// 导出模板
+func (c *PatientController) Patient_ExportTemplate() {
+
+	//第一个参数是文件的地址,第二个参数是下载显示的文件的名称
+	c.Ctx.Output.Download("static/导入患者模板.xlsx", "导入患者模板.xlsx")
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
+	c.ServeJSON()
+	return
+}
+
+func (c *PatientController) VoiceCall_Satisfaction_PDF() {
+	T_id := c.GetString("T_id")
+	var err error
+	r, err := Patient.Read_PatientSatisfaction_ByT_id(T_id)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "SessionId Err!"}
+		c.ServeJSON()
+		return
+	}
+	username := "某某医院某某科室"
+	if r.T_pid > 0 {
+		user, err := Account.Read_User_ByT_id(r.T_uid)
+		if err != nil {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取用户信息失败!"}
+			c.ServeJSON()
+			return
+		}
+		username = user.T_user
+	}
+
+	//读取pdf文件
+	pdf := &gopdf.GoPdf{}
+	pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4}) //595.28, 841.89 = A4
+	pdf.AddPage()
+	err = pdf.AddTTFFont("simsun", "static/fonts/MiSans-Medium.ttf")
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
+		c.ServeJSON()
+		return
+	}
+	err = pdf.SetFont("simsun", "", 26)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
+		c.ServeJSON()
+		return
+	}
+
+	textw, _ := pdf.MeasureTextWidth("患者满意度调查表")
+	pdf.SetX((595 / 2) - (textw / 2))
+	pdf.SetY(60)
+	pdf.Text("患者满意度调查表")
+
+	fontSize := 14
+	err = pdf.SetFont("simsun", "", fontSize)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
+		c.ServeJSON()
+		return
+	}
+
+	var parser core.TTFParser
+	err = parser.Parse("static/fonts/MiSans-Medium.ttf")
+	if err != nil {
+		log.Print(err.Error())
+		return
+	}
+
+	cap := float64(float64(parser.CapHeight()) * 1000.00 / float64(parser.UnitsPerEm()))
+	//convert
+	realHeight := cap * (float64(fontSize) / 1000.0) * 3
+	var x float64 = 45
+	pdf.SetXY(x, 100)
+	pdf.Cell(nil, "尊敬的各位患者朋友:")
+
+	msg := fmt.Sprintf("为了解各位对%s向社会和广大群众提供医疗服务的真实状况,请根据您的亲身经历或感受就以下5个问题对本科室进行真实、客观的评价,请在您认为合适的选项方框内划勾,非常感谢您的配合与支持!", username)
+	msgRune := []rune(msg)
+	for i := 0; i < len(msgRune); {
+		pdf.Br(realHeight)
+
+		end := 0
+		step := 0
+		if i == 0 {
+			pdf.SetX(x + float64(fontSize*2))
+			end = i + 34
+			step = 34
+		} else {
+			pdf.SetX(x)
+			end = i + 36
+			step = 36
+		}
+		if end > len(msgRune) {
+			end = len(msgRune)
+		}
+		pdf.Cell(nil, string(msgRune[i:end]))
+		i += step
+
+	}
+
+	realHeight2 := cap * (float64(fontSize) / 1000.0) * 4
+
+	pdf.Br(realHeight2)
+	RectFill(pdf, "1、您对初入病房时医护人员及时询问病情和检查,是否满意?", fontSize, x, realHeight2, r.T_question1)
+	pdf.Br(realHeight2)
+	RectFill2(pdf, "2、您入院后是否有告知您的管床医生和护士是谁?", fontSize, x, realHeight2, r.T_question2)
+	pdf.Br(realHeight2)
+	RectFill(pdf, "3、您对住院期间入院注意事项的交代是否满意?", fontSize, x, realHeight2, r.T_question3)
+	pdf.Br(realHeight2)
+	RectFill(pdf, "4、在住院期间,您对病情解释是否满意?", fontSize, x, realHeight2, r.T_question4)
+	pdf.Br(realHeight2)
+	RectFill(pdf, "5、您对医护人员的服务态度是否满意?", fontSize, x, realHeight2, r.T_question3)
+	pdf.Br(realHeight2)
+	pdf.Br(realHeight2)
+	pdf.SetX(400)
+	pdf.Cell(nil, fmt.Sprintf("日期:%s", r.CreateTime.Format("2006-01-02")))
+
+	timeStr := "ofile/" + time.Now().Format("20060102150405") + ".pdf"
+
+	err = pdf.WritePdf(timeStr)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
+		c.ServeJSON()
+		return
+	}
+	// 上传 OSS
+	url, is := NatsServer.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/"+timeStr, timeStr)
+	if !is {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"}
+		c.ServeJSON()
+		return
+	}
+
+	//删除目录
+	err = os.Remove(timeStr)
+	if err != nil {
+		fmt.Println(err)
+	}
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url}
+	c.ServeJSON()
+	return
+
+}
+
+func RectFill(pdf *gopdf.GoPdf, text string, fontSize int, x, realHeight float64, digitInfo string) {
+	pdf.SetX(x)
+	pdf.Cell(nil, text)
+
+	pdf.Br(realHeight)
+
+	//textw, _ := pdf.MeasureTextWidth(text)
+
+	//y := x + textw
+	y := x
+
+	var LineWidth float64 = 1
+
+	var text1 = ""
+	if digitInfo == "1" {
+		text1 = "√"
+	}
+	pdf.SetX(y + float64(fontSize*2))
+	pdf.SetLineWidth(LineWidth)
+	pdf.SetLineType("") // 线条样式
+	pdf.CellWithOption(&gopdf.Rect{
+		W: float64(fontSize),
+		H: float64(fontSize),
+	}, text1, gopdf.CellOption{Align: gopdf.Center | gopdf.Middle,
+		Border: gopdf.Left | gopdf.Right | gopdf.Bottom | gopdf.Top,
+	})
+	pdf.Cell(nil, " 非常满意")
+
+	var text2 = ""
+	if digitInfo == "2" {
+		text2 = "√"
+	}
+
+	pdf.SetX(y + float64(fontSize*9))
+	pdf.SetLineWidth(LineWidth)
+	pdf.SetLineType("") // 线条样式
+	pdf.CellWithOption(&gopdf.Rect{
+		W: float64(fontSize),
+		H: float64(fontSize),
+	}, text2, gopdf.CellOption{Align: gopdf.Center | gopdf.Middle,
+		Border: gopdf.Left | gopdf.Right | gopdf.Bottom | gopdf.Top,
+	})
+	pdf.Cell(nil, " 满意")
+
+	var text3 = ""
+	if digitInfo == "3" {
+		text3 = "√"
+	}
+
+	pdf.SetX(y + float64(fontSize*14))
+	pdf.SetLineWidth(LineWidth)
+	pdf.SetLineType("") // 线条样式
+	pdf.CellWithOption(&gopdf.Rect{
+		W: float64(fontSize),
+		H: float64(fontSize),
+	}, text3, gopdf.CellOption{Align: gopdf.Center | gopdf.Middle,
+		Border: gopdf.Left | gopdf.Right | gopdf.Bottom | gopdf.Top,
+	})
+	pdf.Cell(nil, " 不满意")
+
+}
+
+func RectFill2(pdf *gopdf.GoPdf, text string, fontSize int, x, realHeight float64, digitInfo string) {
+	pdf.SetX(x)
+	pdf.Cell(nil, text)
+
+	pdf.Br(realHeight)
+
+	//textw, _ := pdf.MeasureTextWidth(text)
+
+	//y := x + textw
+	y := x
+
+	var LineWidth float64 = 1
+
+	var text1 = ""
+	if digitInfo == "1" {
+		text1 = "√"
+	}
+	pdf.SetX(y + float64(fontSize*2))
+	pdf.SetLineWidth(LineWidth)
+	pdf.SetLineType("") // 线条样式
+	pdf.CellWithOption(&gopdf.Rect{
+		W: float64(fontSize),
+		H: float64(fontSize),
+	}, text1, gopdf.CellOption{Align: gopdf.Center | gopdf.Middle,
+		Border: gopdf.Left | gopdf.Right | gopdf.Bottom | gopdf.Top,
+	})
+	pdf.Cell(nil, " 是")
+
+	var text2 = ""
+	if digitInfo == "2" {
+		text2 = "√"
+	}
+
+	pdf.SetX(y + float64(fontSize*9))
+	pdf.SetLineWidth(LineWidth)
+	pdf.SetLineType("") // 线条样式
+	pdf.CellWithOption(&gopdf.Rect{
+		W: float64(fontSize),
+		H: float64(fontSize),
+	}, text2, gopdf.CellOption{Align: gopdf.Center | gopdf.Middle,
+		Border: gopdf.Left | gopdf.Right | gopdf.Bottom | gopdf.Top,
+	})
+	pdf.Cell(nil, " 否")
+}
+
 func Cron_Patient() {
 
 	//创建一个定时任务对象
@@ -428,7 +896,7 @@ func Send_Notice(nextTime time.Time, user Account.User_R, patient Patient.Patien
 
 	//发送短信通知
 	if patient.T_notice_message == 1 {
-		res, err := http.SmsXSend(user.T_template_id, patient.T_phone, patient.T_name, nextTime.Format("2006年01月02日"))
+		res, err := submail.SmsXSend(user.T_template_id, patient.T_phone, patient.T_name, nextTime.Format("2006年01月02日"))
 		if err != nil {
 			System.Add_SysLogs_T("复诊通知", "短信通知失败", patient)
 		}
@@ -440,7 +908,8 @@ func Send_Notice(nextTime time.Time, user Account.User_R, patient Patient.Patien
 			T_type:   1,
 			T_id:     res.Send_id,
 			T_remark: res.Status,
-			T_code:   res.Fee,
+			T_fee:    res.Fee,
+			T_code:   res.Code,
 			T_State:  1,
 		}
 		if res.Status == "error" {
@@ -456,31 +925,67 @@ func Send_Notice(nextTime time.Time, user Account.User_R, patient Patient.Patien
 	}
 
 	if patient.T_notice_phone == 1 {
-		playInfoList := http.GetPlayInfoList(conf.VoiceCall_Template, []string{user.T_user, patient.T_name, nextTime.Format("2006/01/02")})
-		res, err := http.VoiceNotifyAPI(conf.VoiceCall_Phone, "+86"+patient.T_phone, playInfoList)
+		// ----------- 华为语音通知
+		//playInfoList := http.GetPlayInfoList(conf.VoiceCall_Template, []string{user.T_user, patient.T_name, nextTime.Format("2006/01/02")})
+		//res, err := http.VoiceNotifyAPI(conf.VoiceCall_Phone, "+86"+patient.T_phone, playInfoList)
+		//if err != nil {
+		//	System.Add_SysLogs_T("复诊通知", "电话通知失败", patient)
+		//}
+		//// 保存短信发送记录
+		//smsSend := Patient.PatientSend{
+		//	T_uid:    user.Id,
+		//	T_pid:    patient.Id,
+		//	T_phone:  patient.T_phone,
+		//	T_type:   2,
+		//	T_id:     res.SessionId,
+		//	T_remark: res.Resultdesc,
+		//	T_State:  0,
+		//}
+		//if res.Resultcode != "0" {
+		//	smsSend.T_State = 0
+		//}
+		//if res.Resultcode == "0" {
+		//	Success = true
+		//}
+		//_, err = Patient.Add_PatientSend(smsSend)
+		//if err != nil {
+		//	System.Add_SysLogs_T("复诊通知", "添加发送记录失败", patient)
+		//}
+
+		// ----------- 塞班语音通知
+		res, err := submail.VoiceXSend(patient.T_phone, user.T_user, patient.T_name, nextTime.Format("2006年01月02日"))
 		if err != nil {
 			System.Add_SysLogs_T("复诊通知", "电话通知失败", patient)
 		}
+
 		// 保存短信发送记录
-		smsSend := Patient.PatientSend{
+		send := Patient.PatientSend{
 			T_uid:    user.Id,
 			T_pid:    patient.Id,
 			T_phone:  patient.T_phone,
 			T_type:   2,
-			T_id:     res.SessionId,
-			T_remark: res.Resultdesc,
-			T_State:  0,
+			T_id:     res.Send_id,
+			T_remark: res.Status,
+			T_fee:    res.Fee,
+			T_code:   res.Code,
+			T_State:  1,
 		}
-		if res.Resultcode != "0" {
-			smsSend.T_State = 0
+
+		_, err = Patient.Add_PatientSend(send)
+		if err != nil {
+			System.Add_SysLogs_T("复诊通知", "添加语音发送记录失败", send)
 		}
-		if res.Resultcode == "0" {
+		if res.Status == "error" {
+			send.T_State = 0
+		}
+		if res.Status == "success" {
 			Success = true
 		}
-		_, err = Patient.Add_PatientSend(smsSend)
+		_, err = Patient.Add_PatientSend(send)
 		if err != nil {
-			System.Add_SysLogs_T("复诊通知", "添加发送记录失败", patient)
+			System.Add_SysLogs_T("复诊通知", "添加语音发送记录失败", send)
 		}
+
 	}
 
 	return Success

+ 210 - 16
controllers/User.go

@@ -4,6 +4,7 @@ import (
 	"FollowUp_Notice/Nats/NatsServer"
 	"FollowUp_Notice/conf"
 	"FollowUp_Notice/http"
+	"FollowUp_Notice/http/submail"
 	"FollowUp_Notice/lib"
 	"FollowUp_Notice/logs"
 	"FollowUp_Notice/models/Account"
@@ -150,7 +151,7 @@ func (c *UserController) Add() {
 		return
 	}
 
-	temp, err := http.SmsTemplate_Post(T_user)
+	temp, err := submail.SmsTemplate_Post(T_user)
 	if err != nil || temp.Status != "success" {
 		c.Data["json"] = lib.JSONS{Code: 202, Msg: "创建短信模板失败"}
 		c.ServeJSON()
@@ -292,7 +293,7 @@ func (c *UserController) Del() {
 		return
 	}
 
-	temp, err := http.SmsTemplate_Delete(user.T_template_id)
+	temp, err := submail.SmsTemplate_Delete(user.T_template_id)
 	if err != nil || temp.Status != "success" {
 		c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除短信模板失败"}
 		c.ServeJSON()
@@ -353,6 +354,7 @@ func (c *UserController) Pay() {
 		c.ServeJSON()
 		return
 	}
+	user.T_pass = "******"
 	System.Add_UserLogs_T(c.User.T_uuid, "用户管理", "充值", user)
 	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
 	c.ServeJSON()
@@ -710,7 +712,7 @@ func (c *UserController) Send_Test() {
 	}
 	//发送短信通知
 	if T_type == 1 {
-		res, err := http.SmsXSend("mDZSZ3", T_phone, "张三", time.Now().AddDate(0, 0, 1).Format("2006年01月02日"))
+		res, err := submail.SmsXSend("mDZSZ3", T_phone, "张三", time.Now().AddDate(0, 0, 1).Format("2006年01月02日"))
 		if err != nil {
 			c.Data["json"] = lib.JSONS{Code: 200, Msg: "短信发送失败!"}
 			c.ServeJSON()
@@ -725,7 +727,8 @@ func (c *UserController) Send_Test() {
 			T_type:   1,
 			T_id:     res.Send_id,
 			T_remark: res.Status,
-			T_code:   res.Fee,
+			T_fee:    res.Fee,
+			T_code:   res.Code,
 			T_State:  1,
 		}
 		if res.Status == "error" {
@@ -733,7 +736,7 @@ func (c *UserController) Send_Test() {
 		}
 		_, err = Patient.Add_PatientSend(smsSend)
 		if err != nil {
-			System.Add_SysLogs_T("复诊通知", "添加发送记录失败", smsSend)
+			System.Add_SysLogs_T("复诊通知", "添加短信发送记录失败", smsSend)
 		}
 
 		if res.Status == "error" {
@@ -745,8 +748,37 @@ func (c *UserController) Send_Test() {
 	}
 
 	if T_type == 2 {
-		playInfoList := http.GetPlayInfoList(conf.VoiceCall_Template, []string{"某某医院消化内科", "张三", time.Now().AddDate(0, 0, 1).Format("2006/01/02")})
-		res, err := http.VoiceNotifyAPI(conf.VoiceCall_Phone, "+86"+T_phone, playInfoList)
+		// 华为语音通知
+		//playInfoList := http.GetPlayInfoList(conf.VoiceCall_Template, []string{"某某医院消化内科", "张三", time.Now().AddDate(0, 0, 1).Format("2006/01/02")})
+		//res, err := http.VoiceNotifyAPI(conf.VoiceCall_Phone, "+86"+T_phone, playInfoList)
+		//if err != nil {
+		//	c.Data["json"] = lib.JSONS{Code: 202, Msg: "电话通知失败!"}
+		//	c.ServeJSON()
+		//	return
+		//}
+		// 保存短信发送记录
+		//send := Patient.PatientSend{
+		//	T_uid:   c.User.Id,
+		//	T_pid:   0,
+		//	T_phone: T_phone,
+		//	T_type:  2,
+		//	T_id:    res.SessionId,
+		//	T_code:  -1,
+		//	T_State: 0,
+		//}
+		//
+		//_, err = Patient.Add_PatientSend(send)
+		//if err != nil {
+		//	System.Add_SysLogs_T("复诊通知", "添加发送记录失败", send)
+		//}
+		//
+		//if res.Resultcode != "0" {
+		//	c.Data["json"] = lib.JSONS{Code: 202, Msg: "电话通知失败!"}
+		//	c.ServeJSON()
+		//	return
+		//}
+
+		res, err := submail.VoiceXSend(T_phone, "某某医院某某科室", "张三", time.Now().AddDate(0, 0, 1).Format("2006年01月02日"))
 		if err != nil {
 			c.Data["json"] = lib.JSONS{Code: 202, Msg: "电话通知失败!"}
 			c.ServeJSON()
@@ -759,8 +791,46 @@ func (c *UserController) Send_Test() {
 			T_pid:   0,
 			T_phone: T_phone,
 			T_type:  2,
+			T_id:    res.Send_id,
+			T_fee:   res.Fee,
+			T_code:  res.Code,
+			T_State: 1,
+		}
+
+		if res.Status == "error" {
+			send.T_State = 0
+		}
+		_, err = Patient.Add_PatientSend(send)
+		if err != nil {
+			System.Add_SysLogs_T("复诊通知", "添加语音发送记录失败", send)
+		}
+
+		if res.Status == "error" {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "语音通知失败!"}
+			c.ServeJSON()
+			return
+		}
+
+	}
+
+	// 发送满意度调查短信
+	if T_type == 3 {
+		playInfoList := http.GetSatisfactionPlayInfoList([]string{"张三", "某某医院消化内科"})
+		res, err := http.VoiceNotifyAPI(conf.VoiceCall_Phone, "+86"+T_phone, playInfoList)
+		if err != nil {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "电话通知失败!"}
+			c.ServeJSON()
+			return
+		}
+
+		// 保存电话通知发送记录
+		send := Patient.PatientSend{
+			T_uid:   c.User.Id,
+			T_pid:   0,
+			T_phone: T_phone,
+			T_type:  3,
 			T_id:    res.SessionId,
-			T_code:  -1,
+			T_code:  res.Resultcode,
 			T_State: 0,
 		}
 
@@ -770,11 +840,10 @@ func (c *UserController) Send_Test() {
 		}
 
 		if res.Resultcode != "0" {
-			c.Data["json"] = lib.JSONS{Code: 202, Msg: "电话通知失败!"}
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "满意度调查失败!"}
 			c.ServeJSON()
 			return
 		}
-
 	}
 
 	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
@@ -831,12 +900,11 @@ func (c *UserController) Weixin_Notify() {
 		Code    int
 		Message string
 	}
-	buf := make([]byte, 1024)
-	n, _ := c.Ctx.Request.Body.Read(buf)
-	fmt.Println("Body:", string(buf[0:n]))
+
+	logs.Info("Body:", string(c.Ctx.Input.RequestBody))
 
 	//解密
-	adc_str, err := lib.AesDeCrypt(buf[0:n], []byte(conf.Weixin_PwdKey))
+	adc_str, err := lib.AesDeCrypt(c.Ctx.Input.RequestBody, []byte(conf.Weixin_PwdKey))
 	//adc_str, _ := lib.AesDeCrypt(buf[0:n], []byte(conf.Weixin_PwdKey))
 
 	var body RequestBody
@@ -853,6 +921,14 @@ func (c *UserController) Weixin_Notify() {
 		c.ServeJSON()
 		return
 	}
+	//交易状态
+	//SUCCESS:支付成功
+	//REFUND:转入退款
+	//NOTPAY:未支付
+	//CLOSED:已关闭
+	//REVOKED:已撤销(付款码支付)
+	//USERPAYING:用户支付中(付款码支付)
+	//PAYERROR:支付失败(其他原因,如银行返回失败)
 	UserPayOrder.T_status = body.Status
 	err = Account.Update_UserPayOrder(UserPayOrder, "T_status")
 	if err != nil {
@@ -860,6 +936,37 @@ func (c *UserController) Weixin_Notify() {
 		c.ServeJSON()
 		return
 	}
+	// 添加充值记录
+	// 余额加上充值金额
+	if body.Status == "SUCCESS" {
+		T_money64, _ := decimal.NewFromFloat(float64(c.User.T_money) + UserPayOrder.T_total).Round(2).Float64()
+		c.User.T_money = float32(T_money64)
+		// 修改用户余额
+		err = Account.Update_User(c.User, "T_money")
+		if err != nil {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "充值失败!"}
+			c.ServeJSON()
+			return
+		}
+
+		// 添加充值记录
+		bill := Account.UserBill{
+			T_uid:      c.User.Id,
+			T_type:     Account.Pay,
+			T_bill:     "充值(微信)",
+			T_charging: float32(UserPayOrder.T_total),
+			T_balance:  float32(T_money64),
+		}
+		_, err = Account.Add_UserBill(bill)
+		if err != nil {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "充值失败!"}
+			c.ServeJSON()
+			return
+		}
+		user := c.User
+		user.T_pass = "******"
+		System.Add_UserLogs_T(c.User.T_uuid, "用户管理", "充值", user)
+	}
 
 	c.Data["json"] = JSON{Code: 200, Message: "成功"}
 	c.ServeJSON()
@@ -881,6 +988,93 @@ func (c *UserController) GetWxOrderState() {
 	return
 }
 
+// 满意度统计
+func (c *UserController) Satisfaction_Stats() {
+	list, err := Patient.Read_PatientSatisfaction_ByT_uid(c.User.Id)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+	type Json struct {
+		Count map[string]map[string]int
+		Title map[string]string
+	}
+
+	countMap := make(map[string]map[string]int)
+	for _, v := range list {
+		updateCountMap(countMap, "question1", v.T_question1)
+		updateCountMap(countMap, "question2", v.T_question2)
+		updateCountMap(countMap, "question3", v.T_question3)
+		updateCountMap(countMap, "question4", v.T_question4)
+		updateCountMap(countMap, "question5", v.T_question5)
+	}
+	title := make(map[string]string)
+	title["question1"] = Patient.Question1
+	title["question2"] = Patient.Question2
+	title["question3"] = Patient.Question3
+	title["question4"] = Patient.Question4
+	title["question5"] = Patient.Question5
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Json{Count: countMap, Title: title}}
+
+	c.ServeJSON()
+	return
+
+}
+
+// 辅助函数:更新选项计数
+func updateCountMap(countMap map[string]map[string]int, question string, value string) {
+	if question == "question2" {
+		if strings.Contains("12", value) {
+			if countMap[question] == nil {
+				countMap[question] = map[string]int{
+					"1": 0,
+					"2": 0,
+				}
+			}
+			countMap[question][value]++
+		}
+	} else {
+		if strings.Contains("123", value) {
+			if countMap[question] == nil {
+				countMap[question] = map[string]int{
+					"1": 0,
+					"2": 0,
+					"3": 0,
+				}
+			}
+			countMap[question][value]++
+		}
+	}
+
+}
+
+// 满意度列表
+func (c *UserController) Satisfaction_List() {
+	// 分页参数 初始化
+	page, _ := c.GetInt("page")
+	if page < 1 {
+		page = 1
+	}
+	page_z, _ := c.GetInt("page_z")
+	if page_z < 1 {
+		page_z = conf.Page_size
+	}
+	Patient.Read_Patient_All_Map(c.User.Id)
+	list, cnt := Patient.Read_PatientSatisfaction_List(c.User.Id, page, page_z)
+
+	var r_jsons lib.R_JSONS
+	r_jsons.Num = cnt
+	r_jsons.Data = list
+	r_jsons.Page = page
+	r_jsons.Page_size = int(math.Ceil(float64(cnt) / float64(page_z)))
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
+	c.ServeJSON()
+	return
+
+}
+
 // 用户定时任务
 func Cron_User() {
 
@@ -909,7 +1103,7 @@ func Cron_User_Money_Bill() {
 		// 1 短信 2 电话
 		smsCount := Patient.Read_PatientSend_Count_Yesterday(user.Id, 0, 1, yesterday)
 		voiceCallCount := Patient.Read_PatientSend_Count_Yesterday(user.Id, 0, 2, yesterday)
-		money := float64(smsCount)*conf.Sms_Fee + float64(voiceCallCount)*conf.VoiceCall_Fee
+		money := float64(smsCount)*conf.SUBMAIL_Sms_Fee + float64(voiceCallCount)*conf.VoiceCall_Fee
 		if money == 0 {
 			continue
 		}
@@ -944,7 +1138,7 @@ func Cron_User_Money_Bill() {
 			System.Add_SysLogs_T("用户扣费", "添加扣费记录失败", bill)
 		}
 		if sendMsg {
-			_, err = http.SmsXSendBill(user.T_phone, user.T_user, moneyFlag)
+			_, err = submail.SmsXSendBill(user.T_phone, user.T_user, moneyFlag)
 			info := fmt.Sprintf("T_uid:%v, T_phone:%v, T_user:%v, moneyFlag:%v", user.Id, user.T_phone, user.T_user, moneyFlag)
 			if err != nil {
 				System.Add_SysLogs_T("复诊通知-账单", "短信通知失败", info)

+ 1 - 0
go.mod

@@ -20,6 +20,7 @@ require (
 	github.com/golang/protobuf v1.5.2 // indirect
 	github.com/gomodule/redigo v2.0.0+incompatible // indirect
 	github.com/hashicorp/golang-lru v0.5.4 // indirect
+	github.com/jung-kurt/gofpdf v1.16.2 // indirect
 	github.com/klauspost/compress v1.15.15 // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
 	github.com/minio/highwayhash v1.0.2 // indirect

+ 7 - 0
go.sum

@@ -51,6 +51,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
 github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
 github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -178,6 +179,9 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
 github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
+github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
+github.com/jung-kurt/gofpdf v1.16.2 h1:jgbatWHfRlPYiK85qgevsZTHviWXKwB1TTiKdz5PtRc=
+github.com/jung-kurt/gofpdf v1.16.2/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
 github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4=
@@ -231,6 +235,7 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
 github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
+github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
 github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311 h1:zyWXQ6vu27ETMpYsEMAsisQ+GqJ4e1TPvSNfdOPF0no=
 github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
 github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
@@ -282,6 +287,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
 github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
 github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
 github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
+github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
 github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
@@ -351,6 +357,7 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
 golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=

+ 41 - 4
http/VcoiceCall.go

@@ -1,6 +1,7 @@
 package http
 
 import (
+	"FollowUp_Notice/conf"
 	"FollowUp_Notice/lib"
 	"FollowUp_Notice/logs"
 	"crypto/hmac"
@@ -38,6 +39,7 @@ func buildAKSKHeader(appKey string, appSecret string) string {
 type PlayInfo struct {
 	TemplateID    string   `json:"templateId"`
 	TemplateParas []string `json:"templateParas"`
+	CollectInd    int      `json:"collectInd"`
 }
 
 type VoiceNotifyRequest struct {
@@ -89,9 +91,44 @@ func VoiceNotifyAPI(displayNbr string, calleeNbr string, playInfoList []PlayInfo
 }
 
 func GetPlayInfoList(templateId string, templateParas []string) []PlayInfo {
-	playInfoList := []PlayInfo{{
-		TemplateID:    templateId,
-		TemplateParas: templateParas,
-	}}
+	playInfoList := []PlayInfo{
+		{
+			TemplateID:    templateId,
+			TemplateParas: templateParas,
+			CollectInd:    0,
+		},
+	}
+	return playInfoList
+}
+
+// 满意度调查
+func GetSatisfactionPlayInfoList(templateParas []string) []PlayInfo {
+	playInfoList := []PlayInfo{
+		{
+			TemplateID:    conf.VoiceCall_Satisfaction_Template1,
+			TemplateParas: templateParas,
+			CollectInd:    1,
+		},
+		{
+			TemplateID:    conf.VoiceCall_Satisfaction_Template2,
+			TemplateParas: []string{""},
+			CollectInd:    1,
+		},
+		{
+			TemplateID:    conf.VoiceCall_Satisfaction_Template3,
+			TemplateParas: []string{""},
+			CollectInd:    1,
+		},
+		{
+			TemplateID:    conf.VoiceCall_Satisfaction_Template4,
+			TemplateParas: []string{""},
+			CollectInd:    1,
+		},
+		{
+			TemplateID:    conf.VoiceCall_Satisfaction_Template5,
+			TemplateParas: []string{""},
+			CollectInd:    1,
+		},
+	}
 	return playInfoList
 }

+ 233 - 0
http/submail/SmsTemplate.go

@@ -0,0 +1,233 @@
+package submail
+
+import (
+	"FollowUp_Notice/conf"
+	"FollowUp_Notice/lib"
+	"FollowUp_Notice/logs"
+	"encoding/json"
+	"github.com/go-resty/resty/v2"
+)
+
+type Template struct {
+	Template_id                 string `json:"template_id"`
+	Sms_title                   string `json:"sms_title"`
+	Sms_signature               string `json:"sms_signature"`
+	Sms_content                 string `json:"sms_content"`
+	Add_date                    string `json:"add_date"`
+	Edit_date                   string `json:"edit_date"`
+	Template_status             string `json:"template_status"`
+	Template_status_description string `json:"template_status_description"`
+}
+
+type TemplateRes struct {
+	Status      string   `json:"status"`
+	Template_id string   `json:"template_id"`
+	Template    Template `json:"template"`
+}
+type XSendRes struct {
+	Status  string  `json:"status"`
+	Send_id string  `json:"send_id"`
+	Fee     float64 `json:"fee"`
+	Msg     string  `json:"msg"`
+	Code    string  `json:"code"`
+}
+
+func SmsTemplate_Get(template_id string) (TemplateRes, error) {
+	// Create a Resty Client
+	client := resty.New()
+
+	resp, err := client.R().
+		SetQueryParams(map[string]string{
+			"appid":       conf.SUBMAIL_Sms_Appid,
+			"signature":   conf.SUBMAIL_Sms_Signature,
+			"template_id": template_id,
+		}).
+		Get("https://api-v4.mysubmail.com/sms/template.json")
+
+	if err != nil {
+		return TemplateRes{}, err
+	}
+
+	temp := TemplateRes{}
+	if err = json.Unmarshal(resp.Body(), &temp); err != nil {
+		logs.Error(lib.FuncName(), err)
+		return TemplateRes{}, err
+	}
+	return temp, nil
+}
+
+// 创建模板
+func SmsTemplate_Post(sms_signature string) (TemplateRes, error) {
+	client := resty.New()
+	resp, err := client.R().
+		SetHeader("Content-Type", "application/x-www-form-urlencoded").
+		SetFormData(map[string]string{
+			"appid":         conf.SUBMAIL_Sms_Appid,
+			"signature":     conf.SUBMAIL_Sms_Signature,
+			"sms_title":     "复诊通知",
+			"sms_signature": sms_signature,
+			"sms_content":   "敬爱的@var(name),离上一次来我院治疗的复诊时间已到,为了更好关注您的病情,请于@var(time)到我院进行复诊,祝您早日康复!",
+		}).
+		Post("http://api.mysubmail.com/sms/template.json")
+
+	if err != nil {
+		return TemplateRes{}, err
+	}
+
+	temp := TemplateRes{}
+	if err = json.Unmarshal(resp.Body(), &temp); err != nil {
+		logs.Error(lib.FuncName(), err)
+		return TemplateRes{}, err
+	}
+	return temp, nil
+}
+
+// 修改模板
+func SmsTemplate_Put(template_id, sms_signature string) (TemplateRes, error) {
+	client := resty.New()
+	resp, err := client.R().
+		SetHeader("Content-Type", "application/x-www-form-urlencoded").
+		SetFormData(map[string]string{
+			"appid":         conf.SUBMAIL_Sms_Appid,
+			"signature":     conf.SUBMAIL_Sms_Signature,
+			"template_id":   template_id,
+			"sms_title":     "复诊通知",
+			"sms_signature": sms_signature,
+			"sms_content":   "敬爱的@var(code),离上一次来我院治疗的复诊时间已到,为了更好关注您的病情,请于明日到我院进行复诊,祝您早日康复!",
+		}).
+		SetResult(&TemplateRes{}).
+		Put("http://api.mysubmail.com/sms/template.json")
+
+	if err != nil {
+		return TemplateRes{}, err
+	}
+
+	temp := TemplateRes{}
+	if err = json.Unmarshal(resp.Body(), &temp); err != nil {
+		logs.Error(lib.FuncName(), err)
+		return TemplateRes{}, err
+	}
+	return temp, nil
+}
+
+func SmsTemplate_Delete(template_id string) (TemplateRes, error) {
+	client := resty.New()
+	resp, err := client.R().
+		SetHeader("Content-Type", "application/x-www-form-urlencoded").
+		SetFormData(map[string]string{
+			"appid":       conf.SUBMAIL_Sms_Appid,
+			"signature":   conf.SUBMAIL_Sms_Signature,
+			"template_id": template_id,
+		}).
+		SetResult(&TemplateRes{}).
+		Delete("http://api.mysubmail.com/sms/template.json")
+
+	if err != nil {
+		return TemplateRes{}, err
+	}
+
+	temp := TemplateRes{}
+	if err = json.Unmarshal(resp.Body(), &temp); err != nil {
+		logs.Error(lib.FuncName(), err)
+		return TemplateRes{}, err
+	}
+	return temp, nil
+}
+
+// 批量发送短信
+func SmsMultiSend(template_id, content string) (TemplateRes, error) {
+	client := resty.New()
+	resp, err := client.R().
+		SetHeader("Content-Type", "application/x-www-form-urlencoded").
+		SetFormData(map[string]string{
+			"appid":     conf.SUBMAIL_Sms_Appid,
+			"signature": conf.SUBMAIL_Sms_Signature,
+			"content":   content,
+		}).
+		SetResult(&TemplateRes{}).
+		Delete("https://api-v4.mysubmail.com/sms/multisend")
+
+	if err != nil {
+		return TemplateRes{}, err
+	}
+
+	temp := TemplateRes{}
+	if err = json.Unmarshal(resp.Body(), &temp); err != nil {
+		logs.Error(lib.FuncName(), err)
+		return TemplateRes{}, err
+	}
+	return temp, nil
+}
+
+// 短信模板发送
+func SmsXSend(template_id, to, name, time string) (XSendRes, error) {
+
+	type Vars struct {
+		Name string `json:"name"`
+		Time string `json:"time"`
+	}
+
+	vars := Vars{Name: name, Time: time}
+
+	b, _ := json.Marshal(vars)
+
+	client := resty.New()
+	resp, err := client.R().
+		SetHeader("Content-Type", "application/x-www-form-urlencoded").
+		SetFormData(map[string]string{
+			"appid":     conf.SUBMAIL_Sms_Appid,
+			"signature": conf.SUBMAIL_Sms_Signature,
+			"to":        to,
+			"project":   template_id,
+			"vars":      string(b),
+		}).
+		SetResult(&XSendRes{}).
+		Post("https://api-v4.mysubmail.com/sms/xsend")
+
+	if err != nil {
+		return XSendRes{}, err
+	}
+
+	temp := XSendRes{}
+	if err = json.Unmarshal(resp.Body(), &temp); err != nil {
+		logs.Error(lib.FuncName(), err)
+		return XSendRes{}, err
+	}
+	return temp, nil
+}
+
+func SmsXSendBill(to, name, moneyFlag string) (XSendRes, error) {
+
+	type Vars struct {
+		Name string `json:"name"`
+		Msg  string `json:"msg"`
+	}
+
+	vars := Vars{Name: name, Msg: moneyFlag}
+
+	b, _ := json.Marshal(vars)
+
+	client := resty.New()
+	resp, err := client.R().
+		SetHeader("Content-Type", "application/x-www-form-urlencoded").
+		SetFormData(map[string]string{
+			"appid":     conf.SUBMAIL_Sms_Appid,
+			"signature": conf.SUBMAIL_Sms_Signature,
+			"to":        to,
+			"project":   "LPdPa4",
+			"vars":      string(b),
+		}).
+		SetResult(&XSendRes{}).
+		Post("https://api-v4.mysubmail.com/sms/xsend")
+
+	if err != nil {
+		return XSendRes{}, err
+	}
+
+	temp := XSendRes{}
+	if err = json.Unmarshal(resp.Body(), &temp); err != nil {
+		logs.Error(lib.FuncName(), err)
+		return XSendRes{}, err
+	}
+	return temp, nil
+}

+ 55 - 0
http/submail/VoiceTemplate.go

@@ -0,0 +1,55 @@
+package submail
+
+import (
+	"FollowUp_Notice/conf"
+	"FollowUp_Notice/lib"
+	"FollowUp_Notice/logs"
+	"encoding/json"
+	"github.com/go-resty/resty/v2"
+)
+
+type VoiceXSendRes struct {
+	Status  string  `json:"status"`
+	Send_id string  `json:"send_id"`
+	Fee     float64 `json:"fee"`
+	Msg     string  `json:"msg"`
+	Code    string  `json:"code"`
+}
+
+// 语音模板发送
+func VoiceXSend(to, hospital, name, date string) (VoiceXSendRes, error) {
+
+	type Vars struct {
+		Hospital string `json:"hospital"`
+		Name     string `json:"name"`
+		Date     string `json:"date"`
+	}
+
+	vars := Vars{Hospital: hospital, Name: name, Date: date}
+
+	b, _ := json.Marshal(vars)
+
+	client := resty.New()
+	resp, err := client.R().
+		SetHeader("Content-Type", "application/x-www-form-urlencoded").
+		SetFormData(map[string]string{
+			"appid":     conf.SUBMAIL_Voice_Appid,
+			"signature": conf.SUBMAIL_Voice_Signature,
+			"to":        to,
+			"project":   conf.Voice_Project,
+			"vars":      string(b),
+		}).
+		SetResult(&VoiceXSendRes{}).
+		Post("https://api-v4.mysubmail.com/voice/xsend.json")
+
+	if err != nil {
+		return VoiceXSendRes{}, err
+	}
+
+	temp := VoiceXSendRes{}
+	if err = json.Unmarshal(resp.Body(), &temp); err != nil {
+		logs.Error(lib.FuncName(), err)
+		return VoiceXSendRes{}, err
+	}
+	return temp, nil
+}

+ 13 - 2
models/Account/User.go

@@ -98,11 +98,22 @@ func Add_User(r User) (id int64, err error) {
 	return id, err
 }
 
-// 获取 ById
+// 获取 ByT_uuId
 func Read_User_ByT_uuid(T_uuid string) (r User, err error) {
 	o := orm.NewOrm()
 	qs := o.QueryTable(new(User))
-	err = qs.Filter("T_uuid", T_uuid).One(&r)
+	err = qs.Filter("T_uuid", T_uuid).Filter("T_State__gt", 0).One(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+	return
+}
+
+// 获取 ById
+func Read_User_ByT_id(id int) (r User, err error) {
+	o := orm.NewOrm()
+	qs := o.QueryTable(new(User))
+	err = qs.Filter("Id", id).Filter("T_State__gt", 0).One(&r)
 	if err != nil {
 		logs.Error(lib.FuncName(), err)
 	}

+ 7 - 0
models/Illness/Illness.go

@@ -68,6 +68,13 @@ func Read_Illness_ById(Id int) (r Illness, err error) {
 	return
 }
 
+// 获取 ByT_name
+func ReadOrCreate_Illness(illness Illness) (id int64, err error) {
+	o := orm.NewOrm()
+	_, id, err = o.ReadOrCreate(&illness, "T_name", "T_uid", "T_State")
+	return
+}
+
 // 修改
 func Update_Illness(m Illness, cols ...string) error {
 	o := orm.NewOrm()

+ 39 - 1
models/Patient/Patient.go

@@ -11,6 +11,7 @@ import (
 	orm2 "github.com/beego/beego/v2/client/orm"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 )
 
@@ -67,9 +68,11 @@ func (t *Patient) TableName() string {
 	return "patient" // 数据库名称   // ************** 替换 FormulaList **************
 }
 
+var PatientMap *sync.Map // 泛型
 func init() {
 	//注册模型
 	orm.RegisterModel(new(Patient))
+	PatientMap = new(sync.Map)
 
 }
 func PatientToPatient_R(r Patient) (m Patient_R) {
@@ -131,7 +134,18 @@ func Add_Patient(r Patient) (id int64, err error) {
 func Read_Patient_ByT_uuid(T_uuid string) (r Patient, err error) {
 	o := orm.NewOrm()
 	qs := o.QueryTable(new(Patient))
-	err = qs.Filter("T_uuid", T_uuid).One(&r)
+	err = qs.Filter("T_uuid", T_uuid).Filter("T_State", 1).One(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+	return
+}
+
+// 获取 ById
+func Read_Patient_ById(Id int) (r Patient, err error) {
+	o := orm.NewOrm()
+	qs := o.QueryTable(new(Patient))
+	err = qs.Filter("Id", Id).Filter("T_State", 1).One(&r)
 	if err != nil {
 		logs.Error(lib.FuncName(), err)
 	}
@@ -239,3 +253,27 @@ func Read_Patient_List(T_uid int, T_number, T_name string, T_tag, T_illness, T_s
 
 	return r_, cnt
 }
+
+func Read_Patient_All_Map(T_uid int) {
+	o := orm.NewOrm()
+	// 也可以直接使用 Model 结构体作为表名
+	qs := o.QueryTable(new(Patient))
+	var maps []Patient
+	if T_uid > 0 {
+		qs.Filter("T_uid", T_uid).All(&maps)
+	} else {
+		qs.All(&maps)
+	}
+	for _, v := range maps {
+		PatientMap.Store(v.Id, v.T_name)
+	}
+}
+
+func Read_Patient_T_name_Get(T_pid int) string {
+	v, ok := PatientMap.Load(T_pid)
+	if ok {
+		return v.(string)
+	} else {
+		return ""
+	}
+}

+ 141 - 0
models/Patient/PatientSatisfaction.go

@@ -0,0 +1,141 @@
+package Patient
+
+import (
+	"FollowUp_Notice/lib"
+	"FollowUp_Notice/logs"
+	"github.com/beego/beego/v2/adapter/orm"
+	"time"
+)
+
+var (
+	Question1 = "初入病房时医护人员及时询问病情和检查"
+	Question2 = "是否有告知管床医生和护士是谁"
+	Question3 = "对住院期间入院注意事项的交代"
+	Question4 = "在住院期间,对病情的解释"
+	Question5 = "对医护人员的服务态度"
+)
+
+// 患者满意度
+type PatientSatisfaction struct {
+	Id          int    `orm:"column(ID);size(11);auto;pk"`
+	T_id        string `orm:"size(256);null"`       // 发送id
+	T_uid       int    `orm:"index;size(100);null"` // 用户id
+	T_pid       int    `orm:"index;size(100);null"` // 患者id
+	T_question1 string `orm:"size(256);null"`       // 问题1
+	T_question2 string `orm:"size(256);null"`       // 问题2
+	T_question3 string `orm:"size(256);null"`       // 问题3
+	T_question4 string `orm:"size(256);null"`       // 问题4
+	T_question5 string `orm:"size(256);null"`       // 问题5
+
+	CreateTime time.Time `orm:"column(create_time);type(timestamp);null;auto_now_add"` //auto_now_add 第一次保存时才设置时间
+}
+
+func (t *PatientSatisfaction) TableName() string {
+	return "patient_satisfaction" // 数据库名称   // ************** 替换 FormulaList **************
+}
+
+type PatientSatisfaction_R struct {
+	Id          int
+	T_id        string // 用户id
+	T_uid       int    // 用户id
+	T_pid       int    // 患者id
+	T_p_name    string // 患者名称
+	T_question1 string // 问题1
+	T_question2 string // 问题2
+	T_question3 string // 问题3
+	T_question4 string // 问题4
+	T_question5 string // 问题5
+	CreateTime  string //auto_now_add 第一次保存时才设置时间
+}
+
+func PatientSatisfactionToPatientSatisfaction_R(r PatientSatisfaction) (m PatientSatisfaction_R) {
+	m.Id = r.Id
+	m.T_id = r.T_id
+	m.T_uid = r.T_uid
+	m.T_pid = r.T_pid
+	m.T_p_name = Read_Patient_T_name_Get(r.T_pid)
+	m.T_question1 = r.T_question1
+	m.T_question2 = r.T_question2
+	m.T_question3 = r.T_question3
+	m.T_question4 = r.T_question4
+	m.T_question5 = r.T_question5
+	m.CreateTime = r.CreateTime.Format("2006-01-02 15:04:05")
+	return
+}
+
+func init() {
+	//注册模型
+	orm.RegisterModel(new(PatientSatisfaction))
+}
+
+// 获取 ById
+func Read_PatientSatisfaction_ByT_uid(T_uid int) (r []PatientSatisfaction, err error) {
+	o := orm.NewOrm()
+	qs := o.QueryTable(new(PatientSatisfaction))
+	_, err = qs.Filter("T_uid", T_uid).All(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+	return
+}
+
+// 获取 ById
+func Read_PatientSatisfaction_List(T_uid int, page, page_z int) (r_ []PatientSatisfaction_R, cnt int64) {
+	o := orm.NewOrm()
+	qs := o.QueryTable(new(PatientSatisfaction))
+	var offset int64
+	if page <= 1 {
+		offset = 0
+	} else {
+		offset = int64((page - 1) * page_z)
+	}
+	var r []PatientSatisfaction
+	_, err := qs.Limit(page_z, offset).Filter("T_uid", T_uid).OrderBy("-Id").All(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+	cnt, err = qs.Filter("T_uid", T_uid).Count()
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+
+	for _, v := range r {
+		r_ = append(r_, PatientSatisfactionToPatientSatisfaction_R(v))
+	}
+
+	return
+}
+
+// 添加
+func Add_PatientSatisfaction(r PatientSatisfaction) (id int64, err error) {
+	o := orm.NewOrm()
+	qs := o.QueryTable(new(PatientSatisfaction))
+	var obj PatientSatisfaction
+	err = qs.Filter("T_id", r.T_id).One(&obj)
+	if err != nil && err.Error() == orm.ErrNoRows.Error() {
+		id, err = o.Insert(&r)
+		if err != nil {
+			logs.Error(lib.FuncName(), err)
+		}
+		return
+	}
+	if obj.Id > 0 {
+		r.Id = obj.Id
+		_, err := o.Update(&r, "T_question1", "T_question2", "T_question3", "T_question4", "T_question5")
+		if err != nil {
+			logs.Error(lib.FuncName(), err)
+		}
+	}
+	return int64(r.Id), err
+}
+
+// 获取 ById
+func Read_PatientSatisfaction_ByT_id(T_id string) (r PatientSatisfaction, err error) {
+	o := orm.NewOrm()
+	qs := o.QueryTable(new(PatientSatisfaction))
+	err = qs.Filter("T_id", T_id).One(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+	return
+}

+ 13 - 11
models/Patient/PatientSend.go

@@ -11,16 +11,18 @@ import (
 
 // 患者信息发送
 type PatientSend struct {
-	Id         int       `orm:"column(ID);size(11);auto;pk"`
-	T_uid      int       `orm:"index;size(100);null"`                                  // 用户id
-	T_pid      int       `orm:"index;size(100);null"`                                  // 患者id
-	T_phone    string    `orm:"size(256);null"`                                        // 患者电话 18888888888
-	T_type     int       `orm:"index;size(4);null"`                                    // 1 短信 2 电话
-	T_id       string    `orm:"size(256);null"`                                        // 发送id
-	T_code     int       `orm:"size(256);null"`                                        // 错误码
-	T_remark   string    `orm:"size(256);null"`                                        // 备注
-	T_State    int       `orm:"size(200);default(1)"`                                  // 0失败 1正常
-	CreateTime time.Time `orm:"column(create_time);type(timestamp);null;auto_now_add"` //auto_now_add 第一次保存时才设置时间
+	Id          int       `orm:"column(ID);size(11);auto;pk"`
+	T_uid       int       `orm:"index;size(100);null"`                                  // 用户id
+	T_pid       int       `orm:"index;size(100);null"`                                  // 患者id
+	T_phone     string    `orm:"size(256);null"`                                        // 患者电话 18888888888
+	T_type      int       `orm:"index;size(4);null"`                                    // 1 短信 2 电话 3 电话满意度调查
+	T_id        string    `orm:"size(256);null"`                                        // 发送id
+	T_code      string    `orm:"size(256);null"`                                        // 错误码
+	T_fee       float64   `orm:"digits(12);decimals(2)"`                                // 错误码
+	T_remark    string    `orm:"size(256);null"`                                        // 备注
+	T_State     int       `orm:"size(200);default(1)"`                                  // 0失败 1正常
+	T_digitInfo string    `orm:"size(200)"`                                             // 满意度调查 放音收号结果
+	CreateTime  time.Time `orm:"column(create_time);type(timestamp);null;auto_now_add"` //auto_now_add 第一次保存时才设置时间
 }
 type PatientSend_R struct {
 	Id         int
@@ -28,7 +30,7 @@ type PatientSend_R struct {
 	T_phone    string // 18888888888
 	T_type     int    // 1 短信   2 电话
 	T_id       string
-	T_code     int
+	T_code     string
 	T_remark   string // 备注
 	T_State    int
 	CreateTime string //auto_now_add 第一次保存时才设置时间

+ 7 - 0
models/Surgical/Surgical.go

@@ -69,6 +69,13 @@ func Read_Surgical_ById(Id int) (r Surgical, err error) {
 	return
 }
 
+// 获取 ByT_name
+func ReadOrCreate_Surgical(surgical Surgical) (id int64, err error) {
+	o := orm.NewOrm()
+	_, id, err = o.ReadOrCreate(&surgical, "T_name", "T_uid", "T_State")
+	return
+}
+
 // 修改
 func Update_Surgical(m Surgical, cols ...string) error {
 	o := orm.NewOrm()

+ 7 - 0
models/Tag/Tag.go

@@ -68,6 +68,13 @@ func Read_Tag_ById(Id int) (r Tag, err error) {
 	return
 }
 
+// 获取 ByT_name
+func ReadOrCreate_Tag(tag Tag) (id int64, err error) {
+	o := orm.NewOrm()
+	_, id, err = o.ReadOrCreate(&tag, "T_name", "T_uid", "T_State")
+	return
+}
+
 // 修改
 func Update_Tag(m Tag, cols ...string) error {
 	o := orm.NewOrm()

+ 3 - 0
routers/Account.go

@@ -21,6 +21,9 @@ func init() {
 	beego.Router("/User/Send_Excel", &controllers.UserController{}, "*:Send_Excel") // 通知下载
 	beego.Router("/User/Send_Test", &controllers.UserController{}, "*:Send_Test")   // 测试通知
 
+	beego.Router("/User/Satisfaction_Stats", &controllers.UserController{}, "*:Satisfaction_Stats") // 满意度调查统计
+	beego.Router("/User/Satisfaction_List", &controllers.UserController{}, "*:Satisfaction_List")   // 满意度调查列表
+
 	beego.Router("/Wx/Get_QR_Code", &controllers.UserController{}, "*:Get_Weixin_QR_Code") // 获取微信支付二维码
 	beego.Router("/Wx/Notify", &controllers.UserController{}, "*:Weixin_Notify")           // 获取微信支付二维码
 	beego.Router("/Wx/GetOrderState", &controllers.UserController{}, "*:GetWxOrderState")  // 获取微信支付状态

+ 8 - 4
routers/Patient.go

@@ -8,10 +8,14 @@ import (
 func init() {
 
 	illness := beego.NewNamespace("/Patient",
-		beego.NSRouter("/List", &controllers.PatientController{}, "*:Patient_List"), // 患者列表
-		beego.NSRouter("/Add", &controllers.PatientController{}, "*:Patient_Add"),   // 获取患者
-		beego.NSRouter("/Edit", &controllers.PatientController{}, "*:Patient_Edit"), // 添加患者
-		beego.NSRouter("/Del", &controllers.PatientController{}, "*:Patient_Del"),   // 删除患者
+		beego.NSRouter("/List", &controllers.PatientController{}, "*:Patient_List"),                           // 患者列表
+		beego.NSRouter("/Add", &controllers.PatientController{}, "*:Patient_Add"),                             // 获取患者
+		beego.NSRouter("/Edit", &controllers.PatientController{}, "*:Patient_Edit"),                           // 添加患者
+		beego.NSRouter("/Del", &controllers.PatientController{}, "*:Patient_Del"),                             // 删除患者
+		beego.NSRouter("/Import", &controllers.PatientController{}, "*:Patient_Import"),                       // 删除患者
+		beego.NSRouter("/ExportTemplate", &controllers.PatientController{}, "*:Patient_ExportTemplate"),       // 删除患者
+		beego.NSRouter("/Satisfaction_PDF", &controllers.PatientController{}, "*:VoiceCall_Satisfaction_PDF"), // 删除患者
+		beego.NSRouter("/Send_Satisfaction", &controllers.PatientController{}, "*:Patient_Send_Satisfaction"), // 删除患者
 	)
 
 	beego.AddNamespace(illness)

BIN
static/fonts/三极行楷简体-粗.ttf


BIN
static/fonts/经典宋体简.ttf