package main

import (
	"fmt"
	"io"
	"net/http"

	"encoding/json"

	"strconv"

	"io/ioutil"

	"time"

	"database/sql"

	"strings"

	_ "github.com/mattn/go-adodb"
	//	"golang.org/x/net/websocket"

	//_ "github.com/denisenkom/go-mssqldb"

	//_ "deescloud/odbc/driver"
	//_ "github.com/alexbrainman/odbc"
	//_ "gitlab.com/stone.code/odbc3-go"
	//_ "github.com/weigj/go-odbc"-->deescloud/odbc/driver
	_ "github.com/LukeMauldin/lodbc"

	"kpi/ModulePath"

	"os"

	"sync"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"

	_ "github.com/mattn/go-sqlite3"
	uuid "github.com/satori/go.uuid"

	"encoding/csv"
	//_ "net/http/pprof"
	//	"runtime"
	//	"github.com/shopspring/decimal"
	"github.com/tealeg/xlsx"
)

/*
go-adodb ---cache leak

github.com/weigj/go-odbc  ---查询处理特殊字符有问题

github.com/alexbrainman/odbc ---sqlserver读取汉字乱码(编码格式没有转换)


*/

func testAdo() {
	var conf []string
	var db *sql.DB
	var err error
	conf = append(conf, "Provider=SQLOLEDB")
	conf = append(conf, "Data Source=127.0.0.1,1433")          // sqlserver IP 和 服务器名称
	conf = append(conf, "Initial Catalog=WellNameInformation") // 数据库名
	conf = append(conf, "user id=sa")                          // 登陆用户名
	conf = append(conf, "password=lh123456")                   // 登陆密码
	fmt.Println(strings.Join(conf, ";"))
	db, err = sql.Open("adodb", strings.Join(conf, ";"))
	if err != nil {
		fmt.Println("sql open:", err)
		return
	} else {

	}
	defer db.Close()

	beginTime := time.Now()
	// 执行SQL语句
	rows, err := db.Query("select [6506] from [AUTHINFO] order by ID")
	if err != nil {
		fmt.Println("query: ", err)
		return
	}
	for rows.Next() {
		var id float32

		rows.Scan(&id)
		fmt.Println("id: ", id)
	}

	defer rows.Close()

	fmt.Println(fmt.Sprintf("use time:%v", (time.Now().UnixNano()-beginTime.UnixNano())/1e6))
}

// 2008是要升级sqlserver数据库的补丁的，不建议使用。
func testMssqldb() {
	var server = "127.0.0.1"
	port := 1433
	var user = "sa"
	var password = "lh123456"
	var database = "WellNameInformation"

	//连接字符串
	connString := fmt.Sprintf("server=%s;port%d;database=%s;user id=%s;password=%s", server, port, database, user, password)
	fmt.Println(connString)

	//建立连接
	db, err := sql.Open("mssql", connString)
	if err != nil {
		fmt.Println("Open Connection failed:", err.Error())
	}
	defer db.Close()

	//通过连接对象执行查询
	rows, err := db.Query(`select ID from WellInformation order by ID`)
	if err != nil {
		fmt.Println("Query failed:", err.Error())
		return
	}
	defer rows.Close()

	for rows.Next() {
		var id int64

		rows.Scan(&id)
		fmt.Printf("id: %d \n", id)
	}

}

func testOdbc() {
	conn, err := sql.Open("odbc", "driver={SQL Server};SERVER=127.0.0.1;UID=sa;PWD=lh123456?;DATABASE=WellNameInformation")
	if err != nil {
		fmt.Println("Connecting Error", err.Error())
		return
	} else {
		fmt.Println("connect success!")
	}

	defer conn.Close()

	beginTime := time.Now()
	stmt, err := conn.Prepare("select ID from [WellNameInformation].[dbo].[WellInformation] order by ID")
	if err != nil {
		fmt.Println("Query Error", err)
		return
	}
	defer stmt.Close()
	row, err := stmt.Query()
	if err != nil {
		fmt.Println("Query Error", err)
		return
	}
	defer row.Close()

	cnt := 0
	for row.Next() {
		var id int
		if err := row.Scan(&id); err == nil {
			//fmt.Println(id)

			cnt++
		}
	}

	fmt.Println("record len:", cnt)

	fmt.Println(fmt.Sprintf("use time:%v", (time.Now().UnixNano()-beginTime.UnixNano())/1e6))

	fmt.Printf("%s\n", "finish")
	return
}

var (
	server   string
	port     int
	user     string
	password string
	database string

	sqlConn *sql.DB
	//odbcConn *sql.DB

	//user
	refreshSpan    int64
	ExpireTimeSpan time.Duration

	modelePath string

	mu sync.Mutex

	p_lock     sync.Mutex
	p_import_f int

	plan_file_lock   sync.Mutex
	plan_file_lock_n int

	ch_kpi chan kpi

	ds_file_lock   sync.Mutex
	ds_file_lock_n int

	g_loc string = "2006-01-02 15:04:05"
)

func initLog() {

	beego.BeeLogger.DelLogger("console")

	var err error
	modelePath, err = ModulePath.GetModuleCurrentPath()
	if err != nil {
		fmt.Println("ModulePath.GetModuleCurrentPath() failed err:", err.Error())
		return
	}

	fmt.Println("modelePath:", modelePath)

	config := make(map[string]interface{})
	config["filename"] = modelePath + string("/logs/kpi.log")
	config["level"] = 7
	config["maxlines"] = 0
	config["maxsize"] = 50 * 1024 * 1024 //50M
	config["daily"] = true
	config["maxdays"] = 10

	configJsonStr, err := json.Marshal(config)
	if err != nil {
		fmt.Println("package main init json.Marshal(config) failed,err:", err.Error())
		os.Exit(-1)
	}

	logs.SetLogger(logs.AdapterFile, string(configJsonStr))
}

func initSqlPool(driverType string) {

	if driverType == "ado" {
		var conf []string
		var err error
		conf = append(conf, "Provider=SQLOLEDB")
		conf = append(conf, fmt.Sprintf("Data Source=%s,%d", server, port)) // sqlserver IP 和 服务器名称
		conf = append(conf, fmt.Sprintf("Initial Catalog=%s", database))    // 数据库名
		conf = append(conf, fmt.Sprintf("user id=%s", user))                // 登陆用户名
		conf = append(conf, fmt.Sprintf("password=%s", password))           // 登陆密码
		fmt.Println(strings.Join(conf, ";"))
		sqlConn, err = sql.Open("adodb", strings.Join(conf, ";"))
		if err != nil {
			fmt.Println("sql open:", err.Error())
			os.Exit(0)
		} else {
			fmt.Println("connect success!")
		}

	} else {
		dataSource := fmt.Sprintf("driver={SQL Server};SERVER=%s;UID=%s;PWD=%s;DATABASE=%s", server, user, password, database)
		fmt.Println(dataSource)

		var err error
		sqlConn, err = sql.Open("lodbc", dataSource)
		if err != nil {
			fmt.Println("sql open:", err.Error())
			os.Exit(0)
		} else {
			logs.Info("connect success!")
		}
	}

	sqlConn.SetMaxOpenConns(10)
	sqlConn.SetMaxIdleConns(5)

	/*
		var err error
		dataSource := fmt.Sprintf("driver={SQL Server};SERVER=%s;UID=%s;PWD=%s;DATABASE=%s", server, user, password, database)
		fmt.Println(dataSource)


			odbcConn, err = sql.Open("lodbc", dataSource)
			if err != nil {
				fmt.Println("sql open:", err.Error())
				os.Exit(0)
			} else {
				logs.Info("connect success!")
			}

			odbcConn.SetMaxOpenConns(10)
			odbcConn.SetMaxIdleConns(5)
	*/
}

func getConn(db string) (conn *sql.DB, err error) {
	var conf []string
	conf = append(conf, "Provider=SQLOLEDB")
	conf = append(conf, fmt.Sprintf("Data Source=%s,%d", server, port)) // sqlserver IP 和 服务器名称
	conf = append(conf, fmt.Sprintf("Initial Catalog=%s", db))          // 数据库名
	conf = append(conf, fmt.Sprintf("user id=%s", user))                // 登陆用户名
	conf = append(conf, fmt.Sprintf("password=%s", password))           // 登陆密码
	//fmt.Println(strings.Join(conf, ";"))
	conn, err = sql.Open("adodb", strings.Join(conf, ";"))
	if err != nil {
		fmt.Println("sql open:", err.Error())
		logs.Error("sql open:", err.Error())
		return
	}

	conn.SetMaxIdleConns(1)
	conn.SetMaxOpenConns(2)

	return
}

func getOdbcConn(db string) (conn *sql.DB, err error) {

	dataSource := fmt.Sprintf("driver={SQL Server};SERVER=%s;UID=%s;PWD=%s;DATABASE=%s", server, user, password, db)
	fmt.Println(dataSource)

	conn, err = sql.Open("lodbc", dataSource)
	if err != nil {
		logs.Error("sql open:", err.Error())
		return
	}

	conn.SetMaxOpenConns(2)
	conn.SetMaxIdleConns(1)

	return
}

func fileServerG() {
	//http.Handle("/file", http.FileServer(http.Dir("D:/rk/golang/procs/deescloud")))
	http.Handle("/file/", http.StripPrefix("/file/", http.FileServer(http.Dir(modelePath+"/file"))))
	err := http.ListenAndServe("0.0.0.0:8885", nil)
	if err != nil {
		fmt.Print(err)
	}
}

func uploadFile() {
	http.Handle("/upload/", http.StripPrefix("/upload/", http.FileServer(http.Dir(modelePath+"/upload"))))
	err := http.ListenAndServe("0.0.0.0:8886", nil)
	if err != nil {
		fmt.Print(err)
	}
}

func message_g() {

	for {
		select {
		case v := <-ch_kpi:

			jdata, _ := json.Marshal(v)
			users, _ := get_all_user()
			for i := 0; i < len(users); i++ {
				if users[i].DepartmentId != 1 {
					continue
				}

				if users[i].State != "状态1" {
					continue
				}

				sqlstr := fmt.Sprintf(`INSERT INTO [message]
					           ([user_name]
					           ,[data])
					     VALUES
					           ('%s'
					           ,'%s')`, users[i].Username, string(jdata))
				_, err := sqlConn.Exec(sqlstr)
				if err != nil {
					logs.Error("INSERT INTO [message] err:", err.Error())
				}
			}
		default:
			time.Sleep(time.Second * 5)
		}
	}

}

func init() {

	refreshSpan = 5 //5s

	ExpireTimeSpan = time.Second * 43200 //12小时

	initLog()

	server = beego.AppConfig.String("server")
	port, _ = beego.AppConfig.Int("port")
	user = beego.AppConfig.String("user")
	password = beego.AppConfig.String("password")
	database = beego.AppConfig.String("database")

	initSqlPool("odbc")

}

func main() {

	ch_kpi = make(chan kpi, 1000)

	go sync_file_cache()

	go checkFileExpired()

	//fileserver
	go fileServerG()

	go uploadFile()

	go message_g()

	http.HandleFunc("/test", test)

	http.HandleFunc("/pkpi/login", Login)
	http.HandleFunc("/pkpi/loginOut", LoginOut)
	http.HandleFunc("/pkpi/refreshUser", refreshUser)

	http.HandleFunc("/pkpi/getMenu", getMenu)

	http.HandleFunc("/pkpi/getUsers", getUsers)
	http.HandleFunc("/pkpi/postUser", postUser)

	http.HandleFunc("/pkpi/addkpi", addKpi)
	http.HandleFunc("/pkpi/getkpi", getKpi)
	http.HandleFunc("/pkpi/getPrekpi", getPrekpi)
	http.HandleFunc("/pkpi/getHistoryPrekpi", getHistoryPrekpi)

	http.HandleFunc("/pkpi/importKpi", importKpi)
	http.HandleFunc("/pkpi/importPreTaskKpi", importPreTaskKpi)
	http.HandleFunc("/pkpi/importPreKpi", importPreKpi)
	http.HandleFunc("/pkpi/updatekpi_5", updatekpi_5)

	http.HandleFunc("/pkpi/updatekpi_3", updatekpi_3)
	http.HandleFunc("/pkpi/updatekpi_3_ex", updatekpi_3_ex)
	http.HandleFunc("/pkpi/updatekpi_1", updatekpi_1)
	http.HandleFunc("/pkpi/updatekpi_1_ex", updatekpi_1_ex)

	http.HandleFunc("/pkpi/updatekpi_2", updatekpi_2)
	http.HandleFunc("/pkpi/updatePrekpi", updatePrekpi)

	http.HandleFunc("/pkpi/delKpi", delKpi)
	http.HandleFunc("/pkpi/delPreKpi", delPreKpi)

	http.HandleFunc("/pkpi/task_transfer", task_transfer)

	http.HandleFunc("/pkpi/preTask_transfer", preTask_transfer)

	http.HandleFunc("/pkpi/task_finished", task_finished)

	http.HandleFunc("/pkpi/getkpihis", getKpiUpdateHistory)

	http.HandleFunc("/pkpi/exportKpi", exportKpi)
	http.HandleFunc("/pkpi/exportKpi_ex", exportKpi_ex)

	http.HandleFunc("/pkpi/getUserNames", getUserNames)

	http.HandleFunc("/pkpi/getpUsers", getpUsers)
	http.HandleFunc("/pkpi/postpUser", postpUser)

	http.HandleFunc("/pkpi/getbUsers", getbUsers)
	http.HandleFunc("/pkpi/postbUser", postbUser)

	http.HandleFunc("/pkpi/download_template_file", download_template_file)
	http.HandleFunc("/pkpi/download_pre_template_file", download_pre_template_file)

	http.HandleFunc("/pkpi/get_p", get_p)
	http.HandleFunc("/pkpi/post_p", post_p)
	http.HandleFunc("/pkpi/del_p", del_p)
	http.HandleFunc("/pkpi/import_p", import_p)

	http.HandleFunc("/pkpi/import_plan_t", import_plan_t)

	http.HandleFunc("/pkpi/get_p_id_options", get_p_id_options)
	http.HandleFunc("/pkpi/get_options_byId", get_options_byId)

	http.HandleFunc("/pkpi/get_p_process_options", get_p_process_options)

	http.HandleFunc("/pkpi/export_sap", export_sap)

	http.HandleFunc("/pkpi/get_del_kpi_his", get_del_kpi_his)

	http.HandleFunc("/pkpi/export_transfer_history", export_transfer_history)

	http.HandleFunc("/pkpi/get_cur_did_from_task", get_cur_did_from_task)

	http.HandleFunc("/pkpi/mul_update_kpi_1", mul_update_kpi_1)

	http.HandleFunc("/pkpi/import_pf", import_plan_file)
	http.HandleFunc("/pkpi/get_pf", get_pf)
	http.HandleFunc("/pkpi/del_pf", del_pf)

	http.HandleFunc("/pkpi/upload", upload_process_file)
	http.HandleFunc("/pkpi/upload_pf", upload_project_file)

	http.HandleFunc("/pkpi/update_notes_1", update_notes_1)

	http.HandleFunc("/pkpi/export_plan_collect", export_plan_collect)

	http.HandleFunc("/pkpi/get_message", get_message)
	http.HandleFunc("/pkpi/message_mark", message_mark)

	http.HandleFunc("/pkpi/get_ds", get_ds)
	http.HandleFunc("/pkpi/import_ds_file", import_ds_file)
	http.HandleFunc("/pkpi/del_ds", del_ds)
	http.HandleFunc("/pkpi/upload_ds_file", upload_ds_file)
	http.HandleFunc("/pkpi/download_ds_file", download_ds_file)

	http.HandleFunc("/pkpi/postimn", postimn)
	http.HandleFunc("/pkpi/get_imn", get_imn)
	http.HandleFunc("/pkpi/del_imn", del_imn)
	http.HandleFunc("/pkpi/get_ibase", get_ibase)
	http.HandleFunc("/pkpi/postibase", postibase)
	http.HandleFunc("/pkpi/del_ibase", del_ibase)
	http.HandleFunc("/pkpi/export_ibase", export_ibase)
	http.HandleFunc("/pkpi/import_ibase", import_ibase)
	http.HandleFunc("/pkpi/get_ibase_op_history", get_ibase_op_history)
	http.HandleFunc("/pkpi/get_inspection_op_history", get_inspection_op_history)
	http.HandleFunc("/pkpi/export_inspection", export_inspection)

	http.HandleFunc("/pkpi/get_p_name_options", get_p_name_options)

	http.HandleFunc("/pkpi/post_inspection", post_inspection)
	http.HandleFunc("/pkpi/get_inspection", get_inspection)
	http.HandleFunc("/pkpi/del_inspection", del_inspection)

	http.HandleFunc("/pkpi/get_report_multi_template", get_report_multi_template)
	http.HandleFunc("/pkpi/get_ledger", get_ledger)
	http.HandleFunc("/pkpi/del_ledger", del_ledger)
	http.HandleFunc("/pkpi/post_report", post_report_m)
	http.HandleFunc("/pkpi/post_report_s", post_report_s)
	http.HandleFunc("/pkpi/upload_report_file", upload_report_file)
	http.HandleFunc("/pkpi/download_report_file", download_report_file)

	http.HandleFunc("/pkpi/export_not_completed_Kpi", export_not_completed_Kpi)
	http.HandleFunc("/pkpi/export_completed_Kpi", export_completed_Kpi)

	http.HandleFunc("/pkpi/getPrePlanMess", getPrePlanMess)
	http.HandleFunc("/pkpi/ConfirmBaseData", ConfirmBaseData)

	// ==================== 08/28 添加操作日志  start ====================
	http.HandleFunc("/pkpi/add_operation_log", add_operation_log)
	http.HandleFunc("/pkpi/get_operation_log", get_operation_log)
	http.HandleFunc("/pkpi/del_operation_log", del_operation_log)
	http.HandleFunc("/pkpi/get_operation_log_user", get_operation_log_user)
	http.HandleFunc("/pkpi/export_operation_log", export_operation_log)
	// ==================== 08/28 添加操作日志  end ====================

	//监听服务
	fmt.Println("listen server ...")
	err := http.ListenAndServe("0.0.0.0:8884", nil)
	if err != nil {
		fmt.Println("服务器错误")
	}

}

func download_ds_file(rw http.ResponseWriter, r *http.Request) {
	//获取请求参数
	/*var req download_file_req
	reqdata, _ := ioutil.ReadAll(r.Body)
	json.Unmarshal(reqdata, &req)

	fn := req.Filename*/

	filename := r.FormValue("id")
	base_file_path := modelePath + "/upload_ds/"

	if filename != "" {
		//设置响应头
		header := rw.Header()
		header.Add("Content-Type", "application/octet-stream")
		//header.Add("Content-Disposition", "attachment;filename="+fn)
		//使用ioutil包读取文件
		filepath := base_file_path + filename
		fmt.Println(filepath)
		b, _ := ioutil.ReadFile(filepath)

		//写入到响应流中
		rw.Write(b)
	}

}

// 上传文件
func upload_ds_file(w http.ResponseWriter, r *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("upload_ds_file recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp upload_resp
	var f *os.File
	var err error

	//var rdRow *sql.Rows
	//var d plan_file

	var sqlstr string

	//配置文件读取
	base_file_path := modelePath + "/upload_ds/"

	r.ParseMultipartForm(32 << 20)

	id, _ := strconv.Atoi(r.Form.Get("id"))
	//fmt.Println("id:", id)

	upload_user := r.Form.Get("archive_user")

	//读取文件信息
	file, handler, err := r.FormFile("file")
	if err != nil {
		fmt.Println(err)
		resp.Ret = -1
		goto exit
	}
	defer file.Close()
	fmt.Println(handler.Filename)
	logs.Info(base_file_path + handler.Filename)
	if handler.Filename == "" {
		resp.Ret = -1
		goto exit
	}
	os.Remove(base_file_path + handler.Filename)
	f, err = os.OpenFile(base_file_path+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println(err)
		goto exit
	}
	defer f.Close()
	io.Copy(f, file)

	resp.Ret = 0

	//update record process file info
	sqlstr = fmt.Sprintf(`UPDATE [ds_file]
  				 SET [file] = '%s'
				,[archive_user] = '%s'
      			,[archive_time] = '%s'
				,[op_time]='%s'
				where ID=%d`, handler.Filename, upload_user,
		time.Now().Format("2006-01-02"), time.Now().Format("2006-01-02 15:04:05"), id)
	fmt.Println(sqlstr)

	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("upload_ds_file exec err:%v", err.Error()))
		goto exit
	}

	file_ch <- 1

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintln(w, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("upload_ds_file recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func del_ds(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("del_ds recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var err error
	var resp del_ds_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req del_ds_req
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Ids); i++ {
		sqlstr := fmt.Sprintf(`DELETE FROM [ds_file] where ID=%d`, req.Ids[i].ID)
		fmt.Println(sqlstr)

		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("del_ds Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("del_ds recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func import_ds_file(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("import_ds_file recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var p_flag int

	var reqdata []byte
	var req import_ds_file_Req
	var resp import_ds_file_Resp
	var b bool

	ds_file_lock.Lock()
	p_flag = ds_file_lock_n
	ds_file_lock.Unlock()

	if p_flag == 1 {
		resp.Ret = 1
		goto exit
	} else {
		ds_file_lock.Lock()
		ds_file_lock_n = 1
		ds_file_lock.Unlock()
	}

	reqdata, _ = ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b = checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Data); i++ {
		var id int

		sqlstr := fmt.Sprintf(`SELECT ID from [ds_file] where p_id='%s' and [serial_num]='%s'`, req.Data[i].P_id, req.Data[i].Serial_num)
		fmt.Println(sqlstr)
		rows, err := sqlConn.Query(sqlstr)
		if err != nil {
			logs.Error(fmt.Sprintf(`%s err:%s`, sqlstr, err.Error()))
			resp.Ret = -1
			goto exit
		}

		for rows.Next() {
			if err := rows.Scan(&id); err != nil {
				logs.Error(fmt.Sprintf(`%s scan err:%s`, sqlstr, err.Error()))
				resp.Ret = -1
				goto exit
			}
		}
		rows.Close()

		if id == 0 {
			sqlstr = fmt.Sprintf(`INSERT INTO [ds_file] ([p_id],[p_name],[serial_num],[op_time])
     		VALUES ('%s','%s','%s','%s')`, req.Data[i].P_id, req.Data[i].P_name, req.Data[i].Serial_num,
				time.Now().Format(g_loc))
		} else {
			sqlstr = fmt.Sprintf(`UPDATE [ds_file]
   				SET [p_id] = '%s'
      			,[p_name] = '%s',[serial_num]='%s', [op_time]='%s'  
				 WHERE ID=%d`, req.Data[i].P_id, req.Data[i].P_name, req.Data[i].Serial_num, time.Now().Format(g_loc),
				id)
		}

		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("import_ds_file Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}
	}

	resp.Ret = 0

exit:

	if resp.Ret == 0 {
		ds_file_lock.Lock()
		ds_file_lock_n = 0
		ds_file_lock.Unlock()
	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("import_ds_file recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_ds(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("get_ds recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_ds_req
	var resp get_ds_resp

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	var where_sql string
	var if_where bool

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		goto exit
	}

	if req.P_id != "" {
		likeStr := "%" + req.P_id + "%"
		where_sql += fmt.Sprintf(`[p_id] like '%s'`, likeStr)
		if_where = true
	}

	if req.P_name != "" {
		likeStr := "%" + req.P_name + "%"
		where_sql += fmt.Sprintf(`[p_name] like '%s'`, likeStr)
		if_where = true
	}

	if if_where {
		sqlstr = fmt.Sprintf("SELECT [ID],[p_id],[p_name],[serial_num],[file],[archive_user],[archive_time] FROM [ds_file] where %s order by [ID] desc", where_sql)
	} else {
		sqlstr = fmt.Sprintf("SELECT [ID],[p_id],[p_name],[serial_num],[file],[archive_user],[archive_time] FROM [ds_file] order by [ID] desc")
	}
	logs.Info(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_ds Query err:%v", err.Error()))
		goto exit
	}

	for rdRow.Next() {
		var d ds_file
		if err := rdRow.Scan(&d.ID, &d.P_id, &d.P_name, &d.Serial_num, &d.File, &d.Archive_user, &d.Archive_time); err == nil {
			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_ds scan Error", err.Error())
		}
	}
	rdRow.Close()

exit:

	resp.Total = len(resp.Data)
	if resp.Total == 0 {
		resp.Data = []ds_file{}
	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_ds recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func message_mark(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("message_mark recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req message_mark_req
	var resp CommonResp

	var sqlstr string
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	logs.Info(string(reqdata))
	logs.Info(req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		goto exit
	}

	sqlstr = fmt.Sprintf("delete from [message] where [user_name]='%s'", req.OpUser)
	logs.Info(sqlstr)
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		resp.Ret = -1
	}

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("message_mark recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_message(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("get_message recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_message_req
	var resp getKpiResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	logs.Info(string(reqdata))
	logs.Info(req)

	// 提前声明所有变量
	var (
		rows       *sql.Rows
		err        error
		startRow   int
		endRow     int
		sqlstr     string
		countSql   string
		totalCount int
	)

	// 检查用户是否在线
	if !checkUserIfOnline(req.OpUser, req.OpUserUuid) {
		logs.Info(fmt.Sprintf("用户 %s 不在线", req.OpUser))
		goto exit
	}

	// 计算分页范围
	startRow = (req.Page-1)*req.PageSize + 1
	endRow = req.Page * req.PageSize

	// 构建分页 SQL
	sqlstr = fmt.Sprintf(`
        WITH CTE AS (
            SELECT [data], ROW_NUMBER() OVER(ORDER BY [ID] DESC) AS RowNum 
            FROM [message] 
            WHERE [user_name]='%s'
        ) 
        SELECT [data] 
        FROM CTE 
        WHERE RowNum BETWEEN %d AND %d`,
		req.OpUser, startRow, endRow)

	logs.Info(sqlstr)
	fmt.Println("SQL:", sqlstr)

	// 执行查询
	rows, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_message Query err: %v", err.Error()))
		goto exit
	}

	// 在分页查询前添加总记录数查询
	countSql = fmt.Sprintf("SELECT COUNT(id) FROM [message] WHERE [user_name]='%s'", req.OpUser)
	err = sqlConn.QueryRow(countSql).Scan(&totalCount)
	if err != nil {
		logs.Error(fmt.Sprintf("get_message count query err: %v", err.Error()))
		goto exit
	}
	resp.Total = totalCount

	defer rows.Close()

	// 解析数据
	for rows.Next() {
		var v string
		if err := rows.Scan(&v); err != nil {
			logs.Error("get_message scan Error", err.Error())
			continue
		}

		var d kpi
		if err := json.Unmarshal([]byte(v), &d); err != nil {
			logs.Error("get_message json.Unmarshal Error", err.Error())
			continue
		}

		if len(d.Demand_date) > 2 {
			d.Demand_date = d.Demand_date[2:]
		}

		resp.Data = append(resp.Data, d)
	}

exit:
	// resp.Total = len(resp.Data)
	if resp.Total == 0 {
		resp.Data = []kpi{}
	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_message recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func upload_project_file(w http.ResponseWriter, r *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("upload_project_file recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp upload_resp
	var f *os.File
	var err error

	//var rdRow *sql.Rows
	//var d plan_file

	var sqlstr string

	//配置文件读取
	base_file_path := modelePath + "/upload/"

	r.ParseMultipartForm(32 << 20)

	id, _ := strconv.Atoi(r.Form.Get("id"))
	fmt.Println("id:", id)

	//读取文件信息
	file, handler, err := r.FormFile("file")
	if err != nil {
		fmt.Println(err)
		resp.Ret = -1
		goto exit
	}
	defer file.Close()
	fmt.Println(handler.Filename)
	fmt.Println(base_file_path + handler.Filename)
	if handler.Filename == "" {
		resp.Ret = -1
		goto exit
	}
	os.Remove(base_file_path + handler.Filename)
	f, err = os.OpenFile(base_file_path+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println(err)
		goto exit
	}
	defer f.Close()
	io.Copy(f, file)

	resp.Ret = 0

	//update record process file info
	sqlstr = fmt.Sprintf(`UPDATE [plan_file]
  				 SET [project_file] = '%s'
      			,[p_filing_time] = '%s'
				,[op_time]='%s'
				where ID=%d`, handler.Filename, time.Now().Format("2006-01-02"), time.Now().Format("2006-01-02 15:04:05"),
		id)
	fmt.Println(sqlstr)

	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("upload_project_file exec err:%v", err.Error()))
		goto exit
	}

	file_ch <- 1

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintln(w, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("upload_project_file recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

// 上传文件
func upload_process_file(w http.ResponseWriter, r *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("upload recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp upload_resp
	var f *os.File
	var err error

	//var rdRow *sql.Rows
	//var d plan_file

	var sqlstr string

	//配置文件读取
	base_file_path := modelePath + "/upload/"

	r.ParseMultipartForm(32 << 20)

	id, _ := strconv.Atoi(r.Form.Get("id"))
	//fmt.Println("id:", id)

	upload_user := r.Form.Get("filing_user")

	//读取文件信息
	file, handler, err := r.FormFile("file")
	if err != nil {
		fmt.Println(err)
		resp.Ret = -1
		goto exit
	}
	defer file.Close()
	fmt.Println(handler.Filename)
	logs.Info(base_file_path + handler.Filename)
	if handler.Filename == "" {
		resp.Ret = -1
		goto exit
	}
	os.Remove(base_file_path + handler.Filename)
	f, err = os.OpenFile(base_file_path+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println(err)
		goto exit
	}
	defer f.Close()
	io.Copy(f, file)

	resp.Ret = 0

	//update record process file info
	sqlstr = fmt.Sprintf(`UPDATE [plan_file]
  				 SET [process_file] = '%s'
				,[filing_user] = '%s'
      			,[filing_time] = '%s'
				,[op_time]='%s'
				where ID=%d`, handler.Filename, upload_user,
		time.Now().Format("2006-01-02"), time.Now().Format("2006-01-02 15:04:05"), id)
	//fmt.Println(sqlstr)

	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("upload_process_file exec err:%v", err.Error()))
		goto exit
	}

	file_ch <- 1

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintln(w, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("upload_process_file recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

// 判断文件夹是否存在
func PathExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

func del_pf(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("del_pf recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var err error
	var resp del_pf_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req del_pf_req
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Ids); i++ {

		sqlstr := fmt.Sprintf(`DELETE FROM [plan_file] where ID=%d`, req.Ids[i].ID)
		fmt.Println(sqlstr)

		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("del_pf Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("del_pf recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_pf(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("get_pf recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_pf_Req
	var resp get_pf_Resp

	var sqlstr string
	var rcnt int
	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error
	var count int

	var where_sql string
	var if_where bool

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.P_id != "" {
		likeStr := "%" + req.P_id + "%"
		where_sql += fmt.Sprintf(`[p_id] like '%s'`, likeStr)
		if_where = true
	}

	if req.Plan_name != "" {

		if if_where {
			likeStr := "%" + req.Plan_name + "%"
			where_sql += fmt.Sprintf(` and [plan_name] like '%s'`, likeStr)
			if_where = true
		} else {
			likeStr := "%" + req.Plan_name + "%"
			where_sql += fmt.Sprintf(`[plan_name] like '%s'`, likeStr)
			if_where = true
		}
	}

	if !if_where {
		sqlstr = "select count(ID) from [plan_file]"
	} else {
		sqlstr = fmt.Sprintf("select count(ID) from [plan_file] where %s", where_sql)
	}
	fmt.Println(sqlstr)

	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_pf query %s err:%v", sqlstr, err.Error()))
		goto exit
	}
	defer cntRow.Close()

	for cntRow.Next() {
		if err = cntRow.Scan(&rcnt); err != nil {
			logs.Error(fmt.Sprintf("get_pf scan %s err:%v", sqlstr, err.Error()))
			goto exit
		}
	}
	resp.Total = rcnt

	if !if_where {
		sqlstr = fmt.Sprintf("select top %v [ID],[p_id],[p_name],[plan_name],[process_file],[filing_user],[filing_time],[project_file],[p_filing_time] from [plan_file] where ID not in (select top %v ID from [plan_file] order by ID desc) order by ID desc", req.Count, (req.Index-1)*req.Count)
	} else {
		sqlstr = fmt.Sprintf("select top %v [ID],[p_id],[p_name],[plan_name],[process_file],[filing_user],[filing_time],[project_file],[p_filing_time] from [plan_file] where %s and ID not in (select top %v ID from [plan_file] where %s order by ID desc) order by ID desc", req.Count, where_sql, (req.Index-1)*req.Count, where_sql)
	}
	fmt.Println(sqlstr)
	logs.Info("最终的sql=======", sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_pf Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d plan_file
		if err := rdRow.Scan(&d.ID, &d.P_id, &d.P_name, &d.Plan_name, &d.Plan_process_file, &d.Filing_user, &d.Filing_time, &d.Project_file, &d.P_filing_time); err == nil {
			resp.Data = append(resp.Data, d)
			count++
		} else {
			logs.Error("get_pf scan Error", err.Error())
		}
	}
	logs.Info("循环总条数:", count)
exit:

	jdata, _ := json.Marshal(resp)
	fmt.Println(string(jdata))
	logs.Info("打印的值为：------------", string(jdata))
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("get_pf recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func import_plan_file(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("import_plan_file recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var p_flag int

	var reqdata []byte
	var req import_plan_file_Req
	var resp import_plan_file_Resp
	var b bool

	plan_file_lock.Lock()
	p_flag = plan_file_lock_n
	plan_file_lock.Unlock()

	if p_flag == 1 {
		resp.Ret = 1
		goto exit
	} else {
		plan_file_lock.Lock()
		plan_file_lock_n = 1
		plan_file_lock.Unlock()
	}

	reqdata, _ = ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b = checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Data); i++ {
		var id int

		sqlstr := fmt.Sprintf(`SELECT ID from [plan_file] where p_id='%s' and [plan_name]='%s'`, req.Data[i].P_id, req.Data[i].Plan_name)
		fmt.Println(sqlstr)
		rows, err := sqlConn.Query(sqlstr)
		if err != nil {
			logs.Error(fmt.Sprintf(`%s err:%s`, sqlstr, err.Error()))
			resp.Ret = -1
			goto exit
		}

		for rows.Next() {
			if err := rows.Scan(&id); err != nil {
				logs.Error(fmt.Sprintf(`%s scan err:%s`, sqlstr, err.Error()))
				resp.Ret = -1
				goto exit
			}
		}
		rows.Close()

		if id == 0 {
			sqlstr = fmt.Sprintf(`INSERT INTO [plan_file] ([p_id],[p_name],[plan_name])
     		VALUES ('%s','%s','%s')`, req.Data[i].P_id, req.Data[i].P_name, req.Data[i].Plan_name)
		} else {
			sqlstr = fmt.Sprintf(`UPDATE [plan_file]
   				SET [p_id] = '%s'
      			,[p_name] = '%s',[plan_name]='%s' 
				 WHERE ID=%d`, req.Data[i].P_id, req.Data[i].P_name, req.Data[i].Plan_name,
				id)
		}

		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("import_plan_file Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}
	}

	resp.Ret = 0

exit:

	if resp.Ret != 1 {
		plan_file_lock.Lock()
		plan_file_lock_n = 0
		plan_file_lock.Unlock()
	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("import_plan_file recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_cur_did_from_task(response http.ResponseWriter, request *http.Request) {

	beginTime := time.Now().UnixNano()
	fmt.Println("get_cur_did_from_task recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_cur_did_from_task_req
	var resp get_cur_did_from_task_resp

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.ID == 0 {
		goto exit
	}

	sqlstr = fmt.Sprintf("SELECT [stay_department_id] FROM [plan] where ID=%d", req.ID)
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_cur_did_from_task Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {

		var stay_did int
		if err := rdRow.Scan(&stay_did); err == nil {

			resp.Department_name = get_department_name_from_did(stay_did)
		} else {
			logs.Error("get_cur_did_from_task scan Error", err.Error())
		}
	}

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("get_cur_did_from_task recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func export_sap(response http.ResponseWriter, request *http.Request) {

	beginTime := time.Now().UnixNano()
	fmt.Println("export_sap recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var csv_data [][]string
	var filename string
	filename = fmt.Sprintf(`./file/%v.csv`, beginTime)
	f, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	var req get_p_Req
	var resp exportKpiResp
	var data []p_sap

	var sqlstr string
	var rdRow *sql.Rows

	var where_sql string
	var if_where bool

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.P_id != "" {
		likeStr := "%" + req.P_id + "%"
		where_sql += fmt.Sprintf(`[p_id] like '%s'`, likeStr)
		if_where = true
	}

	if req.P_name != "" {

		if if_where {
			likeStr := "%" + req.P_name + "%"
			where_sql += fmt.Sprintf(` and [p_name] like '%s'`, likeStr)
			if_where = true
		} else {
			likeStr := "%" + req.P_name + "%"
			where_sql += fmt.Sprintf(`[p_name] like '%s'`, likeStr)
			if_where = true
		}
	}

	if !if_where {
		sqlstr = fmt.Sprintf("select [ID],[p_id],[p_name],[data] from [sap] order by ID asc")
	} else {
		sqlstr = fmt.Sprintf("select [ID],[p_id],[p_name],[data] from [sap] where %s order by ID asc", where_sql)
	}
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("export_sap Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d p_sap

		var v string
		var p plan_t
		if err := rdRow.Scan(&d.ID, &d.P_id, &d.P_name, &v); err == nil {

			json.Unmarshal([]byte(v), &p)

			if len(p.Process) >= 3 {
				for i := 0; i < len(p.Process); {

					if i == 0 {
						if p.Process[i+2] == "1" {
							d.P1 = p.Process[i]
							d.P1_t = p.Process[i+1]
						}
					}

					if i == 3 {
						if p.Process[i+2] == "1" {
							d.P2 = p.Process[i]
							d.P2_t = p.Process[i+1]
						}
					}

					if i == 6 {
						if p.Process[i+2] == "1" {
							d.P3 = p.Process[i]
							d.P3_t = p.Process[i+1]
						}
					}

					if i == 9 {
						if p.Process[i+2] == "1" {
							d.P4 = p.Process[i]
							d.P4_t = p.Process[i+1]
						}
					}

					if i == 12 {
						if p.Process[i+2] == "1" {
							d.P5 = p.Process[i]
							d.P5_t = p.Process[i+1]
						}
					}

					if i == 15 {
						if p.Process[i+2] == "1" {
							d.P6 = p.Process[i]
							d.P6_t = p.Process[i+1]
						}
					}

					if i == 18 {
						if p.Process[i+2] == "1" {
							d.P7 = p.Process[i]
							d.P7_t = p.Process[i+1]
						}
					}

					if i == 21 {
						if p.Process[i+2] == "1" {
							d.P8 = p.Process[i]
							d.P8_t = p.Process[i+1]
						}
					}

					if i == 24 {
						if p.Process[i+2] == "1" {
							d.P9 = p.Process[i]
							d.P9_t = p.Process[i+1]
						}
					}

					if i == 27 {
						if p.Process[i+2] == "1" {
							d.P10 = p.Process[i]
							d.P10_t = p.Process[i+1]
						}
					}

					if i == 30 {
						if p.Process[i+2] == "1" {
							d.P11 = p.Process[i]
							d.P11_t = p.Process[i+1]
						}
					}

					if i == 33 {
						if p.Process[i+2] == "1" {
							d.P12 = p.Process[i]
							d.P12_t = p.Process[i+1]
						}
					}

					if i == 36 {
						if p.Process[i+2] == "1" {
							d.P13 = p.Process[i]
							d.P13_t = p.Process[i+1]
						}
					}

					if i == 39 {
						if p.Process[i+2] == "1" {
							d.P14 = p.Process[i]
							d.P14_t = p.Process[i+1]
						}
					}

					if i == 42 {
						if p.Process[i+2] == "1" {
							d.P15 = p.Process[i]
							d.P15_t = p.Process[i+1]
						}
					}

					if i == 45 {
						if p.Process[i+2] == "1" {
							d.P16 = p.Process[i]
							d.P16_t = p.Process[i+1]
						}
					}

					if i == 48 {
						if p.Process[i+2] == "1" {
							d.P17 = p.Process[i]
							d.P17_t = p.Process[i+1]
						}
					}

					if i == 51 {
						if p.Process[i+2] == "1" {
							d.P18 = p.Process[i]
							d.P18_t = p.Process[i+1]
						}
					}

					if i == 54 {
						if p.Process[i+2] == "1" {
							d.P19 = p.Process[i]
							d.P19_t = p.Process[i+1]
						}
					}

					if i == 57 {
						if p.Process[i+2] == "1" {
							d.P20 = p.Process[i]
							d.P20_t = p.Process[i+1]
						}
					}

					if i == 60 {
						if p.Process[i+2] == "1" {
							d.P21 = p.Process[i]
							d.P21_t = p.Process[i+1]
						}
					}

					if i == 63 {
						if p.Process[i+2] == "1" {
							d.P22 = p.Process[i]
							d.P22_t = p.Process[i+1]
						}
					}

					if i == 66 {
						if p.Process[i+2] == "1" {
							d.P23 = p.Process[i]
							d.P23_t = p.Process[i+1]
						}
					}

					if i == 69 {
						if p.Process[i+2] == "1" {
							d.P24 = p.Process[i]
							d.P24_t = p.Process[i+1]
						}
					}

					if i == 72 {
						if p.Process[i+2] == "1" {
							d.P25 = p.Process[i]
							d.P25_t = p.Process[i+1]
						}
					}

					if i == 75 {
						if p.Process[i+2] == "1" {
							d.P26 = p.Process[i]
							d.P26_t = p.Process[i+1]
						}
					}

					if i == 78 {
						if p.Process[i+2] == "1" {
							d.P27 = p.Process[i]
							d.P27_t = p.Process[i+1]
						}
					}

					if i == 81 {
						if p.Process[i+2] == "1" {
							d.P28 = p.Process[i]
							d.P28_t = p.Process[i+1]
						}
					}

					if i == 84 {
						if p.Process[i+2] == "1" {
							d.P29 = p.Process[i]
							d.P29_t = p.Process[i+1]
						}
					}

					if i == 87 {
						if p.Process[i+2] == "1" {
							d.P30 = p.Process[i]
							d.P30_t = p.Process[i+1]
						}
					}

					if i == 90 {
						if p.Process[i+2] == "1" {
							d.P31 = p.Process[i]
							d.P31_t = p.Process[i+1]
						}
					}

					if i == 93 {
						if p.Process[i+2] == "1" {
							d.P32 = p.Process[i]
							d.P32_t = p.Process[i+1]
						}
					}

					if i == 96 {
						if p.Process[i+2] == "1" {
							d.P33 = p.Process[i]
							d.P33_t = p.Process[i+1]
						}
					}

					if i == 99 {
						if p.Process[i+2] == "1" {
							d.P34 = p.Process[i]
							d.P34_t = p.Process[i+1]
						}
					}

					if i == 102 {
						if p.Process[i+2] == "1" {
							d.P35 = p.Process[i]
							d.P35_t = p.Process[i+1]
						}
					}

					i += 3
				}
			}

			data = append(data, d)
		} else {
			logs.Error("export_sap scan Error", err.Error())
		}
	}

	csv_data = append(csv_data, []string{"产品编号", "产品名称",
		"工序1", "工时1",
		"工序2", "工时2",
		"工序3", "工时3",
		"工序4", "工时4",
		"工序5", "工时5",
		"工序6", "工时6",
		"工序7", "工时7",
		"工序8", "工时8",
		"工序9", "工时9",
		"工序10", "工时10",
		"工序11", "工时11",
		"工序12", "工时12",
		"工序13", "工时13",
		"工序14", "工时14",
		"工序15", "工时15",
		"工序16", "工时16",
		"工序17", "工时17",
		"工序18", "工时18",
		"工序19", "工时19",
		"工序20", "工时20",
		"工序21", "工时21",
		"工序22", "工时22",
		"工序23", "工时23",
		"工序24", "工时24",
		"工序25", "工时25",
		"工序26", "工时26",
		"工序27", "工时27",
		"工序28", "工时28",
		"工序29", "工时29",
		"工序30", "工时30",
		"工序31", "工时31",
		"工序32", "工时32",
		"工序33", "工时33",
		"工序34", "工时34",
		"工序35", "工时35"})

	for i := 0; i < len(data); i++ {
		v := data[i]

		csv_data = append(csv_data,
			[]string{v.P_id, v.P_name,
				v.P1, v.P1_t,
				v.P2, v.P2_t,
				v.P3, v.P3_t,
				v.P4, v.P4_t,
				v.P5, v.P5_t,
				v.P6, v.P6_t,
				v.P7, v.P7_t,
				v.P8, v.P8_t,
				v.P9, v.P9_t,
				v.P10, v.P10_t,
				v.P11, v.P11_t,
				v.P12, v.P12_t,
				v.P13, v.P13_t,
				v.P14, v.P14_t,
				v.P15, v.P15_t,
				v.P16, v.P16_t,
				v.P17, v.P17_t,
				v.P18, v.P18_t,
				v.P19, v.P19_t,
				v.P20, v.P20_t,
				v.P21, v.P21_t,
				v.P22, v.P22_t,
				v.P23, v.P23_t,
				v.P24, v.P24_t,
				v.P25, v.P25_t,
				v.P26, v.P26_t,
				v.P27, v.P27_t,
				v.P28, v.P28_t,
				v.P29, v.P29_t,
				v.P30, v.P30_t,
				v.P31, v.P31_t,
				v.P32, v.P32_t,
				v.P33, v.P33_t,
				v.P34, v.P34_t,
				v.P35, v.P35_t})

	}

exit:

	f.WriteString("\xEF\xBB\xBF") // 写入一个UTF-8 BOM 防止中文乱码
	w := csv.NewWriter(f) //创建一个新的写入文件流
	w.WriteAll(csv_data)
	w.Flush()
	resp.FileId = fmt.Sprintf(`%v.csv`, beginTime)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("export_sap recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_p_process_options(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("get_p_process_options recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_p_process_options_req
	var resp get_p_process_options_resp

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	sqlstr = fmt.Sprintf("select [data] from [sap] where p_id='%s'", req.P_id)
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_p_process_options Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var v string

		if err := rdRow.Scan(&v); err == nil {

			var d plan_t
			json.Unmarshal([]byte(v), &d)
			fmt.Println(d)
			resp.P_id = d.P_id
			resp.P_name = d.P_name
			for i := 0; i < len(d.Process); {

				var vv plan_process
				vv.Plan_process_name = d.Process[i]
				vv.Plan_process_t = d.Process[i+1]
				vv.Plan_process_show = d.Process[i+2]

				if vv.Plan_process_show == "1" {
					if !(vv.Plan_process_t == "" || vv.Plan_process_t == "0") {
						resp.Data = append(resp.Data, vv)
					}
				}

				i += 3
			}

		} else {
			logs.Error("get_p_process_options scan Error", err.Error())
		}
	}

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Println(string(jdata))
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("get_p_process_options recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_p_id_options(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("get_p_id_options recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_p_id_options_req
	var resp get_p_id_options_resp

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.P_like_id != "" {
		like_id := "%" + req.P_like_id + "%"
		sqlstr = fmt.Sprintf("select [p_id] from [sap] where p_id like '%s' and flag = '1' order by ID desc", like_id)
	} else {
		sqlstr = fmt.Sprintf("select [p_id] from [sap] where flag = '1' order by ID desc")
	}

	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_p_id_options Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d string

		if err := rdRow.Scan(&d); err == nil {
			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_p_id_options scan Error", err.Error())
		}
	}

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("get_p_id_options recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_options_byId(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("get_p_id_options recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_p_id_options_req
	// 定义新的返回类型
	type OptionItem struct {
		Code string `json:"code"`
		Name string `json:"name"`
	}

	// 修改：定义新的响应结构
	resp := struct {
		Data []OptionItem `json:"data"`
	}{
		Data: []OptionItem{},
	}

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.P_like_id != "" {
		like_id := "%" + req.P_like_id + "%"
		// 修改SQL查询，增加p_name字段
		sqlstr = fmt.Sprintf("select  [p_id], [p_name] from [sap] where p_id like '%s' and flag = '1' order by p_id desc", like_id)
	} else {
		// 修改SQL查询，增加p_name字段
		sqlstr = fmt.Sprintf("select  [p_id], [p_name] from [sap] where flag = '1' order by p_id desc")
	}

	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_p_id_options Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var code string
		var name string // 增加name变量

		// 修改Scan，扫描两个字段
		if err := rdRow.Scan(&code, &name); err == nil {
			// 将数据添加到resp中
			resp.Data = append(resp.Data, OptionItem{
				Code: code,
				Name: name,
			})
		} else {
			logs.Error("get_p_id_options scan Error", err.Error())
		}
	}

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("get_p_id_options recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func import_plan_t(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("import_plan_t recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp import_plan_t_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req import_plan_t_Req
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Data); i++ {
		if len(req.Data[i].Process)%3 != 0 {
			resp.Ret = 1
			resp.Err_text = fmt.Sprintf(`产品编号：%s 工序和工时不完整，请修改！`, req.Data[i].P_id)
			goto exit
		}

		for j := 1; j < len(req.Data[i].Process); {

			//p_use_t, _ := strconv.Atoi(req.Data[i].Process[j])
			if req.Data[i].Process[j] == "" || req.Data[i].Process[j] == "0" {
				resp.Ret = 1
				resp.Err_text = fmt.Sprintf(`产品编号：%s 工时不可为空或者0，请修改！`, req.Data[i].P_id)
				goto exit
			}

			_, err := strconv.ParseFloat(req.Data[i].Process[j], 64)
			if err != nil {
				fmt.Println(err.Error())
				resp.Ret = 1
				resp.Err_text = fmt.Sprintf(`产品编号：%s 工时还有无效符号，请修改！`, req.Data[i].P_id)
				goto exit
			}

			j += 3
		}
	}

	for i := 0; i < len(req.Data); i++ {
		var id int

		sqlstr := fmt.Sprintf(`SELECT ID from sap where p_id='%s'`, req.Data[i].P_id)
		fmt.Println(sqlstr)
		rows, err := sqlConn.Query(sqlstr)
		if err != nil {
			logs.Error(fmt.Sprintf(`import_plan_t SELECT ID from sap where p_id='%s' err:%s`, req.Data[i].P_id, err.Error()))
			resp.Ret = -1
			goto exit
		}

		for rows.Next() {
			if err := rows.Scan(&id); err != nil {
				logs.Error(fmt.Sprintf(`import_plan_t SELECT ID from sap where p_id='%s' scan err:%s`, req.Data[i].P_id, err.Error()))
				resp.Ret = -1
				goto exit
			}
		}
		rows.Close()

		req.Data[i].ID = id
		/*if id == 0 {
			resp.Ret = 1
			resp.Err_text = fmt.Sprintf(`产品编号：%s 不存在，请联系生产管理员添加！`, req.Data[i].P_id)
			goto exit
		} else {
			req.Data[i].ID = id
		}*/
	}

	for i := 0; i < len(req.Data); i++ {
		jdata, _ := json.Marshal(req.Data[i])

		var sqlstr string
		if req.Data[i].ID != 0 {
			sqlstr = fmt.Sprintf(`UPDATE [dbo].[sap]
   				SET [p_id] = '%s'
      			,[p_name] = '%s',[data]='%s' 
				 WHERE ID=%d`, req.Data[i].P_id, req.Data[i].P_name, string(jdata), req.Data[i].ID)
		} else {
			sqlstr = fmt.Sprintf(`INSERT INTO [sap] ([p_id],[p_name],[data]) VALUES ('%s','%s','%s')`,
				req.Data[i].P_id, req.Data[i].P_name, string(jdata))
		}

		_, err := sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("import_plan_t Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("import_plan_t recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func import_p(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("import_p recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var p_flag int

	var reqdata []byte
	var req import_p_Req
	var resp import_p_resp
	var b bool

	p_lock.Lock()
	p_flag = p_import_f
	p_lock.Unlock()

	if p_flag == 1 {
		resp.Ret = 1
		goto exit
	} else {
		p_lock.Lock()
		p_import_f = 1
		p_lock.Unlock()
	}

	reqdata, _ = ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b = checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Data); i++ {
		var id int

		sqlstr := fmt.Sprintf(`SELECT ID from sap where p_id='%s'`, req.Data[i].P_id)
		fmt.Println(sqlstr)
		rows, err := sqlConn.Query(sqlstr)
		if err != nil {
			logs.Error(fmt.Sprintf(`SELECT ID from sap where p_id='%s' err:%s`, req.Data[i].P_id, err.Error()))
			resp.Ret = -1
			goto exit
		}

		for rows.Next() {
			if err := rows.Scan(&id); err != nil {
				logs.Error(fmt.Sprintf(`SELECT ID from sap where p_id='%s' scan err:%s`, req.Data[i].P_id, err.Error()))
				resp.Ret = -1
				goto exit
			}
		}
		rows.Close()

		if id == 0 {
			sqlstr = fmt.Sprintf(`INSERT INTO [sap] ([p_id],[p_name],[flag])
     		VALUES ('%s','%s','%s')`, req.Data[i].P_id, req.Data[i].P_name, "1")
		} else {
			sqlstr = fmt.Sprintf(`UPDATE [dbo].[sap]
   				SET [p_id] = '%s'
      			,[p_name] = '%s'
				 WHERE ID=%d`, req.Data[i].P_id, req.Data[i].P_name, id)
		}

		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("import_p Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}
	}

	resp.Ret = 0

exit:

	//if resp.Ret == 0 {
	p_lock.Lock()
	p_import_f = 0
	p_lock.Unlock()
	//}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("import_p recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func del_p(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("del_p recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var err error
	var resp del_p_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req del_p_req
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Ids); i++ {

		sqlstr := fmt.Sprintf(`DELETE FROM [sap] where ID=%d`, req.Ids[i].ID)
		fmt.Println(sqlstr)

		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("del_p Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("del_p recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func post_p(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("post_p recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var process_data plan_t
	var err error
	var sqlstr string
	var resp post_p_resp

	var jdata []byte

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req post_p_req
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	if req.OperType == 2 && req.Id == 0 {
		logs.Info("post_p sap req id ==0")
		resp.Ret = -1
		goto exit
	}

	//add op check user for same info
	if req.OperType == 1 {
		var cnt int
		row, err := sqlConn.Query(fmt.Sprintf(`select ID from [sap] where [p_id] = '%s' and [flag] = '1'`, req.P_id))
		if err != nil {
			logs.Error(fmt.Sprintf("post_p get sap cnt err:%v", err.Error()))
			resp.Ret = -1
			goto exit
		}

		for row.Next() {
			cnt++
		}
		row.Close()

		if cnt > 0 {
			resp.Ret = 1
			goto exit
		}
	}

	process_data.P_id = req.P_id
	process_data.P_name = req.P_name

	if req.P1 != "" {
		process_data.Process = append(process_data.Process, req.P1, req.P1_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P1, req.P1_t, "0")
	}

	if req.P2 != "" {
		process_data.Process = append(process_data.Process, req.P2, req.P2_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P2, req.P2_t, "0")
	}

	if req.P3 != "" {
		process_data.Process = append(process_data.Process, req.P3, req.P3_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P3, req.P3_t, "0")
	}

	if req.P4 != "" {
		process_data.Process = append(process_data.Process, req.P4, req.P4_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P4, req.P4_t, "0")
	}

	if req.P5 != "" {
		process_data.Process = append(process_data.Process, req.P5, req.P5_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P5, req.P5_t, "0")
	}

	if req.P6 != "" {
		process_data.Process = append(process_data.Process, req.P6, req.P6_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P6, req.P6_t, "0")
	}

	if req.P7 != "" {
		process_data.Process = append(process_data.Process, req.P7, req.P7_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P7, req.P7_t, "0")
	}

	if req.P8 != "" {
		process_data.Process = append(process_data.Process, req.P8, req.P8_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P8, req.P8_t, "0")
	}

	if req.P9 != "" {
		process_data.Process = append(process_data.Process, req.P9, req.P9_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P9, req.P9_t, "0")
	}

	if req.P10 != "" {
		process_data.Process = append(process_data.Process, req.P10, req.P10_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P10, req.P10_t, "0")
	}

	if req.P11 != "" {
		process_data.Process = append(process_data.Process, req.P11, req.P11_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P11, req.P11_t, "0")
	}

	if req.P12 != "" {
		process_data.Process = append(process_data.Process, req.P12, req.P12_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P12, req.P12_t, "0")
	}

	if req.P13 != "" {
		process_data.Process = append(process_data.Process, req.P13, req.P13_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P13, req.P13_t, "0")
	}

	if req.P14 != "" {
		process_data.Process = append(process_data.Process, req.P14, req.P14_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P14, req.P14_t, "0")
	}

	if req.P15 != "" {
		process_data.Process = append(process_data.Process, req.P15, req.P15_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P15, req.P15_t, "0")
	}

	if req.P16 != "" {
		process_data.Process = append(process_data.Process, req.P16, req.P16_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P16, req.P16_t, "0")
	}

	if req.P17 != "" {
		process_data.Process = append(process_data.Process, req.P17, req.P17_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P17, req.P17_t, "0")
	}

	if req.P18 != "" {
		process_data.Process = append(process_data.Process, req.P18, req.P18_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P18, req.P18_t, "0")
	}

	if req.P19 != "" {
		process_data.Process = append(process_data.Process, req.P19, req.P19_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P19, req.P19_t, "0")
	}

	if req.P20 != "" {
		process_data.Process = append(process_data.Process, req.P20, req.P20_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P20, req.P20_t, "0")
	}

	if req.P21 != "" {
		process_data.Process = append(process_data.Process, req.P21, req.P21_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P21, req.P21_t, "0")
	}

	if req.P22 != "" {
		process_data.Process = append(process_data.Process, req.P22, req.P22_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P22, req.P22_t, "0")
	}

	if req.P23 != "" {
		process_data.Process = append(process_data.Process, req.P23, req.P23_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P23, req.P23_t, "0")
	}

	if req.P24 != "" {
		process_data.Process = append(process_data.Process, req.P24, req.P24_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P24, req.P24_t, "0")
	}

	if req.P25 != "" {
		process_data.Process = append(process_data.Process, req.P25, req.P25_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P25, req.P25_t, "0")
	}

	if req.P26 != "" {
		process_data.Process = append(process_data.Process, req.P26, req.P26_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P26, req.P26_t, "0")
	}

	if req.P27 != "" {
		process_data.Process = append(process_data.Process, req.P27, req.P27_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P27, req.P27_t, "0")
	}

	if req.P28 != "" {
		process_data.Process = append(process_data.Process, req.P28, req.P28_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P28, req.P28_t, "0")
	}

	if req.P29 != "" {
		process_data.Process = append(process_data.Process, req.P29, req.P29_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P29, req.P29_t, "0")
	}

	if req.P30 != "" {
		process_data.Process = append(process_data.Process, req.P30, req.P30_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P30, req.P30_t, "0")
	}

	if req.P31 != "" {
		process_data.Process = append(process_data.Process, req.P31, req.P31_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P31, req.P31_t, "0")
	}

	if req.P32 != "" {
		process_data.Process = append(process_data.Process, req.P32, req.P32_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P32, req.P32_t, "0")
	}

	if req.P33 != "" {
		process_data.Process = append(process_data.Process, req.P33, req.P33_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P33, req.P33_t, "0")
	}

	if req.P34 != "" {
		process_data.Process = append(process_data.Process, req.P34, req.P34_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P34, req.P34_t, "0")
	}

	if req.P35 != "" {
		process_data.Process = append(process_data.Process, req.P35, req.P35_t, "1")
	} else {
		process_data.Process = append(process_data.Process, req.P35, req.P35_t, "0")
	}

	jdata, _ = json.Marshal(process_data)

	if req.OperType == 1 { //add
		sqlstr = fmt.Sprintf(`INSERT INTO [sap] ([p_id],[p_name],[data],[flag]) VALUES ('%s','%s','%s','1')`,
			req.P_id, req.P_name, string(jdata))
	} else if req.OperType == 2 { //update
		sqlstr = fmt.Sprintf(`UPDATE [sap] SET [p_id] = '%s',[p_name] = '%s',[data] = '%s' WHERE ID=%d`,
			req.P_id, req.P_name, string(jdata), req.Id)
	} else {
		resp.Ret = -1
		goto exit
	}
	fmt.Println(sqlstr)

	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("post_p Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:

	jdata, _ = json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("post_p recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_p_info(p_id string) (p_name string, if_exist bool) {

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	sqlstr = fmt.Sprintf("select [p_name] from [sap] where p_id='%s' and [flag] = '1'", p_id)
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_p_info Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var v string

		if err := rdRow.Scan(&v); err == nil {
			p_name = v
			if_exist = true
		} else {
			logs.Error("get_p_info scan Error", err.Error())
		}
	}
exit:
	return
}

func get_p(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("get_p recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_p_Req
	var resp get_p_Resp

	var sqlstr string
	var rcnt int
	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error

	var where_sql string
	var if_where bool

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.P_id != "" {
		likeStr := "%" + req.P_id + "%"
		where_sql += fmt.Sprintf(`[p_id] like '%s'`, likeStr)
		if_where = true
	}

	if req.P_name != "" {

		if if_where {
			likeStr := "%" + req.P_name + "%"
			where_sql += fmt.Sprintf(` and [p_name] like '%s'`, likeStr)
			if_where = true
		} else {
			likeStr := "%" + req.P_name + "%"
			where_sql += fmt.Sprintf(`[p_name] like '%s'`, likeStr)
			if_where = true
		}
	}

	if req.Show_unconfirmed {
		if if_where {
			where_sql += fmt.Sprintf(` and [flag] = 0`)
			if_where = true
		} else {
			where_sql += fmt.Sprintf(`[flag] = 0`)
			if_where = true
		}
	} else {
		if if_where {
			where_sql += fmt.Sprintf(` and [flag] = 1`)
			if_where = true
		} else {
			where_sql += fmt.Sprintf(`[flag] = 1`)
			if_where = true
		}
	}

	if !if_where {
		sqlstr = "select count(ID) from [sap] and [flag] = '1'"
	} else {
		sqlstr = fmt.Sprintf("select count(ID) from [sap] where %s", where_sql)
	}
	fmt.Println(sqlstr)

	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_p query %s err:%v", sqlstr, err.Error()))
		goto exit
	}
	defer cntRow.Close()

	for cntRow.Next() {
		if err = cntRow.Scan(&rcnt); err != nil {
			logs.Error(fmt.Sprintf("get_p scan %s err:%v", sqlstr, err.Error()))
			goto exit
		}
	}
	resp.Total = rcnt

	if !if_where {
		sqlstr = fmt.Sprintf("select top %v [ID],[p_id],[p_name],[data] from [sap] where ID not in (select top %v ID from [sap] order by ID asc) order by ID asc", req.Count, (req.Index-1)*req.Count)
	} else {
		sqlstr = fmt.Sprintf("select top %v [ID],[p_id],[p_name],[data] from [sap] where %s and ID not in (select top %v ID from [sap] where %s order by ID asc) order by ID asc", req.Count, where_sql, (req.Index-1)*req.Count, where_sql)
	}
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_p Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d p_sap

		var v string
		var p plan_t
		if err := rdRow.Scan(&d.ID, &d.P_id, &d.P_name, &v); err == nil {

			json.Unmarshal([]byte(v), &p)

			if len(p.Process) >= 3 {
				for i := 0; i < len(p.Process); {

					if i+2 > (len(p.Process) - 1) {
						break
					}

					if i == 0 {
						if p.Process[i+2] == "1" {
							d.P1 = p.Process[i]
							d.P1_t = p.Process[i+1]
						}
					}

					if i == 3 {
						if p.Process[i+2] == "1" {
							d.P2 = p.Process[i]
							d.P2_t = p.Process[i+1]
						}
					}

					if i == 6 {
						if p.Process[i+2] == "1" {
							d.P3 = p.Process[i]
							d.P3_t = p.Process[i+1]
						}
					}

					if i == 9 {
						if p.Process[i+2] == "1" {
							d.P4 = p.Process[i]
							d.P4_t = p.Process[i+1]
						}
					}

					if i == 12 {
						if p.Process[i+2] == "1" {
							d.P5 = p.Process[i]
							d.P5_t = p.Process[i+1]
						}
					}

					if i == 15 {
						if p.Process[i+2] == "1" {
							d.P6 = p.Process[i]
							d.P6_t = p.Process[i+1]
						}
					}

					if i == 18 {
						if p.Process[i+2] == "1" {
							d.P7 = p.Process[i]
							d.P7_t = p.Process[i+1]
						}
					}

					if i == 21 {
						if p.Process[i+2] == "1" {
							d.P8 = p.Process[i]
							d.P8_t = p.Process[i+1]
						}
					}

					if i == 24 {
						if p.Process[i+2] == "1" {
							d.P9 = p.Process[i]
							d.P9_t = p.Process[i+1]
						}
					}

					if i == 27 {
						if p.Process[i+2] == "1" {
							d.P10 = p.Process[i]
							d.P10_t = p.Process[i+1]
						}
					}

					if i == 30 {
						if p.Process[i+2] == "1" {
							d.P11 = p.Process[i]
							d.P11_t = p.Process[i+1]
						}
					}

					if i == 33 {
						if p.Process[i+2] == "1" {
							d.P12 = p.Process[i]
							d.P12_t = p.Process[i+1]
						}
					}

					if i == 36 {
						if p.Process[i+2] == "1" {
							d.P13 = p.Process[i]
							d.P13_t = p.Process[i+1]
						}
					}

					if i == 39 {
						if p.Process[i+2] == "1" {
							d.P14 = p.Process[i]
							d.P14_t = p.Process[i+1]
						}
					}

					if i == 42 {
						if p.Process[i+2] == "1" {
							d.P15 = p.Process[i]
							d.P15_t = p.Process[i+1]
						}
					}

					if i == 45 {
						if p.Process[i+2] == "1" {
							d.P16 = p.Process[i]
							d.P16_t = p.Process[i+1]
						}
					}

					if i == 48 {
						if p.Process[i+2] == "1" {
							d.P17 = p.Process[i]
							d.P17_t = p.Process[i+1]
						}
					}

					if i == 51 {
						if p.Process[i+2] == "1" {
							d.P18 = p.Process[i]
							d.P18_t = p.Process[i+1]
						}
					}

					if i == 54 {
						if p.Process[i+2] == "1" {
							d.P19 = p.Process[i]
							d.P19_t = p.Process[i+1]
						}
					}

					if i == 57 {
						if p.Process[i+2] == "1" {
							d.P20 = p.Process[i]
							d.P20_t = p.Process[i+1]
						}
					}

					if i == 60 {
						if p.Process[i+2] == "1" {
							d.P21 = p.Process[i]
							d.P21_t = p.Process[i+1]
						}
					}

					if i == 63 {
						if p.Process[i+2] == "1" {
							d.P22 = p.Process[i]
							d.P22_t = p.Process[i+1]
						}
					}

					if i == 66 {
						if p.Process[i+2] == "1" {
							d.P23 = p.Process[i]
							d.P23_t = p.Process[i+1]
						}
					}

					if i == 69 {
						if p.Process[i+2] == "1" {
							d.P24 = p.Process[i]
							d.P24_t = p.Process[i+1]
						}
					}

					if i == 72 {
						if p.Process[i+2] == "1" {
							d.P25 = p.Process[i]
							d.P25_t = p.Process[i+1]
						}
					}

					if i == 75 {
						if p.Process[i+2] == "1" {
							d.P26 = p.Process[i]
							d.P26_t = p.Process[i+1]
						}
					}

					if i == 78 {
						if p.Process[i+2] == "1" {
							d.P27 = p.Process[i]
							d.P27_t = p.Process[i+1]
						}
					}

					if i == 81 {
						if p.Process[i+2] == "1" {
							d.P28 = p.Process[i]
							d.P28_t = p.Process[i+1]
						}
					}

					if i == 84 {
						if p.Process[i+2] == "1" {
							d.P29 = p.Process[i]
							d.P29_t = p.Process[i+1]
						}
					}

					if i == 87 {
						if p.Process[i+2] == "1" {
							d.P30 = p.Process[i]
							d.P30_t = p.Process[i+1]
						}
					}

					if i == 90 {
						if p.Process[i+2] == "1" {
							d.P31 = p.Process[i]
							d.P31_t = p.Process[i+1]
						}
					}

					if i == 93 {
						if p.Process[i+2] == "1" {
							d.P32 = p.Process[i]
							d.P32_t = p.Process[i+1]
						}
					}

					if i == 96 {
						if p.Process[i+2] == "1" {
							d.P33 = p.Process[i]
							d.P33_t = p.Process[i+1]
						}
					}

					if i == 99 {
						if p.Process[i+2] == "1" {
							d.P34 = p.Process[i]
							d.P34_t = p.Process[i+1]
						}
					}

					if i == 102 {
						if p.Process[i+2] == "1" {
							d.P35 = p.Process[i]
							d.P35_t = p.Process[i+1]
						}
					}

					i += 3
				}
			}

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_p scan Error", err.Error())
		}
	}

exit:

	jdata, _ := json.Marshal(resp)
	//fmt.Println(string(jdata))
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("get_p recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func download_template_file(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("download_template_file recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req download_template_file_Req
	var resp download_template_file_Resp

	var filename string

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	filename = fmt.Sprintf(`%v.csv`, "导入生产计划")

	resp.FileId = filename

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("download_template_file recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func download_pre_template_file(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("download_template_file recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req download_template_file_Req
	var resp download_template_file_Resp

	var filename string

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	filename = fmt.Sprintf(`%v.csv`, "导入前置生产计划")

	resp.FileId = filename

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("download_template_file recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func postbUser(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("postbUser recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	//	var opContent string
	//	var opType int

	var err error
	var sqlstr string
	var resp post_b_user_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req post_b_user_req
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	if (req.OperType == 2 || req.OperType == 3) && req.Id == 0 {
		logs.Info("update b user req id ==0")
		resp.Ret = -1
		goto exit
	}

	//add op check user for same username
	if req.OperType == 1 {
		var cnt int
		row, err := sqlConn.Query(fmt.Sprintf(`select ID from [user_buyer] where [username] = '%s'`, req.Busername))
		if err != nil {
			logs.Error(fmt.Sprintf("postbUser get user cnt err:%v", err.Error()))
			resp.Ret = -1
			goto exit
		}

		for row.Next() {
			cnt++
		}
		row.Close()

		if cnt > 0 {
			resp.Ret = 1
			goto exit
		}
	}

	if req.OperType == 1 { //add
		//opType = 10001
		//opContent = fmt.Sprintf(`新增用户%s`, req.Username)
		sqlstr = fmt.Sprintf(`INSERT INTO [user_buyer] ([username]) VALUES ('%s')`, req.Busername)
	} else if req.OperType == 2 { //update
		//opType = 10002
		//opContent = fmt.Sprintf(`修改用户%s`, req.Username)
		sqlstr = fmt.Sprintf(`UPDATE [user_buyer] SET [username] = '%s' WHERE ID=%d`,
			req.Busername, req.Id)
	} else if req.OperType == 3 {
		//opType = 10003
		//		opContent = fmt.Sprintf(`删除用户%s`, req.Username)
		sqlstr = fmt.Sprintf(`DELETE FROM [user_buyer] WHERE ID=%d`, req.Id)
	} else {
		resp.Ret = -1
		goto exit
	}
	fmt.Println(sqlstr)

	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("postbUser Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("postbUser recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func getbUsers(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("getbUsers recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_b_user_Req
	var resp get_b_user_Resp

	var sqlstr string
	var rcnt int
	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		fmt.Println(fmt.Sprintf("用户%s不在线", req.OpUser))
		goto exit
	}

	if req.Buser == "" {
		sqlstr = "select count(ID) from [user_buyer]"
	} else {
		likeStr := "%" + req.Buser + "%"
		sqlstr = fmt.Sprintf("select count(ID) from [user_buyer] where [username] like '%s'", likeStr)
	}

	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getbUsers query %s err:%v", sqlstr, err.Error()))
		goto exit
	}
	defer cntRow.Close()

	for cntRow.Next() {
		if err = cntRow.Scan(&rcnt); err != nil {
			logs.Error(fmt.Sprintf("getbUsers scan %s err:%v", sqlstr, err.Error()))
			goto exit
		}
	}
	resp.Total = rcnt

	if req.Buser == "" {
		sqlstr = fmt.Sprintf("select top %v [ID],[username] from [user_buyer] where ID not in (select top %v ID from [user_buyer] order by ID asc) order by ID asc", req.Count, (req.Index-1)*req.Count)
	} else {
		likeStr := "%" + req.Buser + "%"
		sqlstr = fmt.Sprintf("select top %v [ID],[username] from [user_buyer] where username like '%s' and ID not in (select top %v ID from [user_buyer] where username like '%s' order by ID asc) order by ID asc", req.Count, likeStr, (req.Index-1)*req.Count, likeStr)
	}
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getbUsers Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d b_user
		if err := rdRow.Scan(&d.Userid, &d.Busername); err == nil {
			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("getbUsers scan Error", err.Error())
		}
	}

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("getbUsers recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func postpUser(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("postpUser recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	//	var opContent string
	//	var opType int

	var err error
	var sqlstr string
	var resp post_p_user_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req post_p_user_req
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	if (req.OperType == 2 || req.OperType == 3) && req.Id == 0 {
		logs.Info("update p user req id ==0")
		resp.Ret = -1
		goto exit
	}

	//add op check user for same username
	if req.OperType == 1 {
		var cnt int
		row, err := sqlConn.Query(fmt.Sprintf(`select ID from [puser] where [pusername] = '%s'`, req.Pusername))
		if err != nil {
			logs.Error(fmt.Sprintf("postpUser get user cnt err:%v", err.Error()))
			resp.Ret = -1
			goto exit
		}

		for row.Next() {
			cnt++
		}
		row.Close()

		if cnt > 0 {
			resp.Ret = 1
			goto exit
		}
	}

	if req.OperType == 1 { //add
		//opType = 10001
		//opContent = fmt.Sprintf(`新增用户%s`, req.Username)
		sqlstr = fmt.Sprintf(`INSERT INTO [puser] ([pusername],[group_name],p_process) VALUES ('%s','%s','%s')`,
			req.Pusername, req.Group_name, req.Produce_plan)
	} else if req.OperType == 2 { //update
		//opType = 10002
		//opContent = fmt.Sprintf(`修改用户%s`, req.Username)
		sqlstr = fmt.Sprintf(`UPDATE [puser] SET [pusername] = '%s',[group_name] = '%s',p_process= '%s' WHERE ID=%d`,
			req.Pusername, req.Group_name, req.Produce_plan, req.Id)
	} else if req.OperType == 3 {
		//opType = 10003
		//		opContent = fmt.Sprintf(`删除用户%s`, req.Username)
		sqlstr = fmt.Sprintf(`DELETE FROM [puser] WHERE ID=%d`, req.Id)
	} else {
		resp.Ret = -1
		goto exit
	}
	fmt.Println(sqlstr)

	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("postpUser Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("postpUser recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func getpUsers(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	var req get_p_user_Req
	var resp get_p_user_Resp

	var sqlstr string
	var rcnt int
	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error

	var whereSql string
	var ifwhere bool

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		fmt.Println(fmt.Sprintf("用户%s不在线", req.OpUser))
		goto exit
	}

	if req.Puser != "" {
		likeStr := "%" + req.Puser + "%"
		whereSql = fmt.Sprintf(` [pusername] like '%s'`, likeStr)
		ifwhere = true
	}

	if req.Group_name_v != "" {
		likeStr := "%" + req.Group_name_v + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [group_name] like '%s'`, likeStr)
		} else {
			whereSql = fmt.Sprintf(` [group_name] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	if !ifwhere {
		sqlstr = "select count(ID) from [puser]"
	} else {
		sqlstr = fmt.Sprintf("select count(ID) from [puser] where %s", whereSql)
	}

	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getpUsers query %s err:%v", sqlstr, err.Error()))
		goto exit
	}
	defer cntRow.Close()

	for cntRow.Next() {
		if err = cntRow.Scan(&rcnt); err != nil {
			logs.Error(fmt.Sprintf("getpUsers scan %s err:%v", sqlstr, err.Error()))
			goto exit
		}
	}
	resp.Total = rcnt

	if !ifwhere {
		sqlstr = fmt.Sprintf("select top %v [ID],[pusername],[group_name],p_process from [puser] where ID not in (select top %v ID from [puser] order by ID asc) order by ID asc", req.Count, (req.Index-1)*req.Count)
	} else {
		sqlstr = fmt.Sprintf("select top %v [ID],[pusername],[group_name],p_process from [puser] where %s and ID not in (select top %v ID from [puser] where %s order by ID asc) order by ID asc", req.Count, whereSql, (req.Index-1)*req.Count, whereSql)
	}

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getpUsers Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d p_user

		if err := rdRow.Scan(&d.Userid, &d.Pusername, &d.Group_name, &d.Produce_plan); err == nil {
			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("getpUsers scan Error", err.Error())
		}
	}

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("getpUsers recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func exportKpi_bak(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("exportKpi recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req exportKpiReq
	var resp exportKpiResp
	var data []kpi

	var ifwhere bool
	var whereSql string

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	var filename string
	var file *xlsx.File
	var style *xlsx.Style
	var font xlsx.Font
	var row *xlsx.Row
	var cell1 *xlsx.Cell
	var sheet *xlsx.Sheet
	var alignment xlsx.Alignment

	var scan_flag int
	var usrinfo useInfo

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)
	fmt.Println(string(reqdata))
	fmt.Println(req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		goto exit
	}

	usrinfo, err = getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("exportKpi getUserInfo err:%s", err.Error()))
		goto exit
	}

	if req.Id != "" {
		likeStr := "%" + req.Id + "%"
		whereSql += fmt.Sprintf(` [ID] like '%s'`, likeStr)
		ifwhere = true
	}

	if req.Pid != "" {
		likeStr := "%" + req.Pid + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [p_id] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [p_id] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	if req.Pname != "" {
		likeStr := "%" + req.Pname + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [p_name] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [p_name] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	/*if req.Puser != "" {
		likeStr := "%" + req.Puser + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [op_user] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` where [op_user] like '%s'`, likeStr)
		}
		ifwhere = true
	}*/

	if req.Month != "" {
		search_month, _ := strconv.Atoi(req.Month)
		if ifwhere {
			whereSql += fmt.Sprintf(` and [month] = %d`, search_month)
		} else {
			whereSql += fmt.Sprintf(` [month] = %d`, search_month)
		}
		ifwhere = true
	}

	scan_flag = 1 << (usrinfo.DepartmentId - 1)
	if req.If_finished {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [scan_flag]&%d>0 and [stay_department_id]!=%d`, scan_flag, usrinfo.DepartmentId)
		} else {
			whereSql += fmt.Sprintf(` [scan_flag]&%d>0 and [stay_department_id]!=%d`, scan_flag, usrinfo.DepartmentId)
		}
		ifwhere = true
	} else {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [scan_flag]&%d>0 and [stay_department_id]=%d`, scan_flag, usrinfo.DepartmentId)
		} else {
			whereSql += fmt.Sprintf(` [scan_flag]&%d>0 and [stay_department_id]=%d`, scan_flag, usrinfo.DepartmentId)
		}
		ifwhere = true
	}

	if !ifwhere {
		sqlstr = fmt.Sprintf("select [ID],[time],[data] from [plan] order by [ID] desc")
	} else {
		sqlstr = fmt.Sprintf("select [ID],[time],[data] from [plan] where %s order by [ID] desc", whereSql)
	}
	fmt.Println(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("exportKpi Query err:%v", err.Error()))
		goto exit
	}

	for rdRow.Next() {
		var d kpi
		var id int
		var v string
		var createTime string
		if err := rdRow.Scan(&id, &createTime, &v); err == nil {

			json.Unmarshal([]byte(v), &d)

			d.ID = id
			d.CreateTime = createTime[:10] + " " + createTime[11:19]
			data = append(data, d)
		} else {
			logs.Error("exportKpi scan Error", err.Error())
		}
	}
	rdRow.Close()

	file = xlsx.NewFile()
	sheet, err = file.AddSheet("sheet1")
	if err != nil {
		logs.Error("file add sheet err:", err.Error())
	}

	style = xlsx.NewStyle()
	font = *xlsx.NewFont(11, "宋体")
	style.Font = font
	alignment = xlsx.Alignment{
		Horizontal: "center",
		Vertical:   "center",
	}
	style.Alignment = alignment
	style.ApplyAlignment = true

	row = sheet.AddRow()
	//row.SetHeightCM(1) //设置每行的高度
	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "订单日期"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "编码"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "部门"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "任务号"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "产品编号"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "产品名称"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "数量"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "生产班组"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "派产数量"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "计划派产日期"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "承诺完成日期"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "实际完成日期"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "超期"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "生产状态"

	//派产详情
	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "工序"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "生产人员"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "排产数量"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "计划派产日期"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "计划完成日期"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "实际完成日期"

	cell1 = row.AddCell()
	cell1.SetStyle(style)
	cell1.Value = "超期天数"

	for i := 0; i < len(data); i++ {
		v := data[i]

		if len(v.Produce_plan_data) > 0 {
			for j := 0; j < len(v.Produce_plan_data); j++ {
				row := sheet.AddRow()
				//row.SetHeightCM(1) //设置每行的高度

				cell1 := row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.CreateTime

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = strconv.Itoa(v.ID)

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Department_name

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Task_id

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Product_id

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Product_name

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Total_num

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Group_name

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Dispath_num

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Plan_dispath_date

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Plan_finished_date

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Plan_actual_finished_date

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Overdue

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Plan_state

				//派产详情
				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Produce_plan_data[j].Produce_plan

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Produce_plan_data[j].Produce_user

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Produce_plan_data[j].Dispath_num

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Produce_plan_data[j].Plan_dispath_date

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Produce_plan_data[j].P_plan_finished_t

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = v.Produce_plan_data[j].P_actual_finished_t

				cell1 = row.AddCell()
				cell1.SetStyle(style)
				cell1.Value = strconv.Itoa(v.Produce_plan_data[j].P_finished_overdue_day)
			}
		} else {
			row := sheet.AddRow()
			//row.SetHeightCM(1) //设置每行的高度

			cell1 := row.AddCell()
			cell1.SetStyle(style)
			cell1.Value = v.CreateTime

			cell1 = row.AddCell()
			cell1.SetStyle(style)
			cell1.Value = strconv.Itoa(v.ID)

			cell1 = row.AddCell()
			cell1.SetStyle(style)
			cell1.Value = v.Department_name

			cell1 = row.AddCell()
			cell1.SetStyle(style)
			cell1.Value = v.Task_id

			cell1 = row.AddCell()
			cell1.SetStyle(style)
			cell1.Value = v.Product_id

			cell1 = row.AddCell()
			cell1.SetStyle(style)
			cell1.Value = v.Product_name

			cell1 = row.AddCell()
			cell1.SetStyle(style)
			cell1.Value = v.Total_num

			cell1 = row.AddCell()
			cell1.SetStyle(style)
			cell1.Value = v.Group_name

			cell1 = row.AddCell()
			cell1.SetStyle(style)
			cell1.Value = v.Dispath_num

			cell1 = row.AddCell()
			cell1.SetStyle(style)
			cell1.Value = v.Plan_dispath_date

			cell1 = row.AddCell()
			cell1.SetStyle(style)
			cell1.Value = v.Plan_finished_date

			cell1 = row.AddCell()
			cell1.SetStyle(style)
			cell1.Value = v.Plan_actual_finished_date

			cell1 = row.AddCell()
			cell1.SetStyle(style)
			cell1.Value = v.Overdue

			cell1 = row.AddCell()
			cell1.SetStyle(style)
			cell1.Value = v.Plan_state
		}
	}

	filename = fmt.Sprintf(`%v.xlsx`, beginTime)
	err = file.Save("./file/" + filename)
	if err != nil {
		logs.Error("xlsx save err:", err.Error())
	}

	resp.FileId = filename

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("exportKpi recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_time_ex(search_time string) (st []string, b bool) {
	t := strings.Split(search_time, "-")
	if len(t) == 2 {
		t0 := strings.Split(t[0], "/")
		if len(t0) == 3 {
			year, _ := strconv.Atoi(t0[0])
			month, _ := strconv.Atoi(t0[1])
			day, _ := strconv.Atoi(t0[2])

			t0 := fmt.Sprintf(`20%02d/%02d/%02d`, year, month, day)
			st = append(st, t0)
		} else {
			b = true
		}

		t1 := strings.Split(t[1], "/")
		if len(t1) == 3 {
			year, _ := strconv.Atoi(t1[0])
			month, _ := strconv.Atoi(t1[1])
			day, _ := strconv.Atoi(t1[2])

			t0 := fmt.Sprintf(`20%02d/%02d/%02d`, year, month, day)
			st = append(st, t0)
		} else {
			b = true
		}

	} else if len(t) == 1 {
		tt := strings.Split(t[0], "/")
		if len(tt) == 3 {
			year, _ := strconv.Atoi(tt[0])
			month, _ := strconv.Atoi(tt[1])
			day, _ := strconv.Atoi(tt[2])

			bt := fmt.Sprintf(`20%02d/%02d/%02d`, year, month, day)
			et := fmt.Sprintf(`20%02d/%02d/%02d`, year, month, day)
			st = append(st, bt)
			st = append(st, et)
		} else {
			b = true
		}
	}

	if b {
		st = []string{}
	}

	return
}

// 汇总分解
func export_plan_collect(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("export_plan_collect recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	pid_map := make(map[string]int)

	var req export_plan_collect_req
	var resp exportKpiResp
	var data []kpi

	var whereSql string

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	var csv_data [][]string
	var filename string
	filename = fmt.Sprintf(`./file/%v.csv`, beginTime)
	f, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	var scan_flag int
	var usrinfo useInfo

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		goto exit
	}

	usrinfo, err = getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("exportKpi_ex getUserInfo err:%s", err.Error()))
		goto exit
	}

	scan_flag = 1 << (usrinfo.DepartmentId - 1)
	whereSql += fmt.Sprintf(` [scan_flag]&%d>0 and [stay_department_id]=%d`, scan_flag, usrinfo.DepartmentId)
	whereSql += fmt.Sprintf(` and [del_flag] != %d`, 1)

	sqlstr = fmt.Sprintf("select [ID],[time],[data] from [plan] where %s order by [p_id] desc", whereSql)
	fmt.Println(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("exportKpi_ex Query err:%v", err.Error()))
		goto exit
	}

	for rdRow.Next() {
		var d kpi
		var id int
		var v string
		var createTime string
		if err := rdRow.Scan(&id, &createTime, &v); err == nil {

			json.Unmarshal([]byte(v), &d)

			d.ID = id
			d.CreateTime = createTime[:10] + " " + createTime[11:19]
			data = append(data, d)

			pid_map[d.Product_id]++
		} else {
			logs.Error("export_plan_collect scan Error", err.Error())
		}
	}
	rdRow.Close()

	csv_data = append(csv_data, []string{"序号", "订单日期", "部门", "计划/项目号", "产品编号",
		"产品名称", "数量", "需求日期", "RDM", "交付人", "承诺到料", "生产班组", "派产数量", "计划派产日期", "承诺完成日期",
		"实际完成日期", "超期", "生产状态", "飞书链接", "编程状态", "工序", "工时", "准备时间", "编程时间", "生产人员", "派产数量", "计划派产日期",
		"计划完成日期", "实际完成日期", "超期天数"})

	for i := 0; i < len(data); i++ {
		v := data[i]

		if cnt, ok := pid_map[v.Product_id]; ok {
			if cnt < 2 {
				continue
			}
		} else {
			continue
		}

		if len(v.Produce_plan_data) > 0 {
			for j := 0; j < len(v.Produce_plan_data); j++ {

				csv_data = append(csv_data, []string{strconv.Itoa(v.ID), v.CreateTime, v.Department_name,
					v.Task_id, v.Product_id, v.Product_name, v.Total_num,
					v.Demand_date, v.RDM_id, v.Conveyer, v.Promise_date,
					v.Group_name, v.Dispath_num, v.Plan_dispath_date, v.Plan_finished_date,
					v.Plan_actual_finished_date, v.Overdue, v.Plan_state,
					v.Feishu_link, v.Code_state,
					v.Produce_plan_data[j].Produce_plan, v.Produce_plan_data[j].Produce_plan_use_t,
					v.Produce_plan_data[j].Pre_time, v.Produce_plan_data[j].Code_time,
					v.Produce_plan_data[j].Produce_user,
					v.Produce_plan_data[j].Dispath_num, v.Produce_plan_data[j].Plan_dispath_date,
					v.Produce_plan_data[j].P_plan_finished_t, v.Produce_plan_data[j].P_actual_finished_t,
					strconv.Itoa(v.Produce_plan_data[j].P_finished_overdue_day)})
			}
		} else {

			csv_data = append(csv_data, []string{strconv.Itoa(v.ID), v.CreateTime, v.Department_name,
				v.Task_id, v.Product_id, v.Product_name, v.Total_num,
				v.Demand_date, v.RDM_id, v.Conveyer, v.Promise_date,
				v.Group_name, v.Dispath_num,
				v.Plan_dispath_date, v.Plan_finished_date, v.Plan_actual_finished_date,
				v.Overdue, v.Plan_state,
				v.Feishu_link, v.Code_state})
		}
	}

exit:

	f.WriteString("\xEF\xBB\xBF") // 写入一个UTF-8 BOM 防止中文乱码
	w := csv.NewWriter(f) //创建一个新的写入文件流
	w.WriteAll(csv_data)
	w.Flush()
	resp.FileId = fmt.Sprintf(`%v.csv`, beginTime)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("export_plan_collect recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

// 导出检验已完成工序
func export_completed_Kpi(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("exportKpi_ex recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var bt string
	var et string

	var req exportKpiReq
	var resp exportKpiResp
	var data []kpi

	var ifwhere bool
	var whereSql string

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	var csv_data [][]string
	var filename string
	filename = fmt.Sprintf(`./file/%v.csv`, beginTime)
	f, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	var scan_flag int
	var usrinfo useInfo

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)
	fmt.Println(string(reqdata))
	fmt.Println(req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		goto exit
	}

	usrinfo, err = getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("exportKpi_ex getUserInfo err:%s", err.Error()))
		goto exit
	}

	if req.Month != "" {

		st, b := get_time_ex(req.Month)
		if !b {
			if len(st) == 2 {
				bt = st[0]
				et = st[1]
			}
		}
		/*s := get_time(req.Month)
		if s != "" {
			if ifwhere {
				whereSql += fmt.Sprintf(` and %s`, s)
			} else {
				whereSql += fmt.Sprintf(` %s`, s)
			}
			ifwhere = true
		}*/
	}

	scan_flag = 1 << (usrinfo.DepartmentId - 1)

	whereSql += fmt.Sprintf(` [scan_flag]&%d>0 `, scan_flag)
	ifwhere = true

	if req.If_del {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [del_flag] = %d`, 1)
		} else {
			whereSql += fmt.Sprintf(` [del_flag] = %d`, 1)
		}
		ifwhere = true
	} else {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [del_flag] != %d`, 1)
		} else {
			whereSql += fmt.Sprintf(` [del_flag] != %d`, 1)
		}
		ifwhere = true
	}

	if ifwhere {
		whereSql += fmt.Sprintf(` and [group_name] = '质检组'`)
		ifwhere = true
	} else {
		whereSql += fmt.Sprintf(` [group_name] = '质检组'`)
		ifwhere = true
	}

	if !ifwhere {
		sqlstr = fmt.Sprintf("select [ID],[time],[data] from [plan] order by [ID] desc")
	} else {
		sqlstr = fmt.Sprintf("select [ID],[time],[data] from [plan] where %s order by [ID] desc", whereSql)
	}
	fmt.Println(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("exportKpi_ex Query err:%v", err.Error()))
		goto exit
	}

	for rdRow.Next() {
		var d kpi
		var id int
		var v string
		var createTime string
		if err := rdRow.Scan(&id, &createTime, &v); err == nil {

			json.Unmarshal([]byte(v), &d)

			d.ID = id
			d.CreateTime = createTime[:10] + " " + createTime[11:19]
			data = append(data, d)
		} else {
			logs.Error("exportKpi_ex scan Error", err.Error())
		}
	}
	rdRow.Close()

	csv_data = append(csv_data, []string{"订单日期", "编码", "部门", "计划/项目号", "产品编号",
		"产品名称", "数量", "需求日期", "RDM", "交付人", "承诺到料", "生产班组", "派产数量", "计划派产日期", "承诺完成日期",
		"实际完成日期", "超期", "生产状态", "编程状态", "工序", "工时", "准备时间", "编程时间", "生产人员", "派产数量", "计划派产日期",
		"计划完成日期", "实际完成日期", "超期天数"})

	fmt.Println("bt", bt)
	fmt.Println("et", et)
	for i := 0; i < len(data); i++ {
		v := data[i]

		if len(v.Produce_plan_data) > 0 {
			for j := 0; j < len(v.Produce_plan_data); j++ {

				if bt != "" && et != "" {
					if v.Produce_plan_data[j].P_actual_finished_t >= bt && v.Produce_plan_data[j].P_actual_finished_t <= et {
						csv_data = append(csv_data, []string{v.CreateTime, strconv.Itoa(v.ID), v.Department_name,
							v.Task_id, v.Product_id, v.Product_name, v.Total_num,
							v.Demand_date, v.RDM_id, v.Conveyer, v.Promise_date,
							v.Group_name, v.Dispath_num, v.Plan_dispath_date, v.Plan_finished_date,
							v.Plan_actual_finished_date, v.Overdue, v.Plan_state,
							v.Code_state,
							v.Produce_plan_data[j].Produce_plan, v.Produce_plan_data[j].Produce_plan_use_t,
							v.Produce_plan_data[j].Pre_time, v.Produce_plan_data[j].Code_time,
							v.Produce_plan_data[j].Produce_user,
							v.Produce_plan_data[j].Dispath_num, v.Produce_plan_data[j].Plan_dispath_date,
							v.Produce_plan_data[j].P_plan_finished_t, v.Produce_plan_data[j].P_actual_finished_t,
							strconv.Itoa(v.Produce_plan_data[j].P_finished_overdue_day)})
					}
				} else {
					if v.Produce_plan_data[j].P_actual_finished_t != "" {
						csv_data = append(csv_data, []string{v.CreateTime, strconv.Itoa(v.ID), v.Department_name,
							v.Task_id, v.Product_id, v.Product_name, v.Total_num,
							v.Demand_date, v.RDM_id, v.Conveyer, v.Promise_date,
							v.Group_name, v.Dispath_num, v.Plan_dispath_date, v.Plan_finished_date,
							v.Plan_actual_finished_date, v.Overdue, v.Plan_state,
							v.Code_state,
							v.Produce_plan_data[j].Produce_plan, v.Produce_plan_data[j].Produce_plan_use_t,
							v.Produce_plan_data[j].Pre_time, v.Produce_plan_data[j].Code_time,
							v.Produce_plan_data[j].Produce_user,
							v.Produce_plan_data[j].Dispath_num, v.Produce_plan_data[j].Plan_dispath_date,
							v.Produce_plan_data[j].P_plan_finished_t, v.Produce_plan_data[j].P_actual_finished_t,
							strconv.Itoa(v.Produce_plan_data[j].P_finished_overdue_day)})
					}
				}
			}
		}
	}

exit:

	f.WriteString("\xEF\xBB\xBF") // 写入一个UTF-8 BOM 防止中文乱码
	w := csv.NewWriter(f) //创建一个新的写入文件流
	w.WriteAll(csv_data)
	w.Flush()
	resp.FileId = fmt.Sprintf(`%v.csv`, beginTime)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("exportKpi_ex recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

// 导出检验未完成工序
func export_not_completed_Kpi(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("exportKpi_ex recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var bt string
	var et string

	var req exportKpiReq
	var resp exportKpiResp
	var data []kpi

	var ifwhere bool
	var whereSql string

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	var csv_data [][]string
	var filename string
	filename = fmt.Sprintf(`./file/%v.csv`, beginTime)
	f, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	var scan_flag int
	var usrinfo useInfo

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)
	fmt.Println(string(reqdata))
	fmt.Println(req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		goto exit
	}

	usrinfo, err = getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("exportKpi_ex getUserInfo err:%s", err.Error()))
		goto exit
	}

	if req.Month != "" {

		st, b := get_time_ex(req.Month)
		if !b {
			if len(st) == 2 {
				bt = st[0]
				et = st[1]
			}
		}
		/*s := get_time(req.Month)
		if s != "" {
			if ifwhere {
				whereSql += fmt.Sprintf(` and %s`, s)
			} else {
				whereSql += fmt.Sprintf(` %s`, s)
			}
			ifwhere = true
		}*/
	}

	scan_flag = 1 << (usrinfo.DepartmentId - 1)

	whereSql += fmt.Sprintf(` [scan_flag]&%d>0 `, scan_flag)
	ifwhere = true

	if req.If_del {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [del_flag] = %d`, 1)
		} else {
			whereSql += fmt.Sprintf(` [del_flag] = %d`, 1)
		}
		ifwhere = true
	} else {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [del_flag] != %d`, 1)
		} else {
			whereSql += fmt.Sprintf(` [del_flag] != %d`, 1)
		}
		ifwhere = true
	}

	if ifwhere {
		whereSql += fmt.Sprintf(` and [group_name] = '质检组'`)
		ifwhere = true
	} else {
		whereSql += fmt.Sprintf(` [group_name] = '质检组'`)
		ifwhere = true
	}

	if !ifwhere {
		sqlstr = fmt.Sprintf("select [ID],[time],[data] from [plan] order by [ID] desc")
	} else {
		sqlstr = fmt.Sprintf("select [ID],[time],[data] from [plan] where %s order by [ID] desc", whereSql)
	}
	fmt.Println(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("exportKpi_ex Query err:%v", err.Error()))
		goto exit
	}

	for rdRow.Next() {
		var d kpi
		var id int
		var v string
		var createTime string
		if err := rdRow.Scan(&id, &createTime, &v); err == nil {

			json.Unmarshal([]byte(v), &d)

			d.ID = id
			d.CreateTime = createTime[:10] + " " + createTime[11:19]
			data = append(data, d)
		} else {
			logs.Error("exportKpi_ex scan Error", err.Error())
		}
	}
	rdRow.Close()

	csv_data = append(csv_data, []string{"订单日期", "编码", "部门", "计划/项目号", "产品编号",
		"产品名称", "数量", "需求日期", "RDM", "交付人", "承诺到料", "生产班组", "派产数量", "计划派产日期", "承诺完成日期",
		"实际完成日期", "超期", "生产状态", "编程状态", "工序", "工时", "准备时间", "编程时间", "生产人员", "派产数量", "计划派产日期",
		"计划完成日期", "实际完成日期", "超期天数"})

	fmt.Println("bt", bt)
	fmt.Println("et", et)
	for i := 0; i < len(data); i++ {
		v := data[i]

		if len(v.Produce_plan_data) > 0 {
			for j := 0; j < len(v.Produce_plan_data); j++ {

				if bt != "" && et != "" {
					if v.Produce_plan_data[j].P_actual_finished_t >= bt && v.Produce_plan_data[j].P_actual_finished_t <= et {
						csv_data = append(csv_data, []string{v.CreateTime, strconv.Itoa(v.ID), v.Department_name,
							v.Task_id, v.Product_id, v.Product_name, v.Total_num,
							v.Demand_date, v.RDM_id, v.Conveyer, v.Promise_date,
							v.Group_name, v.Dispath_num, v.Plan_dispath_date, v.Plan_finished_date,
							v.Plan_actual_finished_date, v.Overdue, v.Plan_state,
							v.Code_state,
							v.Produce_plan_data[j].Produce_plan, v.Produce_plan_data[j].Produce_plan_use_t,
							v.Produce_plan_data[j].Pre_time, v.Produce_plan_data[j].Code_time,
							v.Produce_plan_data[j].Produce_user,
							v.Produce_plan_data[j].Dispath_num, v.Produce_plan_data[j].Plan_dispath_date,
							v.Produce_plan_data[j].P_plan_finished_t, v.Produce_plan_data[j].P_actual_finished_t,
							strconv.Itoa(v.Produce_plan_data[j].P_finished_overdue_day)})
					}
				} else {
					if v.Produce_plan_data[j].P_actual_finished_t == "" {
						csv_data = append(csv_data, []string{v.CreateTime, strconv.Itoa(v.ID), v.Department_name,
							v.Task_id, v.Product_id, v.Product_name, v.Total_num,
							v.Demand_date, v.RDM_id, v.Conveyer, v.Promise_date,
							v.Group_name, v.Dispath_num, v.Plan_dispath_date, v.Plan_finished_date,
							v.Plan_actual_finished_date, v.Overdue, v.Plan_state,
							v.Code_state,
							v.Produce_plan_data[j].Produce_plan, v.Produce_plan_data[j].Produce_plan_use_t,
							v.Produce_plan_data[j].Pre_time, v.Produce_plan_data[j].Code_time,
							v.Produce_plan_data[j].Produce_user,
							v.Produce_plan_data[j].Dispath_num, v.Produce_plan_data[j].Plan_dispath_date,
							v.Produce_plan_data[j].P_plan_finished_t, v.Produce_plan_data[j].P_actual_finished_t,
							strconv.Itoa(v.Produce_plan_data[j].P_finished_overdue_day)})
					}
				}
			}
		}
	}

exit:

	f.WriteString("\xEF\xBB\xBF") // 写入一个UTF-8 BOM 防止中文乱码
	w := csv.NewWriter(f) //创建一个新的写入文件流
	w.WriteAll(csv_data)
	w.Flush()
	resp.FileId = fmt.Sprintf(`%v.csv`, beginTime)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("exportKpi_ex recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

// 已完成工序导出
func exportKpi_ex(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("exportKpi_ex recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var bt string
	var et string

	var req exportKpiReq
	var resp exportKpiResp
	var data []kpi

	var ifwhere bool
	var whereSql string

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	var csv_data [][]string
	var filename string
	filename = fmt.Sprintf(`./file/%v.csv`, beginTime)
	f, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	var scan_flag int
	var usrinfo useInfo

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)
	fmt.Println(string(reqdata))
	fmt.Println(req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		goto exit
	}

	usrinfo, err = getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("exportKpi_ex getUserInfo err:%s", err.Error()))
		goto exit
	}

	if req.Month != "" {

		st, b := get_time_ex(req.Month)
		if !b {
			if len(st) == 2 {
				bt = st[0]
				et = st[1]
			}
		}
		/*s := get_time(req.Month)
		if s != "" {
			if ifwhere {
				whereSql += fmt.Sprintf(` and %s`, s)
			} else {
				whereSql += fmt.Sprintf(` %s`, s)
			}
			ifwhere = true
		}*/
	}

	scan_flag = 1 << (usrinfo.DepartmentId - 1)

	whereSql += fmt.Sprintf(` [scan_flag]&%d>0 `, scan_flag)
	ifwhere = true

	if req.If_del {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [del_flag] = %d`, 1)
		} else {
			whereSql += fmt.Sprintf(` [del_flag] = %d`, 1)
		}
		ifwhere = true
	} else {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [del_flag] != %d`, 1)
		} else {
			whereSql += fmt.Sprintf(` [del_flag] != %d`, 1)
		}
		ifwhere = true
	}

	if !ifwhere {
		sqlstr = fmt.Sprintf("select [ID],[time],[data] from [plan] order by [ID] desc")
	} else {
		sqlstr = fmt.Sprintf("select [ID],[time],[data] from [plan] where %s order by [ID] desc", whereSql)
	}
	fmt.Println(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("exportKpi_ex Query err:%v", err.Error()))
		goto exit
	}

	for rdRow.Next() {
		var d kpi
		var id int
		var v string
		var createTime string
		if err := rdRow.Scan(&id, &createTime, &v); err == nil {

			json.Unmarshal([]byte(v), &d)

			d.ID = id
			d.CreateTime = createTime[:10] + " " + createTime[11:19]
			data = append(data, d)
		} else {
			logs.Error("exportKpi_ex scan Error", err.Error())
		}
	}
	rdRow.Close()

	csv_data = append(csv_data, []string{"订单日期", "编码", "部门", "计划/项目号", "产品编号",
		"产品名称", "数量", "需求日期", "RDM", "交付人", "承诺到料", "生产班组", "派产数量", "计划派产日期", "承诺完成日期",
		"实际完成日期", "超期", "生产状态", "编程状态", "工序", "工时", "准备时间", "编程时间", "生产人员", "派产数量", "计划派产日期",
		"计划完成日期", "实际完成日期", "超期天数"})

	fmt.Println("bt", bt)
	fmt.Println("et", et)
	for i := 0; i < len(data); i++ {
		v := data[i]

		if len(v.Produce_plan_data) > 0 {
			for j := 0; j < len(v.Produce_plan_data); j++ {

				if bt != "" && et != "" {
					if v.Produce_plan_data[j].P_actual_finished_t >= bt && v.Produce_plan_data[j].P_actual_finished_t <= et {
						csv_data = append(csv_data, []string{v.CreateTime, strconv.Itoa(v.ID), v.Department_name,
							v.Task_id, v.Product_id, v.Product_name, v.Total_num,
							v.Demand_date, v.RDM_id, v.Conveyer, v.Promise_date,
							v.Group_name, v.Dispath_num, v.Plan_dispath_date, v.Plan_finished_date,
							v.Plan_actual_finished_date, v.Overdue, v.Plan_state,
							v.Code_state,
							v.Produce_plan_data[j].Produce_plan, v.Produce_plan_data[j].Produce_plan_use_t,
							v.Produce_plan_data[j].Pre_time, v.Produce_plan_data[j].Code_time,
							v.Produce_plan_data[j].Produce_user,
							v.Produce_plan_data[j].Dispath_num, v.Produce_plan_data[j].Plan_dispath_date,
							v.Produce_plan_data[j].P_plan_finished_t, v.Produce_plan_data[j].P_actual_finished_t,
							strconv.Itoa(v.Produce_plan_data[j].P_finished_overdue_day)})
					}
				} else {
					if v.Produce_plan_data[j].P_actual_finished_t != "" {
						csv_data = append(csv_data, []string{v.CreateTime, strconv.Itoa(v.ID), v.Department_name,
							v.Task_id, v.Product_id, v.Product_name, v.Total_num,
							v.Demand_date, v.RDM_id, v.Conveyer, v.Promise_date,
							v.Group_name, v.Dispath_num, v.Plan_dispath_date, v.Plan_finished_date,
							v.Plan_actual_finished_date, v.Overdue, v.Plan_state,
							v.Code_state,
							v.Produce_plan_data[j].Produce_plan, v.Produce_plan_data[j].Produce_plan_use_t,
							v.Produce_plan_data[j].Pre_time, v.Produce_plan_data[j].Code_time,
							v.Produce_plan_data[j].Produce_user,
							v.Produce_plan_data[j].Dispath_num, v.Produce_plan_data[j].Plan_dispath_date,
							v.Produce_plan_data[j].P_plan_finished_t, v.Produce_plan_data[j].P_actual_finished_t,
							strconv.Itoa(v.Produce_plan_data[j].P_finished_overdue_day)})
					}
				}
			}
		}
	}

exit:

	f.WriteString("\xEF\xBB\xBF") // 写入一个UTF-8 BOM 防止中文乱码
	w := csv.NewWriter(f) //创建一个新的写入文件流
	w.WriteAll(csv_data)
	w.Flush()
	resp.FileId = fmt.Sprintf(`%v.csv`, beginTime)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("exportKpi_ex recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func export_transfer_history(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("export_transfer_history recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req export_transfer_history_req
	var resp export_transfer_history_resp
	var data []kpi

	var department_id int
	var t_sql string
	var t_Sql_department string
	var sqlstr string
	var rdRow *sql.Rows
	var err error

	var scan_flag int

	var csv_data [][]string
	var filename string
	filename = fmt.Sprintf(`./file/%v.csv`, beginTime)
	f, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)
	fmt.Println(string(reqdata))
	fmt.Println(req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		goto exit
	}

	if req.Month != "" {
		t_sql = get_time(req.Month)
	}

	department_id = 3
	t_Sql_department = fmt.Sprintf(` [stay_department_id]=%d `, department_id)

	sqlstr = fmt.Sprintf("select [ID],[time],[data] from [plan] ")
	sqlstr += fmt.Sprintf(` where %s`, t_Sql_department)
	if t_sql != "" {
		sqlstr += fmt.Sprintf(` and %s`, t_sql)
	}
	sqlstr += fmt.Sprintf(" order by [ID] desc")
	fmt.Println(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("export_transfer_history Query err:%v", err.Error()))
		goto exit
	}

	for rdRow.Next() {
		var d kpi
		var id int
		var v string
		var createTime string
		if err := rdRow.Scan(&id, &createTime, &v); err == nil {

			json.Unmarshal([]byte(v), &d)

			d.ID = id
			d.CreateTime = createTime[:10] + " " + createTime[11:19]
			data = append(data, d)
		} else {
			logs.Error("export_transfer_history scan Error", err.Error())
		}
	}
	rdRow.Close()

	department_id = 1
	t_Sql_department = fmt.Sprintf(` [stay_department_id]=%d and [start_department_id]!=%d`, department_id, department_id)

	sqlstr = fmt.Sprintf("select [ID],[time],[data] from [plan] ")
	sqlstr += fmt.Sprintf(` where %s`, t_Sql_department)
	if t_sql != "" {
		sqlstr += fmt.Sprintf(` and %s`, t_sql)
	}
	sqlstr += fmt.Sprintf(" order by [ID] desc")
	fmt.Println(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("export_transfer_history Query err:%v", err.Error()))
		goto exit
	}

	for rdRow.Next() {
		var d kpi
		var id int
		var v string
		var createTime string
		if err := rdRow.Scan(&id, &createTime, &v); err == nil {

			json.Unmarshal([]byte(v), &d)

			d.ID = id
			d.CreateTime = createTime[:10] + " " + createTime[11:19]
			data = append(data, d)
		} else {
			logs.Error("export_transfer_history scan Error", err.Error())
		}
	}
	rdRow.Close()

	department_id = 1
	scan_flag = 1 << (department_id - 1)
	t_Sql_department = fmt.Sprintf(` [scan_flag]&%d>0 and [stay_department_id]!=1 and [stay_department_id]!=3`, scan_flag)

	sqlstr = fmt.Sprintf("select [ID],[time],[data] from [plan] ")
	sqlstr += fmt.Sprintf(` where %s`, t_Sql_department)
	if t_sql != "" {
		sqlstr += fmt.Sprintf(` and %s`, t_sql)
	}
	sqlstr += fmt.Sprintf(" order by [ID] desc")
	fmt.Println(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("export_transfer_history Query err:%v", err.Error()))
		goto exit
	}

	for rdRow.Next() {
		var d kpi
		var id int
		var v string
		var createTime string
		if err := rdRow.Scan(&id, &createTime, &v); err == nil {

			json.Unmarshal([]byte(v), &d)

			d.ID = id
			d.CreateTime = createTime[:10] + " " + createTime[11:19]
			data = append(data, d)
		} else {
			logs.Error("export_transfer_history scan Error", err.Error())
		}
	}
	rdRow.Close()

	csv_data = append(csv_data, []string{"订单日期", "编码", "部门", "计划/项目号", "产品编号",
		"产品名称", "数量", "生产状态",
		"生产部转入日期", "生产部转出日期", "处理时间",
		"供应链转入日期", "供应链转出日期", "处理时间",
		"研发转入日期", "研发转出日期", "处理时间",
		"交付转入日期", "交付转出日期", "处理时间",
		"保温瓶转入日期", "保温瓶转出日期", "处理时间",
		"技术转入日期", "技术转出日期", "处理时间"})

	for i := 0; i < len(data); i++ {
		v := data[i]

		csv_data = append(csv_data, []string{v.CreateTime, strconv.Itoa(v.ID), v.Department_name,
			v.Task_id, v.Product_id, v.Product_name, v.Total_num, v.Plan_state,
			v.D1_bt, v.D1_et, v.D1_ut,
			v.D3_bt, v.D3_et, v.D3_ut,
			v.D5_bt, v.D5_et, v.D5_ut,
			v.D4_bt, v.D4_et, v.D4_ut,
			v.D6_bt, v.D6_et, v.D6_ut,
			v.D7_bt, v.D7_et, v.D7_ut})
	}

exit:

	f.WriteString("\xEF\xBB\xBF") // 写入一个UTF-8 BOM 防止中文乱码
	w := csv.NewWriter(f) //创建一个新的写入文件流
	w.WriteAll(csv_data)
	w.Flush()
	resp.FileId = fmt.Sprintf(`%v.csv`, beginTime)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("export_transfer_history recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

// 导出未完成计划
func exportKpi(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("exportKpi recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req exportKpiReq
	var resp exportKpiResp
	var data []kpi

	var ifwhere bool
	var whereSql string

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	var csv_data [][]string
	var filename string
	filename = fmt.Sprintf(`./file/%v.csv`, beginTime)
	f, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	var scan_flag int
	var usrinfo useInfo

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)
	fmt.Println(string(reqdata))
	fmt.Println(req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		goto exit
	}

	usrinfo, err = getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("exportKpi getUserInfo err:%s", err.Error()))
		goto exit
	}

	if req.Id != "" {
		likeStr := "%" + req.Id + "%"
		whereSql += fmt.Sprintf(` [ID] like '%s'`, likeStr)
		ifwhere = true
	}

	if req.Task_id != "" {
		likeStr := "%" + req.Task_id + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [task_id] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [task_id] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	if req.Pid != "" {
		likeStr := "%" + req.Pid + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [p_id] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [p_id] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	if req.Pname != "" {
		likeStr := "%" + req.Pname + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [p_name] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [p_name] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	//交付人
	if req.Conveyer != "" {
		likeStr := "%" + req.Conveyer + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [conveyer] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [conveyer] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	//交付人
	if req.Rdm_id != "" {
		likeStr := "%" + req.Rdm_id + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [rmd_id] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [rmd_id] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	if req.Product_user != "" {
		likeStr := "%" + req.Product_user + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [p_user] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [p_user] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	if req.Plan_state != "" {
		likeStr := "%" + req.Plan_state + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [p_state] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [p_state] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	if req.Group_name != "" {
		likeStr := "%" + req.Group_name + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [group_name] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [group_name] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	if req.Month != "" {
		s := get_time(req.Month)
		if s != "" {
			if ifwhere {
				whereSql += fmt.Sprintf(` and %s`, s)
			} else {
				whereSql += fmt.Sprintf(` %s`, s)
			}
			ifwhere = true
		}
	}

	if req.Promise_date != "" {
		t, _ := get_time_ex(req.Promise_date)
		if len(t) == 2 {
			if ifwhere {
				whereSql += fmt.Sprintf(` and promise_date >='%s' and promise_date<='%s'`, t[0], t[1])
			} else {
				whereSql += fmt.Sprintf(` promise_date >='%s' and promise_date<='%s'`, t[0], t[1])
			}
			ifwhere = true
		}
	}

	scan_flag = 1 << (usrinfo.DepartmentId - 1)
	if req.If_finished {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [scan_flag]&%d>0 and [stay_department_id]!=%d`, scan_flag, usrinfo.DepartmentId)
		} else {
			whereSql += fmt.Sprintf(` [scan_flag]&%d>0 and [stay_department_id]!=%d`, scan_flag, usrinfo.DepartmentId)
		}
		ifwhere = true
	} else {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [scan_flag]&%d>0 and [stay_department_id]=%d`, scan_flag, usrinfo.DepartmentId)
		} else {
			whereSql += fmt.Sprintf(` [scan_flag]&%d>0 and [stay_department_id]=%d`, scan_flag, usrinfo.DepartmentId)
		}
		ifwhere = true
	}

	if req.If_del {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [del_flag] = %d`, 1)
		} else {
			whereSql += fmt.Sprintf(` [del_flag] = %d`, 1)
		}
		ifwhere = true
	} else {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [del_flag] != %d`, 1)
		} else {
			whereSql += fmt.Sprintf(` [del_flag] != %d`, 1)
		}
		ifwhere = true
	}

	if !ifwhere {
		sqlstr = fmt.Sprintf("select [ID],[time],[data] from [plan] order by [ID] desc")
	} else {
		sqlstr = fmt.Sprintf("select [ID],[time],[data] from [plan] where %s order by [ID] desc", whereSql)
	}
	fmt.Println(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("exportKpi Query err:%v", err.Error()))
		goto exit
	}

	for rdRow.Next() {
		var d kpi
		var id int
		var v string
		var createTime string
		if err := rdRow.Scan(&id, &createTime, &v); err == nil {

			json.Unmarshal([]byte(v), &d)

			d.ID = id
			d.CreateTime = createTime[:10] + " " + createTime[11:19]

			if d.Plan_actual_finished_date != "" && d.Plan_finished_date != "" {
				if d.Plan_actual_finished_date > d.Plan_finished_date {
					d.Overdue = "是"
				}
			}

			if d.Plan_actual_finished_date == "" && d.Plan_finished_date != "" {
				now_t := time.Now().Format(g_loc)

				now_t = strings.ReplaceAll(string(now_t[:10]), "-", "/")
				if now_t > d.Plan_finished_date {
					d.Overdue = "是"
				}
			}

			data = append(data, d)
		} else {
			logs.Error("exportKpi scan Error", err.Error())
		}
	}
	rdRow.Close()

	csv_data = append(csv_data, []string{"序号", "订单日期", "部门", "计划/项目号", "产品编号",
		"产品名称", "数量", "需求日期", "RDM", "交付人", "承诺到料", "物料超期", "生产班组", "派产数量", "计划派产日期", "承诺完成日期",
		"实际完成日期", "超期", "生产状态", "飞书链接", "编程状态", "工序", "工时", "准备时间", "编程时间", "生产人员", "派产数量", "计划派产日期",
		"计划完成日期", "实际完成日期", "超期天数"})

	for i := 0; i < len(data); i++ {
		v := data[i]

		if len(v.Produce_plan_data) > 0 {
			for j := 0; j < len(v.Produce_plan_data); j++ {

				if req.Plan_finished && v.Produce_plan_data[j].P_actual_finished_t == "" {
					continue
				}

				csv_data = append(csv_data, []string{strconv.Itoa(v.ID), v.CreateTime, v.Department_name,
					v.Task_id, v.Product_id, v.Product_name, v.Total_num,
					v.Demand_date, v.RDM_id, v.Conveyer, v.Promise_date, v.M_overdue,
					v.Group_name, v.Dispath_num, v.Plan_dispath_date, v.Plan_finished_date,
					v.Plan_actual_finished_date, v.Overdue, v.Plan_state,
					v.Feishu_link, v.Code_state,
					v.Produce_plan_data[j].Produce_plan, v.Produce_plan_data[j].Produce_plan_use_t,
					v.Produce_plan_data[j].Pre_time, v.Produce_plan_data[j].Code_time,
					v.Produce_plan_data[j].Produce_user,
					v.Produce_plan_data[j].Dispath_num, v.Produce_plan_data[j].Plan_dispath_date,
					v.Produce_plan_data[j].P_plan_finished_t, v.Produce_plan_data[j].P_actual_finished_t,
					strconv.Itoa(v.Produce_plan_data[j].P_finished_overdue_day)})
			}
		} else {

			if req.Plan_finished {
				continue
			}

			csv_data = append(csv_data, []string{strconv.Itoa(v.ID), v.CreateTime, v.Department_name,
				v.Task_id, v.Product_id, v.Product_name, v.Total_num,
				v.Demand_date, v.RDM_id, v.Conveyer, v.Promise_date, v.M_overdue,
				v.Group_name, v.Dispath_num,
				v.Plan_dispath_date, v.Plan_finished_date, v.Plan_actual_finished_date,
				v.Overdue, v.Plan_state,
				v.Feishu_link, v.Code_state})
		}
	}

exit:

	f.WriteString("\xEF\xBB\xBF") // 写入一个UTF-8 BOM 防止中文乱码
	w := csv.NewWriter(f) //创建一个新的写入文件流
	w.WriteAll(csv_data)
	w.Flush()
	resp.FileId = fmt.Sprintf(`%v.csv`, beginTime)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("exportKpi recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func getKpiUpdateHistory(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("getKpiUpdateHistory recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req getKpiUpdateHistoryReq
	var resp getKpiUpdateHistoryResp

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	sqlstr = fmt.Sprintf(`SELECT [op_time],[op_user],[data] FROM [update_history] where ID=%d order by [op_time] desc`, req.ID)
	fmt.Println(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getKpiUpdateHistory Query err:%v", err.Error()))
		goto exit
	}

	for rdRow.Next() {
		var d kpiUpdateRd
		if err := rdRow.Scan(&d.OpTime, &d.Opuser, &d.OpContext); err == nil {
			if len(d.OpTime) >= 19 {
				d.OpTime = d.OpTime[:10] + " " + d.OpTime[11:19]
			}

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("getKpiUpdateHistory scan Error", err.Error())
		}
	}
	rdRow.Close()

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("getKpiUpdateHistory recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func task_finished(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("task_finished recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var err error
	var sqlstr string
	var resp task_finished_Resp

	var b bool
	//var usrinfo useInfo

	var now_time string
	var update_context string

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req task_finished_Req
	json.Unmarshal(reqdata, &req)

	b = checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	now_time = time.Now().Format("2006-01-02 15:04:05")
	for i := 0; i < len(req.ID); i++ {
		var data []byte
		var rows *sql.Rows
		var kpiData kpi
		var stay_department_id int

		sqlstr = fmt.Sprintf("select [stay_department_id],[data] from [plan] where ID=%d", req.ID[i])
		rows, err = sqlConn.Query(sqlstr)
		if err != nil {
			logs.Info(fmt.Sprintf("task_finished Query err:%s", err.Error()))
			resp.Ret = -1
			goto exit
		}

		for rows.Next() {
			var v string
			if err = rows.Scan(&stay_department_id, &v); err == nil {
				json.Unmarshal([]byte(v), &kpiData)
			}
		}
		rows.Close()

		kpiData.Process_end_time = time.Now().Format("2006-01-02 15:04:05")
		task_transfer_update_time(stay_department_id, 0, &kpiData)
		if stay_department_id == 2 {
			if kpiData.Delivery_time != "" && kpiData.Process_end_time != "" {
				timeLayout := "2006-01-02 15:04:05"
				loc, _ := time.LoadLocation("Local")

				bt, _ := time.ParseInLocation(timeLayout, kpiData.Delivery_time, loc)
				et, _ := time.ParseInLocation(timeLayout, kpiData.Process_end_time, loc)
				if int(et.Sub(bt).Hours()) > 72 {
					kpiData.Delivery_overdue = "已超期"
				}
			}
		}
		kpiData.Plan_state = "入库"
		data, _ = json.Marshal(kpiData)

		sqlstr = fmt.Sprintf(`UPDATE [plan]
   			SET [data]='%s',[stay_department_id] = %d,[p_state]='%s' WHERE ID=%d`,
			string(data), 0, kpiData.Plan_state, req.ID[i])
		fmt.Println(sqlstr)
		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("task_finished Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}

		stay_did_name := get_department_name_from_did(stay_department_id)
		update_context = fmt.Sprintf(`任务从%s转出入库`, stay_did_name)
		sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, req.ID[i], now_time, req.OpUser, update_context)
		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("task_finished Exec Error:", err.Error())
			resp.Ret = -1
		}
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("task_finished recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_department_id_from_name(department_name string) (departmentid int) {
	//1生产 2质检 3供应链 4交付 5研发 6 保温瓶
	if department_name == "生产" {
		departmentid = 1
	} else if department_name == "质检" {
		departmentid = 2
	} else if department_name == "供应链" {
		departmentid = 3
	} else if department_name == "交付" {
		departmentid = 4
	} else if department_name == "研发" {
		departmentid = 5
	} else if department_name == "保温瓶" {
		departmentid = 6
	} else if department_name == "技术" {
		departmentid = 7
	} else if department_name == "生产订单" {
		departmentid = 8
	} else {
		departmentid = 1
	}

	return
}

func get_department_name_from_did(department_did int) (department_name string) {
	//1生产 2质检 3供应链 4交付 5研发 6 保温瓶 7技术 8生产订单
	if department_did == 1 {
		department_name = "生产"
	} else if department_did == 2 {
		department_name = "质检"
	} else if department_did == 3 {
		department_name = "供应链"
	} else if department_did == 4 {
		department_name = "交付"
	} else if department_did == 5 {
		department_name = "研发"
	} else if department_did == 6 {
		department_name = "保温瓶"
	} else if department_did == 7 {
		department_name = "技术"
	} else if department_did == 8 {
		department_name = "生产订单"
	} else if department_did == 0 {
		department_name = "入库"
	} else {
		department_name = "无对应部门"
	}

	return
}

func task_transfer_update_time(stay_departmentid int, desc_departmentid int, kpiData *kpi) {
	//1生产 2质检 3供应链 4交付 5研发 6保温瓶

	if stay_departmentid == desc_departmentid {
		return
	}

	timeLayout := "2006-01-02 15:04:05"
	loc, _ := time.LoadLocation("Local")

	if stay_departmentid == 1 {
		kpiData.D1_et = time.Now().Format("2006-01-02 15:04:05")

		if kpiData.D1_bt != "" && kpiData.D1_et != "" {
			bt, _ := time.ParseInLocation(timeLayout, kpiData.D1_bt, loc)
			et, _ := time.ParseInLocation(timeLayout, kpiData.D1_et, loc)
			kpiData.d1_ut_ += int(et.Sub(bt).Hours())
			kpiData.D1_ut = fmt.Sprintf(`%d小时`, kpiData.d1_ut_)
		}
	} else if stay_departmentid == 2 {
		kpiData.D2_et = time.Now().Format("2006-01-02 15:04:05")

		if kpiData.D2_bt != "" && kpiData.D2_et != "" {
			bt, _ := time.ParseInLocation(timeLayout, kpiData.D2_bt, loc)
			et, _ := time.ParseInLocation(timeLayout, kpiData.D2_et, loc)
			kpiData.d2_ut_ += int(et.Sub(bt).Hours())
			kpiData.D2_ut = fmt.Sprintf(`%d小时`, kpiData.d2_ut_)
		}

	} else if stay_departmentid == 3 {
		kpiData.D3_et = time.Now().Format("2006-01-02 15:04:05")

		if kpiData.D3_bt != "" && kpiData.D3_et != "" {
			bt, _ := time.ParseInLocation(timeLayout, kpiData.D3_bt, loc)
			et, _ := time.ParseInLocation(timeLayout, kpiData.D3_et, loc)
			kpiData.d3_ut_ += int(et.Sub(bt).Hours())
			kpiData.D3_ut = fmt.Sprintf(`%d小时`, kpiData.d3_ut_)
		}

	} else if stay_departmentid == 4 {
		kpiData.D4_et = time.Now().Format("2006-01-02 15:04:05")

		if kpiData.D4_bt != "" && kpiData.D4_et != "" {
			bt, _ := time.ParseInLocation(timeLayout, kpiData.D4_bt, loc)
			et, _ := time.ParseInLocation(timeLayout, kpiData.D4_et, loc)
			kpiData.d4_ut_ += int(et.Sub(bt).Hours())
			kpiData.D4_ut = fmt.Sprintf(`%d小时`, kpiData.d4_ut_)
		}

	} else if stay_departmentid == 5 {
		kpiData.D5_et = time.Now().Format("2006-01-02 15:04:05")

		if kpiData.D5_bt != "" && kpiData.D5_et != "" {
			bt, _ := time.ParseInLocation(timeLayout, kpiData.D5_bt, loc)
			et, _ := time.ParseInLocation(timeLayout, kpiData.D5_et, loc)
			kpiData.d5_ut_ += int(et.Sub(bt).Hours())
			kpiData.D5_ut = fmt.Sprintf(`%d小时`, kpiData.d5_ut_)
		}

	} else if stay_departmentid == 6 {
		kpiData.D6_et = time.Now().Format("2006-01-02 15:04:05")

		if kpiData.D6_bt != "" && kpiData.D6_et != "" {
			bt, _ := time.ParseInLocation(timeLayout, kpiData.D6_bt, loc)
			et, _ := time.ParseInLocation(timeLayout, kpiData.D6_et, loc)
			kpiData.d6_ut_ += int(et.Sub(bt).Hours())
			kpiData.D6_ut = fmt.Sprintf(`%d小时`, kpiData.d6_ut_)
		}
	} else if stay_departmentid == 7 {
		kpiData.D7_et = time.Now().Format("2006-01-02 15:04:05")

		if kpiData.D7_bt != "" && kpiData.D7_et != "" {
			bt, _ := time.ParseInLocation(timeLayout, kpiData.D7_bt, loc)
			et, _ := time.ParseInLocation(timeLayout, kpiData.D7_et, loc)
			kpiData.d7_ut_ += int(et.Sub(bt).Hours())
			kpiData.D7_ut = fmt.Sprintf(`%d小时`, kpiData.d7_ut_)
		}
	}

	if desc_departmentid == 1 {
		kpiData.D1_bt = time.Now().Format("2006-01-02 15:04:05")
		kpiData.D1_et = ""
	} else if desc_departmentid == 2 {
		kpiData.D2_bt = time.Now().Format("2006-01-02 15:04:05")
		kpiData.D2_et = ""

		kpiData.Delivery_time = kpiData.D2_bt
	} else if desc_departmentid == 3 {
		kpiData.D3_bt = time.Now().Format("2006-01-02 15:04:05")
		kpiData.D3_et = ""
	} else if desc_departmentid == 4 {
		kpiData.D4_bt = time.Now().Format("2006-01-02 15:04:05")
		kpiData.D4_et = ""
	} else if desc_departmentid == 5 {
		kpiData.D5_bt = time.Now().Format("2006-01-02 15:04:05")
		kpiData.D5_et = ""
	} else if desc_departmentid == 6 {
		kpiData.D6_bt = time.Now().Format("2006-01-02 15:04:05")
		kpiData.D6_et = ""
	} else if desc_departmentid == 7 {
		kpiData.D7_bt = time.Now().Format("2006-01-02 15:04:05")
		kpiData.D7_et = ""
	}

	return
}

func task_transfer(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("task_transfer recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	//var err error
	var sqlstr string
	var resp task_transfer_Resp

	var stay_departmentid int
	var departmentid int
	var jdata []byte

	var now_time string
	var update_context string
	//var user_info useInfo

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req task_transfer_Req
	json.Unmarshal(reqdata, &req)
	escapeSingleQuote := func(s string) string {
		return strings.Replace(s, "'", "''", -1)
	}

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}
	fmt.Println("转入生产计划depa22222rtmentid", req.DepartmentName)
	departmentid = get_department_id_from_name(req.DepartmentName)
	fmt.Println("转入生产计划departmentid", departmentid)
	now_time = time.Now().Format("2006-01-02 15:04:05")
	for i := 0; i < len(req.ID); i++ {
		var kpiData kpi
		var scan_flag int
		sqlstr = fmt.Sprintf("select data,scan_flag,stay_department_id from [plan] where ID=%d", req.ID[i])
		rows, err := sqlConn.Query(sqlstr)
		if err != nil {
			logs.Info(fmt.Sprintf("task_transfer Query err:%s", err.Error()))
			resp.Ret = -1
			goto exit
		}

		for rows.Next() {

			var v string
			if err = rows.Scan(&v, &scan_flag, &stay_departmentid); err == nil {
				json.Unmarshal([]byte(v), &kpiData)
			}
		}
		rows.Close()
		fmt.Println("转入生产计划depa33333333rtmentid", departmentid)

		scan_flag = scan_flag | (1 << (departmentid - 1))
		fmt.Println("转入生产计划depa444444444rtmentid", scan_flag)
		//update time
		task_transfer_update_time(stay_departmentid, departmentid, &kpiData)

		if departmentid == 1 {
			kpiData.Plan_state = "待分解"
		}

		fmt.Println("kpiData.Plan_state = ", kpiData.Plan_state)

		if stay_departmentid == 1 && departmentid != 1 {
			kpiData.Flag1 = true
		}

		if stay_departmentid == 3 && departmentid == 1 {
			if kpiData.Promise_date != "" {
				t := strings.ReplaceAll(kpiData.Promise_date, "/", "-")
				t += " 00:00:00"

				timeLayout := "2006-01-02 15:04:05"
				loc, _ := time.LoadLocation("Local")

				bt, _ := time.ParseInLocation(timeLayout, t, loc)
				now := time.Now()
				t1 := fmt.Sprintf(`%d-%02d-%02d 00:00:00`, now.Year(), now.Month(), now.Day())
				et, _ := time.ParseInLocation(timeLayout, t1, loc)
				h := bt.Sub(et).Hours()
				//fmt.Println("h:", h)
				kpiData.M_overdue = strconv.Itoa(int(h / 24))
			}
		}

		jdata, _ = json.Marshal(kpiData)
		fmt.Println("kpiData---------", kpiData)
		fmt.Println("jdata---------", jdata)
		sqlstr = fmt.Sprintf(`UPDATE [plan]
   			SET [data] = '%s' ,[stay_department_id] = %d,[scan_flag] = %d,[p_state]='%s' WHERE ID=%d`,
			escapeSingleQuote(string(jdata)), departmentid, scan_flag, kpiData.Plan_state, req.ID[i])
		//fmt.Println(sqlstr)
		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("task_transfer Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}

		if departmentid == 1 { //消息
			ch_kpi <- kpiData
		}

		if stay_departmentid != departmentid {
			stay_did_name := get_department_name_from_did(stay_departmentid)
			update_context = fmt.Sprintf(`任务从%s转到%s`, stay_did_name, req.DepartmentName)
			sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, req.ID[i], now_time, req.OpUser, update_context)
			_, err = sqlConn.Exec(sqlstr)
			if err != nil {
				logs.Info("task_transfer Exec Error:", err.Error())
				resp.Ret = -1
			}
		}
	}

	resp.Ret = 0

exit:

	jdata, _ = json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("task_transfer recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func preTask_transfer(response http.ResponseWriter, request *http.Request) {

}

func get_del_kpi_his(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("get_del_kpi_his recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_del_kpi_his_req
	var resp get_del_kpi_his_resp

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		goto exit
	}

	if req.ID == 0 {
		logs.Info(fmt.Sprintf("get_del_kpi_his ID == 0"))
		goto exit
	}

	sqlstr = fmt.Sprintf("select [data] from [del_history] where ID=%d", req.ID)
	fmt.Println(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_del_kpi_his Query err:%v", err.Error()))
		goto exit
	}

	for rdRow.Next() {
		var v string
		if err := rdRow.Scan(&v); err == nil {
			resp.Data = v
		} else {
			logs.Error("get_del_kpi_his scan Error", err.Error())
		}
	}
	rdRow.Close()

exit:

	if resp.Data == "" {
		resp.Data = "无删除记录"
	}
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("get_del_kpi_his recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func delKpi(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("delKpi recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var context string
	var op_time string

	var err error
	var sqlstr string
	var resp DelKpiResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req DelKpiReq
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	sqlstr = fmt.Sprintf(`UPDATE [plan] SET [del_flag] =1 WHERE ID=%d`, req.ID)
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("delKpi Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	op_time = time.Now().Format("2006-01-02 15:04:05")
	context = fmt.Sprintf(`%s %s删除了序号%d生产计划记录`,
		op_time, req.OpUser, req.ID)
	resp.Ret = 0

exit:

	if resp.Ret == 0 {
		sqlstr = fmt.Sprintf(`INSERT INTO [dbo].[del_history]
           ([ID]
           ,[op_time]
           ,[op_user]
           ,[data])
     VALUES
           (%d
           ,'%s'
           ,'%s'
           ,'%s')`,
			req.ID, op_time, req.OpUser, context)
		fmt.Println(sqlstr)
		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("delKpi Exec Error:", err.Error())
			resp.Ret = -1
		}
	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("delKpi recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func delPreKpi(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("delKpi recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var context string
	var op_time string

	var err error
	var sqlstr string
	var resp DelKpiResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req DelKpiReq
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	sqlstr = fmt.Sprintf(`UPDATE [pre_plan] SET [del_flag] =1 WHERE ID=%d`, req.ID)
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("delPreKpi Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	op_time = time.Now().Format("2006-01-02 15:04:05")
	context = fmt.Sprintf(`%s %s删除了序号%d生产计划记录`,
		op_time, req.OpUser, req.ID)
	resp.Ret = 0

exit:

	if resp.Ret == 0 {
		sqlstr = fmt.Sprintf(`INSERT INTO [dbo].[del_history]
           ([ID]
           ,[op_time]
           ,[op_user]
           ,[data])
     VALUES
           (%d
           ,'%s'
           ,'%s'
           ,'%s')`,
			req.ID, op_time, req.OpUser, context)
		fmt.Println(sqlstr)
		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("delPreKpi Exec Error:", err.Error())
			resp.Ret = -1
		}
	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("delPreKpi recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func updatekpi_2(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("updatekpi_2 recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var data []byte
	//	var month int

	var err error
	var sqlstr string
	var resp UpdateKpiResp

	var b bool

	//	var usrinfo useInfo
	//	var update_context string

	var rows *sql.Rows
	var kpiData kpi
	var num_ok int

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req UpdateKpiReq
	json.Unmarshal(reqdata, &req)

	if req.Data.ID == 0 {
		logs.Info(fmt.Sprintf("updatekpi_2 id ==0"))
		resp.Ret = -1
		goto exit
	}

	b = checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	/*usrinfo, err = getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("updatekpi_5 getUserInfo err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}*/

	sqlstr = fmt.Sprintf("select data from [plan] where ID=%d", req.Data.ID)
	rows, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Info(fmt.Sprintf("updatekpi_2 Query err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}

	for rows.Next() {

		var v string
		if err = rows.Scan(&v); err == nil {
			json.Unmarshal([]byte(v), &kpiData)
		}
	}
	rows.Close()

	kpiData.Plan_state = req.Data.Plan_state
	kpiData.DeliveryDetailInfo = req.Data.DeliveryDetailInfo

	for i := 0; i < len(req.Data.DeliveryDetailInfo); i++ {

		n, _ := strconv.Atoi(req.Data.DeliveryDetailInfo[i].Num_ok)
		num_ok += n
	}
	kpiData.Num_ok = strconv.Itoa(num_ok)

	data, _ = json.Marshal(kpiData)
	sqlstr = fmt.Sprintf(`UPDATE [plan]
   			SET [data] = '%s' WHERE ID=%d`,
		string(data), req.Data.ID)
	fmt.Println(sqlstr)
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("updatekpi_2 Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:

	/*if resp.Ret == 0 && req.OperType == 2 {
		if update_context != "" {
			sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, req.Data.ID, time.Now().Format("2006-01-02 15:04:05"), req.OpUser, update_context)
			_, err = sqlConn.Exec(sqlstr)
			if err != nil {
				logs.Info("postKpi Exec Error:", err.Error())
				resp.Ret = -1
			}
		}
	}*/

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("updatekpi_2 recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func updatePrekpi(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("updatePrekpi recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp UpdateKpiResp

	// 解析请求数据
	reqdata, _ := ioutil.ReadAll(request.Body)
	var req UpdateKpiReq
	json.Unmarshal(reqdata, &req)

	// 检查ID
	if req.Data.ID == 0 {
		logs.Info("updatePrekpi id == 0")
		resp.Ret = -1
	}

	// 检查用户是否在线
	if !checkUserIfOnline(req.OpUser, req.OpUserUuid) {
		logs.Info(fmt.Sprintf("用户%s不在线", req.OpUser))
		resp.Ret = -1
	}

	// 获取用户信息（用于 start_dept）
	usrinfo, err := getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("updatePrekpi getUserInfo err:%s", err.Error()))
		resp.Ret = -1
	}

	// 当前时间、月份
	nowStr := time.Now().Format("2006-01-02 15:04:05")
	month := time.Now().Year()*100 + int(time.Now().Month())

	// 将 req.Data 序列化为 JSON 字符串，存入 data 字段
	dataBytes, err := json.Marshal(req.Data)
	if err != nil {
		logs.Info("updatePrekpi json marshal Error:", err.Error())
		resp.Ret = -1

	}
	dataJSON := string(dataBytes)

	// 转义函数
	escapeSingleQuote := func(s string) string {
		return strings.Replace(s, "'", "''", -1)
	}

	// 构建更新SQL（补全所有字段）
	sqlstr := fmt.Sprintf(`UPDATE [pre_plan] SET
		[time]            = '%s',
		[month]           = %d,
		[data]            = '%s',
		[p_id]            = '%s',
		[p_name]          = '%s',
		[group_leader]    = '%s',
		[p_state]         = '%s',
		[group_name]      = '%s',
		[conveyer]        = '%s',
		[rmd_id]          = '%s',
		[is_frist_process]= '%s',
		[is_img]          = '%s',
		[is_materials]    = '%s',
		[is_new_gauge]    = '%s',
		[start_dept]      = '%s',
		[remarks]         = '%s',
		[task_id]         = '%s',
		[demand_date]     = '%s',
		[total_num]       = '%s',
		[promise_date]    = '%s',
		[file_check]      = '%s'
	WHERE [id] = %d`,

		nowStr,                                     // time
		month,                                      // month
		escapeSingleQuote(dataJSON),                // data
		escapeSingleQuote(req.Data.Product_id),     // p_id
		escapeSingleQuote(req.Data.Product_name),   // p_name
		"",                                         // group_leader（留空或从 req 补充）
		escapeSingleQuote(req.Data.Plan_state),     // p_state
		escapeSingleQuote(req.Data.Group_name),     // group_name
		escapeSingleQuote(req.Data.Conveyer),       // conveyer
		escapeSingleQuote(req.Data.RDM_id),         // rmd_id
		escapeSingleQuote(req.Data.First_procesds), // is_frist_process
		escapeSingleQuote(req.Data.Is_img),         // is_img
		escapeSingleQuote(req.Data.Is_materials),   // is_materials
		escapeSingleQuote(req.Data.Is_new_gauge),   // is_new_gauge
		escapeSingleQuote(usrinfo.Department),      // start_dept（使用当前用户部门）
		escapeSingleQuote(req.Data.Remarks),        // remarks
		escapeSingleQuote(req.Data.Task_id),        // task_id
		escapeSingleQuote(req.Data.Demand_date),    // demand_date
		escapeSingleQuote(req.Data.Total_num),      // total_num
		escapeSingleQuote(req.Data.Promise_date),   // promise_date
		escapeSingleQuote(req.Data.FileCheck),      // file_check
		req.Data.ID)                                // WHERE id

	fmt.Println("Update SQL:", sqlstr)

	// 执行更新
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("updatePrekpi Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:
	// 返回响应
	jdata, _ := json.Marshal(resp)
	response.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Printf("updatePrekpi recv req end, use time: %v ms\n", (endTime-beginTime)/1e6)
}

// func updatePrekpi(response http.ResponseWriter, request *http.Request) {
// 	beginTime := time.Now().UnixNano()
// 	fmt.Println("updatePrekpi recv req begin", time.Now().Format("2006-01-02 15:04:05"))

// 	var resp UpdateKpiResp

// 	// 解析请求数据
// 	reqdata, _ := ioutil.ReadAll(request.Body)
// 	var req UpdateKpiReq
// 	json.Unmarshal(reqdata, &req)

// 	// 检查ID
// 	if req.Data.ID == 0 {
// 		logs.Info("updatePrekpi id == 0")
// 		resp.Ret = -1
// 	}

// 	// 检查用户是否在线
// 	if !checkUserIfOnline(req.OpUser, req.OpUserUuid) {
// 		logs.Info(fmt.Sprintf("用户%s不在线", req.OpUser))
// 		resp.Ret = -1
// 	}

// 	// 对包含单引号的字符串进行转义
// 	escapeSingleQuote := func(s string) string {
// 		return strings.Replace(s, "'", "''", -1)
// 	}

// 	// 构建更新SQL
// 	sqlstr := fmt.Sprintf(`UPDATE [pre_plan] SET
// 		task_id = '%s',
// 		p_id = '%s',
// 		p_name = '%s',
// 		promise_date = '%s',
// 		rmd_id = '%s',
// 		conveyer = '%s',
// 		total_num = '%s',
// 		remarks =  '%s',
// 		file_check =  '%s'
// 		WHERE id = %d`,
// 		escapeSingleQuote(req.Data.Task_id),
// 		req.Data.Product_id,
// 		escapeSingleQuote(req.Data.Product_name),
// 		req.Data.Promise_date,
// 		req.Data.RDM_id,
// 		req.Data.Conveyer,
// 		req.Data.Total_num,
// 		req.Data.Remarks,
// 		req.Data.FileCheck,
// 		req.Data.ID)

// 	fmt.Println("Update SQL:", sqlstr)

// 	// 执行更新
// 	_, err := sqlConn.Exec(sqlstr)
// 	if err != nil {
// 		logs.Info("updatePrekpi Exec Error:", err.Error())
// 		resp.Ret = -1
// 		goto exit
// 	}

// 	resp.Ret = 0

// exit:
// 	// 返回响应
// 	jdata, _ := json.Marshal(resp)
// 	response.Header().Set("Content-Type", "application/json")
// 	fmt.Fprintf(response, string(jdata))

// 	endTime := time.Now().UnixNano()
// 	fmt.Printf("updatePrekpi recv req end, use time: %v ms\n", (endTime-beginTime)/1e6)
// }

// 生产修改入库记录
func update_finished_record(req UpdateKpiReq, kpiData kpi) (resp UpdateKpiResp) {
	var total_num int
	var dispath_num int
	var dispath_total_num int

	var plan_f_date time.Time
	var plan_actual_f_data time.Time

	var data []byte

	var err error
	var sqlstr string

	var stay_d_id int
	var stay_did_name string
	var desc_did_name string

	timeLayout := "2006-01-02 15:04:05"
	loc, _ := time.LoadLocation("Local")

	kpiData.Plan_state = req.Data.Plan_state
	kpiData.Feishu_link = req.Data.Feishu_link
	kpiData.Produce_plan_data = req.Data.Produce_plan_data

	if kpiData.Plan_state == "做账" {
		kpiData.Group_name = "保障组"
	} else {
		kpiData.Group_name = req.Data.Group_name
	}

	stay_did_name = get_department_name_from_did(stay_d_id)
	if kpiData.Plan_state != "入库" {
		task_transfer_update_time(stay_d_id, 1, &kpiData)
		stay_d_id = 1
		desc_did_name = get_department_name_from_did(stay_d_id)
	}

	kpiData.Dispath_num = req.Data.Dispath_num

	total_num, _ = strconv.Atoi(kpiData.Total_num)
	dispath_total_num, _ = strconv.Atoi(kpiData.Dispath_num)
	for i := 0; i < len(kpiData.Produce_plan_data); i++ {
		num, _ := strconv.Atoi(kpiData.Produce_plan_data[i].Dispath_num)
		dispath_num += num

		bt := strings.ReplaceAll(kpiData.Produce_plan_data[i].P_plan_finished_t, "/", "-") + " 00:00:00"
		plan_finished_date, _ := time.ParseInLocation(timeLayout, bt, loc)

		et := strings.ReplaceAll(kpiData.Produce_plan_data[i].P_actual_finished_t, "/", "-") + " 00:00:00"
		actual_finished_t, _ := time.ParseInLocation(timeLayout, et, loc)
		total_h := actual_finished_t.Sub(plan_finished_date).Hours()
		if total_h > 0 {
			kpiData.Produce_plan_data[i].P_finished_overdue_day = int(total_h) / 24
		}

		if i == 0 {
			kpiData.Plan_dispath_date = kpiData.Produce_plan_data[i].Plan_dispath_date
			kpiData.Plan_finished_date = kpiData.Produce_plan_data[i].P_plan_finished_t
			kpiData.Plan_actual_finished_date = kpiData.Produce_plan_data[i].P_actual_finished_t
		} else {
			if kpiData.Plan_dispath_date > kpiData.Produce_plan_data[i].Plan_dispath_date {
				kpiData.Plan_dispath_date = kpiData.Produce_plan_data[i].Plan_dispath_date
			}

			if kpiData.Plan_finished_date < kpiData.Produce_plan_data[i].P_plan_finished_t {
				kpiData.Plan_finished_date = kpiData.Produce_plan_data[i].P_plan_finished_t
			}

			if kpiData.Plan_actual_finished_date < kpiData.Produce_plan_data[i].P_actual_finished_t {
				kpiData.Plan_actual_finished_date = kpiData.Produce_plan_data[i].P_actual_finished_t
			}
		}
	}

	if total_num < dispath_total_num {
		resp.Ret = 3
		goto exit
	}

	plan_f_date, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(kpiData.Plan_finished_date, "/", "-")+" 00:00:00", loc)
	plan_actual_f_data, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(kpiData.Plan_actual_finished_date, "/", "-")+" 00:00:00", loc)
	if plan_actual_f_data.Sub(plan_f_date).Hours() > 0 {
		kpiData.Overdue = "是"
	} else {
		kpiData.Overdue = "否"
	}

	data, _ = json.Marshal(kpiData)
	sqlstr = fmt.Sprintf(`UPDATE [plan]
   			SET [stay_department_id]=%d,[data] = '%s',[group_name]='%s',[p_state]='%s' WHERE ID=%d`,
		stay_d_id, string(data), kpiData.Group_name, kpiData.Plan_state,
		req.Data.ID)
	fmt.Println(sqlstr)
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("update_finished_record Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	if kpiData.Plan_state != "入库" {
		update_context := fmt.Sprintf(`任务从%s转到%s`, stay_did_name, desc_did_name)
		sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, req.Data.ID, time.Now().Format("2006-01-02 15:04:05"), req.OpUser, update_context)
		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("update_finished_record Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}
	}

	resp.Ret = 0

exit:
	return
}

func check_is_finished_record(req UpdateKpiReq) (b bool) {
	sqlstr := fmt.Sprintf("select stay_department_id from [plan] where ID=%d", req.Data.ID)
	rows, err := sqlConn.Query(sqlstr)
	if err != nil {
		logs.Info(fmt.Sprintf("check_is_finished_record Query err:%s", err.Error()))
		return
	}

	for rows.Next() {

		var stay_did int
		if err = rows.Scan(&stay_did); err == nil {
			if stay_did == 0 {
				b = true
			} else {
				b = false
			}
		}
	}
	rows.Close()
	return
}

func check_feishu_link(req UpdateKpiReq) (b bool) {
	if req.Data.Plan_state == "待分解" ||
		req.Data.Plan_state == "待派产" ||
		req.Data.Plan_state == "生产中" ||
		req.Data.Plan_state == "入库" ||
		req.Data.Plan_state == "做账" ||
		req.Data.Plan_state == "检验不合格" {
		if req.Data.Feishu_link == "" {
			b = true
		}
	}
	return
}

func check_feishu_link_ex(req kpi) (b bool) {
	if req.Plan_state == "待分解" ||
		req.Plan_state == "待派产" ||
		req.Plan_state == "生产中" ||
		req.Plan_state == "入库" ||
		req.Plan_state == "做账" ||
		req.Plan_state == "检验不合格" {
		if req.Feishu_link == "" {
			b = true
		}
	}
	return
}

// 导入生产计划
func mul_update_kpi_1(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("mul_update_kpi_1 recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var str []byte

	var resp mul_update_kpi_1_resp
	m := make(map[int]int)
	var kpis_data []kpi

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req mul_update_kpi_1_req
	json.Unmarshal(reqdata, &req)

	timeLayout := "2006-01-02 15:04:05"
	loc, _ := time.LoadLocation("Local")

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Data); i++ {

		if req.Data[i].ID == 0 {
			logs.Info(fmt.Sprintf("mul_update_kpi_1 id ==0"))
			resp.Ret = -1
			goto exit
		}

		if check_feishu_link_ex(req.Data[i]) {
			resp.Err_text = fmt.Sprintf("产品编号:%s 此生产状态下飞书链接不可为空", req.Data[i].Product_id)
			resp.Ret = 2
			goto exit
		}

		if req.Data[i].Plan_state == "入库" || req.Data[i].Plan_state == "做账" {
			for j := 0; j < len(req.Data[i].Produce_plan_data); j++ {
				if req.Data[i].Produce_plan_data[j].P_actual_finished_t == "" {
					resp.Err_text = fmt.Sprintf("产品编号:%s 实际完成日期不可为空！", req.Data[i].Product_id)
					resp.Ret = 2
					goto exit
				}
			}
		}

		for k := 0; k < len(req.Data[i].Produce_plan_data); k++ {
			t := strings.Split(req.Data[i].Produce_plan_data[k].Plan_dispath_date, "/")
			if len(t) == 3 {
				month, _ := strconv.Atoi(t[1])
				day, _ := strconv.Atoi(t[2])
				req.Data[i].Produce_plan_data[k].Plan_dispath_date = fmt.Sprintf(`%s/%02d/%02d`, t[0], month, day)
			}

			t = strings.Split(req.Data[i].Produce_plan_data[k].P_plan_finished_t, "/")
			if len(t) == 3 {
				month, _ := strconv.Atoi(t[1])
				day, _ := strconv.Atoi(t[2])
				req.Data[i].Produce_plan_data[k].P_plan_finished_t = fmt.Sprintf(`%s/%02d/%02d`, t[0], month, day)
			}

			t = strings.Split(req.Data[i].Produce_plan_data[k].P_actual_finished_t, "/")
			if len(t) == 3 {
				month, _ := strconv.Atoi(t[1])
				day, _ := strconv.Atoi(t[2])
				req.Data[i].Produce_plan_data[k].P_actual_finished_t = fmt.Sprintf(`%s/%02d/%02d`, t[0], month, day)
			}
		}

		if index, ok := m[req.Data[i].ID]; !ok {
			kpis_data = append(kpis_data, req.Data[i])
			m[req.Data[i].ID] = len(kpis_data) - 1
		} else {
			kpis_data[index].Produce_plan_data = append(kpis_data[index].Produce_plan_data, req.Data[i].Produce_plan_data...)
		}
	}

	str, _ = json.Marshal(kpis_data)
	fmt.Println(string(str))

	for i := 0; i < len(kpis_data); i++ {

		var plan_fin_num int

		var plan_f_date time.Time
		var plan_actual_f_data time.Time

		var t_plan_fin_time string

		var total_num int
		var dispath_total_num int

		var stay_d_id int
		var stay_did_name string
		var kpiData kpi

		var if_exist bool
		var puser string

		sqlstr := fmt.Sprintf("select stay_department_id,data from [plan] where ID=%d", kpis_data[i].ID)
		rows, err := sqlConn.Query(sqlstr)
		if err != nil {
			logs.Info(fmt.Sprintf("updatekpi_1 Query err:%s", err.Error()))
			resp.Ret = -1
			goto exit
		}

		for rows.Next() {

			var v string
			if err = rows.Scan(&stay_d_id, &v); err == nil {
				json.Unmarshal([]byte(v), &kpiData)
				if_exist = true
			}
		}
		rows.Close()

		if !if_exist {
			logs.Info(fmt.Sprintf("序号:%v 不存在，请联系生产管理员添加！", kpis_data[i].ID))
			resp.Err_text = fmt.Sprintf("序号:%v 不存在，请联系生产管理员添加！", kpis_data[i].ID)
			resp.Ret = 2
			goto exit
		}

		if stay_d_id == 0 {
			resp.Err_text = fmt.Sprintf("序号:%v 已入库不可批量修改操作！", kpis_data[i].ID)
			resp.Ret = 2
			goto exit
		} else if stay_d_id != 1 {
			resp.Err_text = fmt.Sprintf("序号:%v 不在生产部不可批量修改操作！", kpis_data[i].ID)
			resp.Ret = 2
			goto exit
		}

		kpiData.ID = kpis_data[i].ID
		kpiData.Plan_state = kpis_data[i].Plan_state
		if kpiData.Plan_state == "做账" {
			kpiData.Group_name = "保障组"
		} else {
			kpiData.Group_name = kpis_data[i].Group_name
		}
		kpiData.Dispath_num = kpis_data[i].Dispath_num

		kpiData.Feishu_link = kpis_data[i].Feishu_link
		kpiData.Code_state = kpis_data[i].Code_state
		kpiData.Produce_plan_data = []ProduceProcess{}
		kpiData.Produce_plan_data = append(kpiData.Produce_plan_data, kpis_data[i].Produce_plan_data...)

		total_num, _ = strconv.Atoi(kpiData.Total_num)
		dispath_total_num, _ = strconv.Atoi(kpiData.Dispath_num)
		fmt.Println(total_num, dispath_total_num)
		if total_num < dispath_total_num {
			resp.Ret = 3
			goto exit
		}

		for j := 0; j < len(kpiData.Produce_plan_data); j++ {
			kpiData.Produce_plan_data[j].Id = j + 1

			if kpiData.Produce_plan_data[j].Pre_time != "" {
				kpiData.Produce_plan_data[j].Pre_time_checked = true
			}
			if kpiData.Produce_plan_data[j].Code_time != "" {
				kpiData.Produce_plan_data[j].Code_time_checked = true
			}

			if kpiData.Produce_plan_data[j].P_actual_finished_t != "" {
				plan_fin_num++
			}

			if t_plan_fin_time != "" && kpiData.Produce_plan_data[j].Plan_dispath_date < t_plan_fin_time {
				resp.Err_text = fmt.Sprintf("产品编号:%s 工序派产时间不可小于上一个工序实际完成时间，请修改！", kpiData.Product_id)
				resp.Ret = 2
				goto exit
			} else {
				t_plan_fin_time = kpiData.Produce_plan_data[j].P_actual_finished_t
			}

			if kpiData.Produce_plan_data[j].P_actual_finished_t != "" && kpiData.Produce_plan_data[j].P_actual_finished_t < kpiData.Produce_plan_data[j].Plan_dispath_date {
				fmt.Println(kpiData.Produce_plan_data[j].P_actual_finished_t, kpiData.Produce_plan_data[j].Plan_dispath_date)
				resp.Err_text = fmt.Sprintf("产品编号:%s 工序实际完成时间不可小于派产时间，请修改！", kpiData.Product_id)
				resp.Ret = 2
				goto exit
			}

			bt := strings.ReplaceAll(kpiData.Produce_plan_data[j].P_plan_finished_t, "/", "-") + " 00:00:00"
			plan_finished_date, _ := time.ParseInLocation(timeLayout, bt, loc)

			et := strings.ReplaceAll(kpiData.Produce_plan_data[j].P_actual_finished_t, "/", "-") + " 00:00:00"
			actual_finished_t, _ := time.ParseInLocation(timeLayout, et, loc)
			total_h := actual_finished_t.Sub(plan_finished_date).Hours()
			if total_h > 0 {
				kpiData.Produce_plan_data[j].P_finished_overdue_day = int(total_h) / 24
			} else {
				kpiData.Produce_plan_data[j].P_finished_overdue_day = 0
			}

			if j == 0 {
				kpiData.Plan_dispath_date = kpiData.Produce_plan_data[j].Plan_dispath_date
				kpiData.Plan_finished_date = kpiData.Produce_plan_data[j].P_plan_finished_t
				kpiData.Plan_actual_finished_date = kpiData.Produce_plan_data[j].P_actual_finished_t
			} else {
				if kpiData.Plan_dispath_date > kpiData.Produce_plan_data[j].Plan_dispath_date {
					kpiData.Plan_dispath_date = kpiData.Produce_plan_data[j].Plan_dispath_date
				}

				if kpiData.Plan_finished_date < kpiData.Produce_plan_data[j].P_plan_finished_t {
					kpiData.Plan_finished_date = kpiData.Produce_plan_data[j].P_plan_finished_t
				}

				if kpiData.Plan_actual_finished_date < kpiData.Produce_plan_data[j].P_actual_finished_t {
					kpiData.Plan_actual_finished_date = kpiData.Produce_plan_data[j].P_actual_finished_t
				}
			}

			if j == 0 {
				puser += kpiData.Produce_plan_data[j].Produce_user
			} else {
				puser += "," + kpiData.Produce_plan_data[j].Produce_user
			}
		}
		kpiData.Plan_fin_state = fmt.Sprintf(`%d/%d`, plan_fin_num, len(kpiData.Produce_plan_data))

		if kpiData.Plan_actual_finished_date != "" && kpiData.Plan_finished_date != "" {
			plan_f_date, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(kpiData.Plan_finished_date, "/", "-")+" 00:00:00", loc)

			plan_actual_f_data, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(kpiData.Plan_actual_finished_date, "/", "-")+" 00:00:00", loc)
			if plan_actual_f_data.Sub(plan_f_date).Hours() > 0 {
				kpiData.Overdue = "是"
			} else {
				kpiData.Overdue = "否"
			}
		} else if kpiData.Plan_actual_finished_date == "" && kpiData.Plan_finished_date != "" {
			plan_f_date, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(kpiData.Plan_finished_date, "/", "-")+" 00:00:00", loc)

			if time.Now().Sub(plan_f_date).Hours() > 0 {
				kpiData.Overdue = "是"
			} else {
				kpiData.Overdue = "否"
			}
		} else {
			kpiData.Overdue = "否"
		}

		if kpiData.Plan_dispath_date != "" {
			if kpiData.Plan_finished_date < kpiData.Plan_dispath_date {
				resp.Err_text = fmt.Sprintf("产品编号:%s 承诺完成日期不能早于派产日期", kpiData.Product_id)
				resp.Ret = 2
				goto exit
			}

			if kpiData.Plan_actual_finished_date != "" && (kpiData.Plan_actual_finished_date < kpiData.Plan_dispath_date) {
				fmt.Println(kpiData.Plan_actual_finished_date, kpiData.Plan_dispath_date)
				resp.Err_text = fmt.Sprintf("产品编号:%s 实际完成日期不能早于派产日期", kpiData.Product_id)
				resp.Ret = 2
				goto exit
			}
		}

		stay_did_name = get_department_name_from_did(stay_d_id)
		if kpiData.Plan_state == "入库" {
			task_transfer_update_time(stay_d_id, 0, &kpiData)
			stay_d_id = 0
		}

		data, _ := json.Marshal(kpiData)

		sqlstr = fmt.Sprintf(`UPDATE [plan]	SET [stay_department_id]=%d,[data] = '%s',[p_state]='%s',[group_name]='%s'
		,[p_user]='%s'
		 WHERE ID=%d`,
			stay_d_id, string(data), kpiData.Plan_state, kpiData.Group_name,
			puser,
			kpiData.ID)
		fmt.Println(sqlstr)
		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("mul_update_kpi_1 Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}

		if kpiData.Plan_state == "入库" {
			update_context := fmt.Sprintf(`任务从%s转出入库`, stay_did_name)
			sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, kpiData.ID, time.Now().Format("2006-01-02 15:04:05"), req.OpUser, update_context)
			_, err := sqlConn.Exec(sqlstr)
			if err != nil {
				logs.Info("mul_update_kpi_1 Exec Error:", err.Error())
				resp.Ret = -1
				goto exit
			}
		}
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("mul_update_kpi_1 recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func update_notes_1(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("update_notes_1 recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var data []byte

	var err error
	var sqlstr string
	var resp UpdateKpiResp

	var rows *sql.Rows
	var kpiData kpi

	//	timeLayout := "2006-01-02 15:04:05"
	//	loc, _ := time.LoadLocation("Local")

	reqdata, _ := ioutil.ReadAll(request.Body)
	fmt.Println(string(reqdata))
	var req Update_notes_req
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	sqlstr = fmt.Sprintf("select data from [plan] where ID=%d", req.ID)
	rows, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Info(fmt.Sprintf("update_notes_1 Query err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}

	for rows.Next() {

		var v string
		if err = rows.Scan(&v); err == nil {
			json.Unmarshal([]byte(v), &kpiData)
		}
	}
	rows.Close()

	kpiData.Notes = req.Notes

	data, _ = json.Marshal(kpiData)
	sqlstr = fmt.Sprintf(`UPDATE [plan]
   			SET [data] = '%s'
			WHERE ID=%d`,
		string(data), req.ID)
	fmt.Println(sqlstr)
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("update_notes_1 Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("update_notes_1 recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func updatekpi_1(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("updatekpi_1 recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var plan_fin_num int

	var total_num int
	var dispath_num int
	var dispath_total_num int

	var plan_f_date time.Time
	var plan_actual_f_data time.Time

	var data []byte

	var err error
	var sqlstr string
	var resp UpdateKpiResp

	var b bool

	var t_plan_fin_time string

	var rows *sql.Rows
	var kpiData kpi

	var if_exist bool

	var stay_d_id int
	var stay_did_name string

	var puser string

	timeLayout := "2006-01-02 15:04:05"
	loc, _ := time.LoadLocation("Local")

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req UpdateKpiReq
	json.Unmarshal(reqdata, &req)

	if req.Data.ID == 0 {
		logs.Info(fmt.Sprintf("updatekpi_1 id ==0"))
		resp.Ret = -1
		goto exit
	}

	if check_feishu_link(req) {
		resp.Err_text = fmt.Sprintf("产品编号:%s 此生产状态下飞书链接不可为空", req.Data.Product_id)
		resp.Ret = 2
		goto exit
	}

	if req.Data.Plan_dispath_date != "" {
		if req.Data.Plan_finished_date < req.Data.Plan_dispath_date {
			resp.Err_text = fmt.Sprintf("产品编号:%s 承诺完成日期不能早于派产日期", req.Data.Product_id)
			resp.Ret = 2
			goto exit
		}

		if req.Data.Plan_actual_finished_date != "" && (req.Data.Plan_actual_finished_date < req.Data.Plan_dispath_date) {
			resp.Err_text = fmt.Sprintf("产品编号:%s 实际完成日期不能早于派产日期", req.Data.Product_id)
			resp.Ret = 2
			goto exit
		}
	}

	if req.Data.Plan_state == "入库" || req.Data.Plan_state == "做账" {
		for i := 0; i < len(req.Data.Produce_plan_data); i++ {
			if req.Data.Produce_plan_data[i].P_actual_finished_t == "" {
				resp.Err_text = fmt.Sprintf("产品编号:%s 实际完成日期不可为空！", req.Data.Product_id)
				resp.Ret = 2
				goto exit
			}
		}
	}

	b = checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	sqlstr = fmt.Sprintf("select stay_department_id,data from [plan] where ID=%d", req.Data.ID)
	rows, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Info(fmt.Sprintf("updatekpi_1 Query err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}

	for rows.Next() {

		var v string
		if err = rows.Scan(&stay_d_id, &v); err == nil {
			json.Unmarshal([]byte(v), &kpiData)
		}
	}
	rows.Close()

	req.Data.Product_name, if_exist = get_p_info(req.Data.Product_id)
	if !if_exist {
		logs.Info(fmt.Sprintf("产品编号:%s 不存在，请联系生产管理员添加！", req.Data.Product_id))
		resp.Err_text = fmt.Sprintf("产品编号:%s 不存在，请联系生产管理员添加！", req.Data.Product_id)
		resp.Ret = 2
		goto exit
	}

	b = check_is_finished_record(req)
	if b {
		resp = update_finished_record(req, kpiData)
		goto exit
	}

	kpiData.Plan_state = req.Data.Plan_state
	kpiData.Feishu_link = req.Data.Feishu_link
	kpiData.Code_state = req.Data.Code_state
	kpiData.Notes = req.Data.Notes
	kpiData.Produce_plan_data = req.Data.Produce_plan_data

	if kpiData.Plan_state == "做账" {
		kpiData.Group_name = "保障组"
	} else {
		kpiData.Group_name = req.Data.Group_name
	}

	stay_did_name = get_department_name_from_did(stay_d_id)
	if kpiData.Plan_state == "入库" {
		task_transfer_update_time(stay_d_id, 0, &kpiData)
		stay_d_id = 0
	}

	kpiData.Dispath_num = req.Data.Dispath_num

	total_num, _ = strconv.Atoi(kpiData.Total_num)
	dispath_total_num, _ = strconv.Atoi(kpiData.Dispath_num)
	for i := 0; i < len(kpiData.Produce_plan_data); i++ {

		if kpiData.Produce_plan_data[i].P_actual_finished_t != "" {
			plan_fin_num++
		}

		if t_plan_fin_time != "" && req.Data.Produce_plan_data[i].Plan_dispath_date < t_plan_fin_time {
			resp.Err_text = fmt.Sprintf("产品编号:%s 工序派产时间不可小于上一个工序实际完成时间，请修改！", req.Data.Product_id)
			resp.Ret = 2
			goto exit
		} else {
			t_plan_fin_time = req.Data.Produce_plan_data[i].P_actual_finished_t
		}

		if req.Data.Produce_plan_data[i].P_actual_finished_t != "" && req.Data.Produce_plan_data[i].P_actual_finished_t < req.Data.Produce_plan_data[i].Plan_dispath_date {
			resp.Err_text = fmt.Sprintf("产品编号:%s 工序实际完成时间不可小于派产时间，请修改！", req.Data.Product_id)
			resp.Ret = 2
			goto exit
		}

		num, _ := strconv.Atoi(kpiData.Produce_plan_data[i].Dispath_num)
		dispath_num += num

		bt := strings.ReplaceAll(kpiData.Produce_plan_data[i].P_plan_finished_t, "/", "-") + " 00:00:00"
		plan_finished_date, _ := time.ParseInLocation(timeLayout, bt, loc)

		et := strings.ReplaceAll(kpiData.Produce_plan_data[i].P_actual_finished_t, "/", "-") + " 00:00:00"
		actual_finished_t, _ := time.ParseInLocation(timeLayout, et, loc)
		total_h := actual_finished_t.Sub(plan_finished_date).Hours()
		if total_h > 0 {
			kpiData.Produce_plan_data[i].P_finished_overdue_day = int(total_h) / 24
		} else {
			kpiData.Produce_plan_data[i].P_finished_overdue_day = 0
		}

		if i == 0 {
			kpiData.Plan_dispath_date = kpiData.Produce_plan_data[i].Plan_dispath_date
			kpiData.Plan_finished_date = kpiData.Produce_plan_data[i].P_plan_finished_t
			kpiData.Plan_actual_finished_date = kpiData.Produce_plan_data[i].P_actual_finished_t
		} else {
			if kpiData.Plan_dispath_date > kpiData.Produce_plan_data[i].Plan_dispath_date {
				kpiData.Plan_dispath_date = kpiData.Produce_plan_data[i].Plan_dispath_date
			}

			if kpiData.Plan_finished_date < kpiData.Produce_plan_data[i].P_plan_finished_t {
				kpiData.Plan_finished_date = kpiData.Produce_plan_data[i].P_plan_finished_t
			}

			if kpiData.Plan_actual_finished_date < kpiData.Produce_plan_data[i].P_actual_finished_t {
				kpiData.Plan_actual_finished_date = kpiData.Produce_plan_data[i].P_actual_finished_t
			}
		}

		if i == 0 {
			puser += kpiData.Produce_plan_data[i].Produce_user
		} else {
			puser += "," + kpiData.Produce_plan_data[i].Produce_user
		}
	}
	kpiData.Plan_fin_state = fmt.Sprintf(`%d/%d`, plan_fin_num, len(kpiData.Produce_plan_data))

	if total_num < dispath_total_num {
		resp.Ret = 3
		goto exit
	}

	if kpiData.Plan_actual_finished_date != "" && kpiData.Plan_finished_date != "" {
		plan_f_date, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(kpiData.Plan_finished_date, "/", "-")+" 00:00:00", loc)

		plan_actual_f_data, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(kpiData.Plan_actual_finished_date, "/", "-")+" 00:00:00", loc)
		if plan_actual_f_data.Sub(plan_f_date).Hours() > 0 {
			kpiData.Overdue = "是"
		} else {
			kpiData.Overdue = "否"
		}
	} else if kpiData.Plan_actual_finished_date == "" && kpiData.Plan_finished_date != "" {
		plan_f_date, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(kpiData.Plan_finished_date, "/", "-")+" 00:00:00", loc)

		if time.Now().Sub(plan_f_date).Hours() > 0 {
			kpiData.Overdue = "是"
		} else {
			kpiData.Overdue = "否"
		}
	} else {
		kpiData.Overdue = "否"
	}

	data, _ = json.Marshal(kpiData)
	sqlstr = fmt.Sprintf(`UPDATE [plan]
   			SET [stay_department_id]=%d,[data] = '%s',[p_state]='%s',[group_name]='%s' 
			,[p_user]='%s'
			WHERE ID=%d`,
		stay_d_id, string(data), kpiData.Plan_state, kpiData.Group_name,
		puser,
		req.Data.ID)
	fmt.Println(sqlstr)
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("updatekpi_1 Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	if kpiData.Plan_state == "入库" {
		update_context := fmt.Sprintf(`任务从%s转出入库`, stay_did_name)
		sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, req.Data.ID, time.Now().Format("2006-01-02 15:04:05"), req.OpUser, update_context)
		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("updatekpi_1 Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}
	}

	resp.Ret = 0

exit:

	/*if resp.Ret == 0 && req.OperType == 2 {
		if update_context != "" {
			sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, req.Data.ID, time.Now().Format("2006-01-02 15:04:05"), req.OpUser, update_context)
			_, err = sqlConn.Exec(sqlstr)
			if err != nil {
				logs.Info("postKpi Exec Error:", err.Error())
				resp.Ret = -1
			}
		}
	}*/

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("updatekpi_1 recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func updatekpi_1_ex(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("updatekpi_1_ex recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var plan_fin_num int

	var total_num int
	var dispath_total_num int

	var plan_f_date time.Time
	var plan_actual_f_data time.Time

	var data []byte

	var err error
	var sqlstr string
	var resp UpdateKpiResp

	var b bool

	var t_plan_fin_time string

	var rows *sql.Rows
	var kpiData kpi

	var if_exist bool

	var stay_d_id int
	var stay_did_name string

	var puser string

	timeLayout := "2006-01-02 15:04:05"
	loc, _ := time.LoadLocation("Local")

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req UpdateKpiReq
	json.Unmarshal(reqdata, &req)

	if req.Data.ID == 0 {
		logs.Info(fmt.Sprintf("updatekpi_1 id ==0"))
		resp.Ret = -1
		goto exit
	}

	if check_feishu_link(req) {
		resp.Err_text = fmt.Sprintf("产品编号:%s 此生产状态下飞书链接不可为空", req.Data.Product_id)
		resp.Ret = 2
		goto exit
	}

	if req.Data.Plan_dispath_date != "" {
		if req.Data.Plan_finished_date < req.Data.Plan_dispath_date {
			resp.Err_text = fmt.Sprintf("产品编号:%s 承诺完成日期不能早于派产日期", req.Data.Product_id)
			resp.Ret = 2
			goto exit
		}

		if req.Data.Plan_actual_finished_date != "" && (req.Data.Plan_actual_finished_date < req.Data.Plan_dispath_date) {
			resp.Err_text = fmt.Sprintf("产品编号:%s 实际完成日期不能早于派产日期", req.Data.Product_id)
			resp.Ret = 2
			goto exit
		}
	}

	if req.Data.Plan_state == "入库" || req.Data.Plan_state == "做账" {
		for i := 0; i < len(req.Data.Produce_plan_data); i++ {
			if req.Data.Produce_plan_data[i].P_actual_finished_t == "" {
				resp.Err_text = fmt.Sprintf("产品编号:%s 实际完成日期不可为空！", req.Data.Product_id)
				resp.Ret = 2
				goto exit
			}
		}
	}

	b = checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	sqlstr = fmt.Sprintf("select stay_department_id,data from [plan] where ID=%d", req.Data.ID)
	rows, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Info(fmt.Sprintf("updatekpi_1_ex Query err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}

	for rows.Next() {

		var v string
		if err = rows.Scan(&stay_d_id, &v); err == nil {
			json.Unmarshal([]byte(v), &kpiData)
		}
	}
	rows.Close()

	req.Data.Product_name, if_exist = get_p_info(req.Data.Product_id)
	if !if_exist {
		logs.Info(fmt.Sprintf("产品编号:%s 不存在，请联系生产管理员添加！", req.Data.Product_id))
		resp.Err_text = fmt.Sprintf("产品编号:%s 不存在，请联系生产管理员添加！", req.Data.Product_id)
		resp.Ret = 2
		goto exit
	}

	kpiData.Task_id = req.Data.Task_id
	kpiData.Product_id = req.Data.Product_id
	kpiData.Product_name = req.Data.Product_name
	kpiData.Total_num = req.Data.Total_num

	kpiData.Demand_date = req.Data.Demand_date
	kpiData.RDM_id = req.Data.RDM_id
	kpiData.Conveyer = req.Data.Conveyer

	kpiData.Plan_state = req.Data.Plan_state
	kpiData.Feishu_link = req.Data.Feishu_link
	kpiData.Code_state = req.Data.Code_state
	kpiData.Notes = req.Data.Notes
	kpiData.Produce_plan_data = req.Data.Produce_plan_data

	if kpiData.Plan_state == "做账" {
		kpiData.Group_name = "保障组"
	} else {
		kpiData.Group_name = req.Data.Group_name
	}

	stay_did_name = get_department_name_from_did(stay_d_id)
	if kpiData.Plan_state == "入库" {
		task_transfer_update_time(stay_d_id, 0, &kpiData)
		stay_d_id = 0
	}

	kpiData.Dispath_num = req.Data.Dispath_num

	total_num, _ = strconv.Atoi(kpiData.Total_num)
	dispath_total_num, _ = strconv.Atoi(kpiData.Dispath_num)
	for i := 0; i < len(kpiData.Produce_plan_data); i++ {

		if kpiData.Produce_plan_data[i].P_actual_finished_t != "" {
			plan_fin_num++
		}

		if t_plan_fin_time != "" && req.Data.Produce_plan_data[i].Plan_dispath_date < t_plan_fin_time {
			resp.Err_text = fmt.Sprintf("产品编号:%s 工序派产时间不可小于上一个工序实际完成时间，请修改！", req.Data.Product_id)
			resp.Ret = 2
			goto exit
		} else {
			t_plan_fin_time = req.Data.Produce_plan_data[i].P_actual_finished_t
		}

		if req.Data.Produce_plan_data[i].P_actual_finished_t != "" && req.Data.Produce_plan_data[i].P_actual_finished_t < req.Data.Produce_plan_data[i].Plan_dispath_date {
			resp.Err_text = fmt.Sprintf("产品编号:%s 工序实际完成时间不可小于派产时间，请修改！", req.Data.Product_id)
			resp.Ret = 2
			goto exit
		}

		bt := strings.ReplaceAll(kpiData.Produce_plan_data[i].P_plan_finished_t, "/", "-") + " 00:00:00"
		plan_finished_date, _ := time.ParseInLocation(timeLayout, bt, loc)

		et := strings.ReplaceAll(kpiData.Produce_plan_data[i].P_actual_finished_t, "/", "-") + " 00:00:00"
		actual_finished_t, _ := time.ParseInLocation(timeLayout, et, loc)
		total_h := actual_finished_t.Sub(plan_finished_date).Hours()
		if total_h > 0 {
			kpiData.Produce_plan_data[i].P_finished_overdue_day = int(total_h) / 24
		} else {
			kpiData.Produce_plan_data[i].P_finished_overdue_day = 0
		}

		if i == 0 {
			kpiData.Plan_dispath_date = kpiData.Produce_plan_data[i].Plan_dispath_date
			kpiData.Plan_finished_date = kpiData.Produce_plan_data[i].P_plan_finished_t
			kpiData.Plan_actual_finished_date = kpiData.Produce_plan_data[i].P_actual_finished_t
		} else {
			if kpiData.Plan_dispath_date > kpiData.Produce_plan_data[i].Plan_dispath_date {
				kpiData.Plan_dispath_date = kpiData.Produce_plan_data[i].Plan_dispath_date
			}

			if kpiData.Plan_finished_date < kpiData.Produce_plan_data[i].P_plan_finished_t {
				kpiData.Plan_finished_date = kpiData.Produce_plan_data[i].P_plan_finished_t
			}

			if kpiData.Plan_actual_finished_date < kpiData.Produce_plan_data[i].P_actual_finished_t {
				kpiData.Plan_actual_finished_date = kpiData.Produce_plan_data[i].P_actual_finished_t
			}
		}

		if i == 0 {
			puser += kpiData.Produce_plan_data[i].Produce_user
		} else {
			puser += "," + kpiData.Produce_plan_data[i].Produce_user
		}
	}
	kpiData.Plan_fin_state = fmt.Sprintf(`%d/%d`, plan_fin_num, len(kpiData.Produce_plan_data))

	if total_num < dispath_total_num {
		resp.Ret = 3
		goto exit
	}

	/*for k, v := range plan_map {
		if dispath_total_num < v {
			resp.Err_text = fmt.Sprintf("单工序(%s)派产数量不可大于派产总数！", k)
			resp.Ret = 2
			goto exit
		}
	}*/

	if kpiData.Plan_actual_finished_date != "" && kpiData.Plan_finished_date != "" {
		plan_f_date, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(kpiData.Plan_finished_date, "/", "-")+" 00:00:00", loc)

		plan_actual_f_data, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(kpiData.Plan_actual_finished_date, "/", "-")+" 00:00:00", loc)
		if plan_actual_f_data.Sub(plan_f_date).Hours() > 0 {
			kpiData.Overdue = "是"
		} else {
			kpiData.Overdue = "否"
		}
	} else if kpiData.Plan_actual_finished_date == "" && kpiData.Plan_finished_date != "" {
		plan_f_date, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(kpiData.Plan_finished_date, "/", "-")+" 00:00:00", loc)

		if time.Now().Sub(plan_f_date).Hours() > 0 {
			kpiData.Overdue = "是"
		} else {
			kpiData.Overdue = "否"
		}
	} else {
		kpiData.Overdue = "否"
	}

	data, _ = json.Marshal(kpiData)
	sqlstr = fmt.Sprintf(`UPDATE [plan]
   			SET [stay_department_id]=%d,[data] = '%s',[p_id]='%s',[p_name]='%s',[p_state]='%s',[group_name]='%s',[task_id]='%s',
			[conveyer]='%s',
			[rmd_id]='%s' 
			,[p_user]='%s'
			WHERE ID=%d`,
		stay_d_id, string(data), kpiData.Product_id, kpiData.Product_name, kpiData.Plan_state, kpiData.Group_name, kpiData.Task_id,
		kpiData.Conveyer, kpiData.RDM_id,
		puser,
		req.Data.ID)
	fmt.Println(sqlstr)
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("updatekpi_1_ex Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	if kpiData.Plan_state == "入库" {
		update_context := fmt.Sprintf(`任务从%s转出入库`, stay_did_name)
		sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, req.Data.ID, time.Now().Format("2006-01-02 15:04:05"), req.OpUser, update_context)
		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("updatekpi_1_ex Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}
	}

	resp.Ret = 0

exit:

	/*if resp.Ret == 0 && req.OperType == 2 {
		if update_context != "" {
			sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, req.Data.ID, time.Now().Format("2006-01-02 15:04:05"), req.OpUser, update_context)
			_, err = sqlConn.Exec(sqlstr)
			if err != nil {
				logs.Info("postKpi Exec Error:", err.Error())
				resp.Ret = -1
			}
		}
	}*/

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("updatekpi_1_ex recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func updatekpi_3(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("updatekpi_3 recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var promise_date time.Time
	var promised_date time.Time

	timeLayout := "2006-01-02 15:04:05"
	loc, _ := time.LoadLocation("Local")

	var data []byte
	//	var month int

	var err error
	var sqlstr string
	var resp UpdateKpiResp

	var b bool

	//	var usrinfo useInfo
	//	var update_context string

	var rows *sql.Rows
	var kpiData kpi

	var if_exist bool

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req UpdateKpiReq
	json.Unmarshal(reqdata, &req)

	if req.Data.ID == 0 {
		logs.Info(fmt.Sprintf("updatekpi_3 id ==0"))
		resp.Ret = -1
		goto exit
	}

	b = checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	/*usrinfo, err = getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("updatekpi_5 getUserInfo err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}*/

	sqlstr = fmt.Sprintf("select data from [plan] where ID=%d", req.Data.ID)
	rows, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Info(fmt.Sprintf("updatekpi_3 Query err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}

	for rows.Next() {

		var v string
		if err = rows.Scan(&v); err == nil {
			json.Unmarshal([]byte(v), &kpiData)
		}
	}
	rows.Close()

	req.Data.Product_name, if_exist = get_p_info(req.Data.Product_id)
	if !if_exist {
		logs.Info(fmt.Sprintf("产品编号:%s 不存在，请联系生产管理员添加！", req.Data.Product_id))
		resp.Err_text = fmt.Sprintf("产品编号:%s 不存在，请联系生产管理员添加！", req.Data.Product_id)
		resp.Ret = 2
		goto exit
	}

	//kpiData.Plan_state = req.Data.Plan_state
	kpiData.Material_inventory = req.Data.Material_inventory
	kpiData.Promise_date = req.Data.Promise_date
	kpiData.Promised_date = req.Data.Promised_date
	kpiData.Buyer = req.Data.Buyer
	kpiData.Material_p = req.Data.Material_p

	promise_date, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(req.Data.Promise_date, "/", "-")+" 00:00:00", loc)
	promised_date, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(req.Data.Promised_date, "/", "-")+" 00:00:00", loc)
	if promised_date.Sub(promise_date).Hours() > 0 {
		kpiData.Material_overdue = "是"
	} else {
		kpiData.Material_overdue = "否"
	}

	data, _ = json.Marshal(kpiData)
	sqlstr = fmt.Sprintf(`UPDATE [plan]
   			SET [data] = '%s',[promise_date]='%s' WHERE ID=%d`,
		string(data), kpiData.Promise_date, req.Data.ID)
	fmt.Println(sqlstr)
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("updatekpi_3 Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:

	/*if resp.Ret == 0 && req.OperType == 2 {
		if update_context != "" {
			sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, req.Data.ID, time.Now().Format("2006-01-02 15:04:05"), req.OpUser, update_context)
			_, err = sqlConn.Exec(sqlstr)
			if err != nil {
				logs.Info("postKpi Exec Error:", err.Error())
				resp.Ret = -1
			}
		}
	}*/

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("updatekpi_3 recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func updatekpi_3_ex(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("updatekpi_3_ex recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var promise_date time.Time
	var promised_date time.Time

	timeLayout := "2006-01-02 15:04:05"
	loc, _ := time.LoadLocation("Local")

	var data []byte
	//	var month int

	var err error
	var sqlstr string
	var resp UpdateKpiResp

	var b bool

	//	var usrinfo useInfo
	//	var update_context string

	var rows *sql.Rows
	var kpiData kpi

	var if_exist bool

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req UpdateKpiReq
	json.Unmarshal(reqdata, &req)

	if req.Data.ID == 0 {
		logs.Info(fmt.Sprintf("updatekpi_3_ex id ==0"))
		resp.Ret = -1
		goto exit
	}

	b = checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	/*usrinfo, err = getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("updatekpi_5 getUserInfo err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}*/

	sqlstr = fmt.Sprintf("select data from [plan] where ID=%d", req.Data.ID)
	rows, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Info(fmt.Sprintf("updatekpi_3_ex Query err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}

	for rows.Next() {

		var v string
		if err = rows.Scan(&v); err == nil {
			json.Unmarshal([]byte(v), &kpiData)
		}
	}
	rows.Close()

	req.Data.Product_name, if_exist = get_p_info(req.Data.Product_id)
	if !if_exist {
		logs.Info(fmt.Sprintf("产品编号:%s 不存在，请联系生产管理员添加！", req.Data.Product_id))
		resp.Err_text = fmt.Sprintf("产品编号:%s 不存在，请联系生产管理员添加！", req.Data.Product_id)
		resp.Ret = 2
		goto exit
	}

	kpiData.Priority = req.Data.Priority
	//kpiData.Department_name = req.Data.Department_name
	kpiData.Task_id = req.Data.Task_id
	kpiData.Product_id = req.Data.Product_id
	kpiData.Product_name = req.Data.Product_name
	kpiData.Total_num = req.Data.Total_num
	//kpiData.Plan_state = req.Data.Plan_state

	kpiData.Material_inventory = req.Data.Material_inventory
	kpiData.Promise_date = req.Data.Promise_date
	kpiData.Promised_date = req.Data.Promised_date
	kpiData.Buyer = req.Data.Buyer

	kpiData.Demand_date = req.Data.Demand_date
	kpiData.RDM_id = req.Data.RDM_id
	kpiData.Conveyer = req.Data.Conveyer
	kpiData.Material_p = req.Data.Material_p

	promise_date, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(req.Data.Promise_date, "/", "-")+" 00:00:00", loc)
	promised_date, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(req.Data.Promised_date, "/", "-")+" 00:00:00", loc)
	if promised_date.Sub(promise_date).Hours() > 0 {
		kpiData.Material_overdue = "是"
	} else {
		kpiData.Material_overdue = "否"
	}

	data, _ = json.Marshal(kpiData)
	sqlstr = fmt.Sprintf(`UPDATE [plan]
   			SET [data] = '%s',[p_id]='%s',[p_name]='%s',[task_id]='%s',[promise_date]='%s',
			[conveyer]='%s',
			[rmd_id]='%s' WHERE ID=%d`,
		string(data), kpiData.Product_id, kpiData.Product_name, kpiData.Task_id, kpiData.Promise_date,
		kpiData.Conveyer, kpiData.RDM_id,
		req.Data.ID)
	fmt.Println(sqlstr)
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("updatekpi_3_ex Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:

	/*if resp.Ret == 0 && req.OperType == 2 {
		if update_context != "" {
			sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, req.Data.ID, time.Now().Format("2006-01-02 15:04:05"), req.OpUser, update_context)
			_, err = sqlConn.Exec(sqlstr)
			if err != nil {
				logs.Info("postKpi Exec Error:", err.Error())
				resp.Ret = -1
			}
		}
	}*/

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("updatekpi_3_ex recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func updatekpi_5(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("updatekpi_5 recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var data []byte
	//	var month int

	var err error
	var sqlstr string
	var resp UpdateKpiResp

	var b bool

	//	var usrinfo useInfo
	//	var update_context string

	var rows *sql.Rows
	var kpiData kpi

	var if_exist bool

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req UpdateKpiReq
	json.Unmarshal(reqdata, &req)
	escapeSingleQuote := func(s string) string {
		return strings.Replace(s, "'", "''", -1)
	}
	if req.Data.ID == 0 {
		logs.Info(fmt.Sprintf("updatekpi_5 id ==0"))
		resp.Ret = -1
		goto exit
	}

	b = checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	/*usrinfo, err = getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("updatekpi_5 getUserInfo err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}*/

	sqlstr = fmt.Sprintf("select data from [plan] where ID=%d", req.Data.ID)
	rows, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Info(fmt.Sprintf("updatekpi_5 Query err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}

	for rows.Next() {

		var v string
		if err = rows.Scan(&v); err == nil {
			json.Unmarshal([]byte(v), &kpiData)
		}
	}
	rows.Close()

	req.Data.Product_name, if_exist = get_p_info(req.Data.Product_id)

	if !if_exist {
		logs.Info(fmt.Sprintf("产品编号:%s 不存在，请联系生产管理员添加！", req.Data.Product_id))
		resp.Err_text = fmt.Sprintf("产品编号:%s 不存在，请联系生产管理员添加！", req.Data.Product_id)
		resp.Ret = 2
		goto exit
	}

	kpiData.Task_id = req.Data.Task_id
	kpiData.Product_id = req.Data.Product_id
	kpiData.Product_name = req.Data.Product_name
	kpiData.Total_num = req.Data.Total_num
	kpiData.Demand_date = req.Data.Demand_date
	kpiData.RDM_id = req.Data.RDM_id
	kpiData.Conveyer = req.Data.Conveyer

	data, _ = json.Marshal(kpiData)

	sqlstr = fmt.Sprintf(`UPDATE [plan]
   			SET [data] = '%s',[p_id]='%s',[p_name]='%s',[task_id]='%s',
			[conveyer]='%s',
			[rmd_id]='%s' WHERE ID=%d`,
		escapeSingleQuote(string(data)), kpiData.Product_id, escapeSingleQuote(kpiData.Product_name), kpiData.Task_id,
		kpiData.Conveyer, kpiData.RDM_id,
		req.Data.ID)
	fmt.Println(sqlstr)
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("updatekpi_5 Exec Error:", err.Error())
		fmt.Println("updatekpi_5 Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:

	/*if resp.Ret == 0 && req.OperType == 2 {
		if update_context != "" {
			sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, req.Data.ID, time.Now().Format("2006-01-02 15:04:05"), req.OpUser, update_context)
			_, err = sqlConn.Exec(sqlstr)
			if err != nil {
				logs.Info("postKpi Exec Error:", err.Error())
				resp.Ret = -1
			}
		}
	}*/

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("updatekpi_5 recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func importKpi(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("importKpi recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var data []byte
	var month int

	var err error
	var sqlstr string
	var resp import_kpi_resp

	var usrinfo useInfo
	var err_context1 string
	var err_context2 string
	var err_context3 string
	var err_context4 string

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req importKpiReq
	json.Unmarshal(reqdata, &req)
	fmt.Println("Data------", req.Data)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	usrinfo, err = getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("importKpi getUserInfo err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Data); i++ {
		v := req.Data[i]

		if v.Task_id == "" || v.Product_id == "" || v.Total_num == "" ||
			v.Demand_date == "" || v.Conveyer == "" {
			resp.Err_text = "计划/项目号,产品编号,数量,需求日期,RDM任务号,交付人不可为空！"
			resp.Ret = 1
			goto exit
		}

		if v.Total_num != "" {
			n, err := strconv.Atoi(v.Total_num)
			if err != nil {
				if err_context1 == "" {
					err_context1 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
				} else {
					err_context1 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
				}
			} else {
				if n > 9999 {
					if err_context1 == "" {
						err_context1 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
					} else {
						err_context1 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
					}
				}
			}
		}

		if v.RDM_id != "" {
			v.RDM_id = strings.ReplaceAll(v.RDM_id, "#", "")
			n, err := strconv.Atoi(v.RDM_id)
			if err != nil {
				if err_context2 == "" {
					err_context2 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
				} else {
					err_context2 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
				}
			} else {
				if n > 9999999 {
					if err_context2 == "" {
						err_context2 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
					} else {
						err_context2 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
					}
				}
			}
		}

		sqlstr = fmt.Sprintf("select [p_name] from [sap] where p_id='%s'", v.Product_id)
		fmt.Println(sqlstr)

		rdRow, err := sqlConn.Query(sqlstr)
		if err != nil {
			logs.Error(fmt.Sprintf("importKpi Query err:%v", err.Error()))
			goto exit
		}

		var p_name string
		for rdRow.Next() {
			if err := rdRow.Scan(&p_name); err == nil {
			} else {
				logs.Error("importKpi scan Error", err.Error())
			}
		}
		rdRow.Close()

		if p_name == "" {
			if err_context3 == "" {
				err_context3 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
			} else {
				err_context3 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
			}
		} else {
			req.Data[i].Product_name = p_name
		}

		demand_t := req.Data[i].Demand_date
		demand_t = strings.ReplaceAll(demand_t, "-", "/")
		t := strings.Split(demand_t, "/")
		if len(t) == 3 {
			month, _ := strconv.Atoi(t[1])
			day, _ := strconv.Atoi(t[2])
			demand_time := fmt.Sprintf(`%s-%02d-%02d 00:00:00`, t[0], month, day)
			fmt.Println(demand_time)

			timeLayout := "2006-01-02 15:04:05"
			loc, _ := time.LoadLocation("Local")

			bt, _ := time.ParseInLocation(timeLayout, demand_time, loc)
			if int(bt.Sub(time.Now()).Hours()) < 72 {
				if err_context4 == "" {
					err_context4 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
				} else {
					err_context4 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
				}
			}
		}
	}

	if err_context1 != "" {
		err_context1 += " 数量含非数字或大于9999，请仔细核对！"
	}
	if err_context2 != "" {
		err_context2 += " RDM任务号只允许1-9999999，请仔细核对！"
	}

	if err_context3 != "" {
		err_context3 += " 不存在，请联系生产管理员添加！"
	}

	if err_context4 != "" {
		err_context4 += " 需求日期必须大于当前日期三天及以上！"
	}

	if err_context1 != "" || err_context2 != "" || err_context3 != "" || err_context4 != "" {
		resp.Err_text = err_context3 + err_context2 + err_context1 + err_context4
		resp.Ret = 1
		goto exit
	}

	for i := 0; i < len(req.Data); i++ {
		req.Data[i].RDM_id = strings.ReplaceAll(req.Data[i].RDM_id, "#", "")

		demand_t := req.Data[i].Demand_date
		demand_t = strings.ReplaceAll(demand_t, "-", "/")
		t := strings.Split(demand_t, "/")
		if len(t) == 3 {
			month, _ := strconv.Atoi(t[1])
			day, _ := strconv.Atoi(t[2])
			req.Data[i].Demand_date = fmt.Sprintf(`%s/%02d/%02d`, t[0], month, day)
		}

		var maxid int
		var rows *sql.Rows

		var start_department_id int
		var stay_department_id int
		var scan_flag int
		//mark stay did
		text := req.Data[i].Plan_state
		if text == "" {
			start_department_id = usrinfo.DepartmentId
			stay_department_id = start_department_id
			scan_flag = 1 << (usrinfo.DepartmentId - 1)

			task_transfer_update_time(0, usrinfo.DepartmentId, &req.Data[i])
		} else {
			start_department_id = usrinfo.DepartmentId
			task_transfer_update_time(0, usrinfo.DepartmentId, &req.Data[i])

			if strings.Contains(text, "核对物料") {
				stay_department_id = 3
			} else {
				stay_department_id = start_department_id
			}
			task_transfer_update_time(start_department_id, stay_department_id, &req.Data[i])

			scan_flag = (1 << (start_department_id - 1)) | (1 << (stay_department_id - 1))
		}

		req.Data[i].Department_name = usrinfo.Department
		req.Data[i].Plan_state = ""
		if req.Data[i].Plan_state == "" {
			req.Data[i].Plan_state = "待分解"
		}
		data, _ = json.Marshal(req.Data[i])
		month = time.Now().Year()*100 + int(time.Now().Month())

		// 对包含单引号的字符串进行转义
		escapeSingleQuote := func(s string) string {
			return strings.Replace(s, "'", "''", -1)
		}

		sqlstr = fmt.Sprintf(`INSERT INTO [plan]
             ([time]
             ,[month]
             ,[data]
             ,[start_department_id]
             ,[stay_department_id]
             ,[scan_flag]
             ,[del_flag]
            ,[p_id]
            ,[p_name]
            ,[group_leader]
    ,[p_state]
            ,[group_name]
    ,[task_id]
    ,[conveyer]
    ,[rmd_id])
               VALUES ('%s',%d,'%s',%d,%d,%d,%d,'%s','%s','%s','%s','%s','%s','%s','%s')`,
			time.Now().Format("2006-01-02 15:04:05"), month,
			escapeSingleQuote(string(data)), // 转义JSON中的单引号
			start_department_id, stay_department_id,
			scan_flag, 0,
			escapeSingleQuote(req.Data[i].Product_id),
			escapeSingleQuote(req.Data[i].Product_name),
			"",
			req.Data[i].Plan_state,
			escapeSingleQuote(req.Data[i].Group_name),
			escapeSingleQuote(req.Data[i].Task_id),
			escapeSingleQuote(req.Data[i].Conveyer),
			escapeSingleQuote(req.Data[i].RDM_id))

		mu.Lock()
		_, err = sqlConn.Exec(sqlstr)
		fmt.Println("sqlstr-------------------", sqlstr)
		if err != nil {
			mu.Unlock()
			logs.Info("importKpi Exec Error:", err.Error())
			fmt.Println("sqlstr-------------------", err.Error())
			resp.Ret = -1
			goto exit
		}

		//获取id
		sqlstr = fmt.Sprintf(`SELECT top 1 [ID] FROM [plan] order by ID desc`)
		rows, err = sqlConn.Query(sqlstr)
		if err == nil {

			for rows.Next() {
				if err = rows.Scan(&maxid); err != nil {
					logs.Info("addKpi scan Error:", err.Error())
				}
			}

			rows.Close()
		}
		mu.Unlock()

		if maxid > 0 {

			now_time := time.Now().Format("2006-01-02 15:04:05")
			update_context := fmt.Sprintf(`任务导入`)
			sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, maxid, now_time, req.OpUser, update_context)
			_, err = sqlConn.Exec(sqlstr)
			if err != nil {
				logs.Info("importKpi Exec Error:", err.Error())
				goto exit
			}

			if stay_department_id != start_department_id {
				stay_did_name := get_department_name_from_did(stay_department_id)
				update_context = fmt.Sprintf(`任务从%s转到%s`, usrinfo.Department, stay_did_name)
				sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, maxid, now_time, req.OpUser, update_context)
				_, err = sqlConn.Exec(sqlstr)
				if err != nil {
					logs.Info("importKpi Exec Error:", err.Error())
					goto exit
				}
			}
		}
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("importKpi recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func importPreTaskKpi(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("importKpi recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var data []byte
	var month int

	var err error
	var sqlstr string
	var resp import_kpi_resp

	var usrinfo useInfo
	var err_context1 string
	var err_context2 string
	var err_context3 string
	var err_context4 string
	var err_context5 string

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req importKpiReq
	json.Unmarshal(reqdata, &req)
	fmt.Println("Data------", req.Data)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	usrinfo, err = getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("importKpi getUserInfo err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Data); i++ {
		v := req.Data[i]
		fmt.Println("v.Demand_date == ", v.Demand_date)

		if v.Demand_date == "" {
			resp.Err_text = "生产回复日期不可为空！"
			resp.Ret = 1
			goto exit
		}

		if v.Total_num != "" {
			n, err := strconv.Atoi(v.Total_num)
			if err != nil {
				if err_context1 == "" {
					err_context1 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
				} else {
					err_context1 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
				}
			} else {
				if n > 9999 {
					if err_context1 == "" {
						err_context1 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
					} else {
						err_context1 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
					}
				}
			}
		}

		if v.RDM_id != "" {
			v.RDM_id = strings.ReplaceAll(v.RDM_id, "#", "")
			n, err := strconv.Atoi(v.RDM_id)
			if err != nil {
				if err_context2 == "" {
					err_context2 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
				} else {
					err_context2 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
				}
			} else {
				if n > 9999999 {
					if err_context2 == "" {
						err_context2 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
					} else {
						err_context2 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
					}
				}
			}
		}

		sqlstr = fmt.Sprintf("select [p_name] from [sap] where p_id='%s'", v.Product_id)
		fmt.Println(sqlstr)

		rdRow, err := sqlConn.Query(sqlstr)
		if err != nil {
			logs.Error(fmt.Sprintf("importKpi Query err:%v", err.Error()))
			goto exit
		}

		var p_name string
		for rdRow.Next() {
			if err := rdRow.Scan(&p_name); err == nil {
			} else {
				logs.Error("importKpi scan Error", err.Error())
			}
		}
		rdRow.Close()

		if p_name == "" {
			if err_context3 == "" {
				err_context3 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
			} else {
				err_context3 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
			}
		} else {
			req.Data[i].Product_name = p_name
		}

		demand_t := req.Data[i].Demand_date
		demand_t = strings.ReplaceAll(demand_t, "-", "/")
		t := strings.Split(demand_t, "/")
		if len(t) == 3 {
			month, _ := strconv.Atoi(t[1])
			day, _ := strconv.Atoi(t[2])
			demand_time := fmt.Sprintf(`%s-%02d-%02d 00:00:00`, t[0], month, day)
			fmt.Println(demand_time)

			timeLayout := "2006-01-02 15:04:05"
			loc, _ := time.LoadLocation("Local")

			bt, _ := time.ParseInLocation(timeLayout, demand_time, loc)
			if int(bt.Sub(time.Now()).Hours()) < 72 {
				if err_context4 == "" {
					err_context4 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
				} else {
					err_context4 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
				}
			}
		}

		sqlstr = fmt.Sprintf("select [flag] from [sap] where p_id='%s'", v.Product_id)

		flagRow, err := sqlConn.Query(sqlstr)
		if err != nil {
			logs.Error(fmt.Sprintf("importKpi Query err:%v", err.Error()))
			goto exit
		}

		var flag string
		for flagRow.Next() {
			if err := flagRow.Scan(&flag); err == nil {
			} else {
				logs.Error("importKpi scan Error", err.Error())
			}
		}
		flagRow.Close()

		if flag == "0" {
			if err_context3 == "" {
				err_context5 += fmt.Sprintf(`产品编号 %s 未确认，请联系生产部经理确认。`, v.Product_id)
			} else {
				err_context5 += fmt.Sprintf(`;产品编号 %s 未确认，请联系生产部经理确认。`, v.Product_id)

			}
		}
	}

	if err_context1 != "" {
		err_context1 += " 数量含非数字或大于9999，请仔细核对！"
	}
	if err_context2 != "" {
		err_context2 += " RDM任务号只允许1-9999999，请仔细核对！"
	}

	// if err_context3 != "" {
	// 	err_context3 += " 不存在，请联系生产管理员添加！"
	// }

	if err_context1 != "" || err_context2 != "" || err_context3 != "" || err_context5 != "" {
		resp.Err_text = err_context3 + err_context2 + err_context1 + err_context5
		resp.Ret = 1
		goto exit
	}

	for i := 0; i < len(req.Data); i++ {
		req.Data[i].RDM_id = strings.ReplaceAll(req.Data[i].RDM_id, "#", "")

		demand_t := req.Data[i].Demand_date
		demand_t = strings.ReplaceAll(demand_t, "-", "/")
		t := strings.Split(demand_t, "/")
		if len(t) == 3 {
			month, _ := strconv.Atoi(t[1])
			day, _ := strconv.Atoi(t[2])
			req.Data[i].Demand_date = fmt.Sprintf(`%s/%02d/%02d`, t[0], month, day)
		}

		var maxid int
		var rows *sql.Rows

		var start_department_id int
		var stay_department_id int
		var scan_flag int
		//mark stay did
		text := req.Data[i].Plan_state
		if text == "" {
			start_department_id = usrinfo.DepartmentId
			stay_department_id = start_department_id
			scan_flag = 1 << (usrinfo.DepartmentId - 1)

			task_transfer_update_time(0, usrinfo.DepartmentId, &req.Data[i])
		} else {
			start_department_id = usrinfo.DepartmentId
			task_transfer_update_time(0, usrinfo.DepartmentId, &req.Data[i])

			if strings.Contains(text, "核对物料") {
				stay_department_id = 3
			} else {
				stay_department_id = start_department_id
			}
			task_transfer_update_time(start_department_id, stay_department_id, &req.Data[i])

			scan_flag = (1 << (start_department_id - 1)) | (1 << (stay_department_id - 1))
		}

		req.Data[i].Department_name = usrinfo.Department
		req.Data[i].Plan_state = ""
		if req.Data[i].Plan_state == "" {
			req.Data[i].Plan_state = "待分解"
		}
		data, _ = json.Marshal(req.Data[i])
		month = time.Now().Year()*100 + int(time.Now().Month())

		// 对包含单引号的字符串进行转义
		escapeSingleQuote := func(s string) string {
			return strings.Replace(s, "'", "''", -1)
		}

		sqlstr = fmt.Sprintf(`INSERT INTO [plan]
             ([time]
             ,[month]
             ,[data]
             ,[start_department_id]
             ,[stay_department_id]
             ,[scan_flag]
             ,[del_flag]
            ,[p_id]
            ,[p_name]
            ,[group_leader]
    ,[p_state]
            ,[group_name]
    ,[task_id]
    ,[conveyer]
    ,[rmd_id])
               VALUES ('%s',%d,'%s',%d,%d,%d,%d,'%s','%s','%s','%s','%s','%s','%s','%s')`,
			time.Now().Format("2006-01-02 15:04:05"), month,
			escapeSingleQuote(string(data)), // 转义JSON中的单引号
			start_department_id, stay_department_id,
			scan_flag, 0,
			escapeSingleQuote(req.Data[i].Product_id),
			escapeSingleQuote(req.Data[i].Product_name),
			"",
			req.Data[i].Plan_state,
			escapeSingleQuote(req.Data[i].Group_name),
			escapeSingleQuote(req.Data[i].Task_id),
			escapeSingleQuote(req.Data[i].Conveyer),
			escapeSingleQuote(req.Data[i].RDM_id))

		mu.Lock()
		_, err = sqlConn.Exec(sqlstr)
		fmt.Println("sqlstr-------------------", sqlstr)
		if err != nil {
			mu.Unlock()
			logs.Info("importKpi Exec Error:", err.Error())
			fmt.Println("sqlstr-------------------", err.Error())
			resp.Ret = -1
			goto exit
		}

		//将前置表更新为提交状态
		sqlstr = fmt.Sprintf(`UPDATE [pre_plan] SET [commit_flag] = 1 WHERE [id] = %v`, req.Data[i].ID)
		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			mu.Unlock()
			logs.Info("前置表更新失败:", err.Error())
			fmt.Println("前置表更新失败-------------------", err.Error())
			resp.Ret = -1
			goto exit
		}
		//获取id
		sqlstr = fmt.Sprintf(`SELECT top 1 [ID] FROM [plan] order by ID desc`)
		rows, err = sqlConn.Query(sqlstr)
		if err == nil {

			for rows.Next() {
				if err = rows.Scan(&maxid); err != nil {
					logs.Info("addKpi scan Error:", err.Error())
				}
			}

			rows.Close()
		}
		mu.Unlock()

		if maxid > 0 {

			now_time := time.Now().Format("2006-01-02 15:04:05")
			update_context := fmt.Sprintf(`任务导入`)
			sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, maxid, now_time, req.OpUser, update_context)
			_, err = sqlConn.Exec(sqlstr)
			if err != nil {
				logs.Info("importKpi Exec Error:", err.Error())
				goto exit
			}

			if stay_department_id != start_department_id {
				stay_did_name := get_department_name_from_did(stay_department_id)
				update_context = fmt.Sprintf(`任务从%s转到%s`, usrinfo.Department, stay_did_name)
				sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, maxid, now_time, req.OpUser, update_context)
				_, err = sqlConn.Exec(sqlstr)
				if err != nil {
					logs.Info("importKpi Exec Error:", err.Error())
					goto exit
				}
			}
		}
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("importKpi recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func importPreKpi(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("importKpi recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var data []byte
	var month int

	var err error
	var sqlstr string
	var resp import_kpi_resp

	var usrinfo useInfo
	var err_context1 string
	var err_context2 string
	var err_context3 string
	var err_context4 string
	// var err_context5 string

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req importKpiReq
	json.Unmarshal(reqdata, &req)
	fmt.Println("Data------", req.Data)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	usrinfo, err = getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("importKpi getUserInfo err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Data); i++ {
		v := req.Data[i]

		if v.Total_num != "" {
			n, err := strconv.Atoi(v.Total_num)
			if err != nil {
				if err_context1 == "" {
					err_context1 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
				} else {
					err_context1 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
				}
			} else {
				if n > 9999 {
					if err_context1 == "" {
						err_context1 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
					} else {
						err_context1 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
					}
				}
			}
		}

		if v.RDM_id != "" {
			v.RDM_id = strings.ReplaceAll(v.RDM_id, "#", "")
			n, err := strconv.Atoi(v.RDM_id)
			if err != nil {
				if err_context2 == "" {
					err_context2 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
				} else {
					err_context2 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
				}
			} else {
				if n > 9999999 {
					if err_context2 == "" {
						err_context2 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
					} else {
						err_context2 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
					}
				}
			}
		}

		sqlstr = fmt.Sprintf("select [p_name] from [sap] where p_id='%s'", v.Product_id)
		fmt.Println(sqlstr)
		logs.Error("导入产品编号-------------", sqlstr)
		rdRow, err := sqlConn.Query(sqlstr)
		if err != nil {
			logs.Error(fmt.Sprintf("importKpi Query err:%v", err.Error()))
			goto exit
		}

		var p_name string
		for rdRow.Next() {
			if err := rdRow.Scan(&p_name); err == nil {
			} else {
				logs.Error("importKpi scan Error", err.Error())
			}
		}
		logs.Error("导入产品名称-------------", p_name)
		rdRow.Close()

		if p_name == "" {
			if err_context3 == "" {
				err_context3 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
			} else {
				err_context3 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
			}
		} else {
			req.Data[i].Product_name = p_name
		}

		demand_t := req.Data[i].Promise_date
		demand_t = strings.ReplaceAll(demand_t, "-", "/")
		t := strings.Split(demand_t, "/")
		if len(t) == 3 {
			month, _ := strconv.Atoi(t[1])
			day, _ := strconv.Atoi(t[2])
			demand_time := fmt.Sprintf(`%s-%02d-%02d 00:00:00`, t[0], month, day)
			fmt.Println(demand_time)

			timeLayout := "2006-01-02 15:04:05"
			loc, _ := time.LoadLocation("Local")

			bt, _ := time.ParseInLocation(timeLayout, demand_time, loc)
			fmt.Println("importPreKpibt:", bt)
			fmt.Println("importPreKpihour:", bt.Sub(time.Now()).Hours())
		}
		if req.Data[i].Promise_date != "" {
			promise_date := req.Data[i].Promise_date
			promise_date = strings.ReplaceAll(promise_date, "-", "/")
			s := strings.Split(promise_date, "/")
			if len(s) == 3 {
				month, _ := strconv.Atoi(s[1])
				day, _ := strconv.Atoi(s[2])
				promise_date := fmt.Sprintf(`%s-%02d-%02d 00:00:00`, s[0], month, day)
				fmt.Println(promise_date)

				timeLayout := "2006-01-02 15:04:05"
				loc, _ := time.LoadLocation("Local")

				bt, _ := time.ParseInLocation(timeLayout, promise_date, loc)
				fmt.Println("hour:", bt.Sub(time.Now()).Hours())
				if int(bt.Sub(time.Now()).Hours()) < 72 {
					if err_context4 == "" {
						err_context4 += fmt.Sprintf(`生产确认日期必须大于当前日期三天及以上！`)
					} else {
						err_context4 += fmt.Sprintf(`生产确认日期必须大于当前日期三天及以上！`)
					}
				}
			}
		}

	}

	if err_context1 != "" {
		err_context1 += " 数量含非数字或大于9999，请仔细核对！"
	}
	if err_context2 != "" {
		err_context2 += " RDM任务号只允许1-9999999，请仔细核对！"
	}

	if err_context1 != "" || err_context2 != "" || err_context4 != "" {
		resp.Err_text = err_context2 + err_context1 + err_context4
		resp.Ret = 1
		goto exit
	}
	for i := 0; i < len(req.Data); i++ {
		req.Data[i].RDM_id = strings.ReplaceAll(req.Data[i].RDM_id, "#", "")

		demand_t := req.Data[i].Demand_date
		demand_t = strings.ReplaceAll(demand_t, "-", "/")
		t := strings.Split(demand_t, "/")
		if len(t) == 3 {
			month, _ := strconv.Atoi(t[1])
			day, _ := strconv.Atoi(t[2])
			req.Data[i].Demand_date = fmt.Sprintf(`%s/%02d/%02d`, t[0], month, day)
		}

		var maxid int
		var rows *sql.Rows

		var start_department_id int
		var stay_department_id int
		var scan_flag int
		//mark stay did
		text := req.Data[i].Plan_state
		if text == "" {
			start_department_id = usrinfo.DepartmentId
			stay_department_id = start_department_id
			scan_flag = 1 << (usrinfo.DepartmentId - 1)

			task_transfer_update_time(0, usrinfo.DepartmentId, &req.Data[i])
		} else {
			start_department_id = usrinfo.DepartmentId
			task_transfer_update_time(0, usrinfo.DepartmentId, &req.Data[i])

			if strings.Contains(text, "核对物料") {
				stay_department_id = 3
			} else {
				stay_department_id = start_department_id
			}
			task_transfer_update_time(start_department_id, stay_department_id, &req.Data[i])

			scan_flag = (1 << (start_department_id - 1)) | (1 << (stay_department_id - 1))
		}

		req.Data[i].Department_name = usrinfo.Department
		req.Data[i].Plan_state = ""
		if req.Data[i].Plan_state == "" {
			req.Data[i].Plan_state = "待生产部回复加工周期"
		}

		data, _ = json.Marshal(req.Data[i])
		month = time.Now().Year()*100 + int(time.Now().Month())

		// 对包含单引号的字符串进行转义
		escapeSingleQuote := func(s string) string {
			return strings.Replace(s, "'", "''", -1)
		}

		//插入数据之前，如果不存在产品数据，则插入sap基础数据表中
		countSql := fmt.Sprintf(`SELECT COUNT(*) from sap where p_id='%s'`, req.Data[i].Product_id)
		fmt.Println(countSql)

		var count int
		err := sqlConn.QueryRow(countSql).Scan(&count)
		if err != nil {
			return
		}
		if count == 0 {
			sqlstr = fmt.Sprintf(`INSERT INTO [sap] ([p_id],[p_name] , [flag]) VALUES ('%s','%s','0')`,
				req.Data[i].Product_id, req.Data[i].Product_name)
			_, err = sqlConn.Exec(sqlstr)
			if err != nil {
				mu.Unlock()
				resp.Ret = -1
				goto exit
			}
		}

		sqlstr = fmt.Sprintf(`INSERT INTO [pre_plan]
         ([time]
         ,[month]
         ,[data]
         ,[scan_flag]
         ,[del_flag]
        ,[p_id]
        ,[p_name]
        ,[group_leader]
        ,[p_state]
        ,[group_name]
        ,[conveyer]
        ,[rmd_id]
        ,[is_frist_process]  
        ,[is_img]           
        ,[is_materials]     
        ,[is_new_gauge]     
        ,[start_dept]
        ,[remarks]
        ,[task_id]
        ,[demand_date]
        ,[total_num]
        ,[commit_flag]
        ,[promise_date]
        ,[file_check])      
           VALUES ('%s', %d, '%s', %d,  %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s')`,
			time.Now().Format("2006-01-02 15:04:05"),
			month,
			escapeSingleQuote(string(data)),
			scan_flag,
			0,
			escapeSingleQuote(req.Data[i].Product_id),
			escapeSingleQuote(req.Data[i].Product_name),
			"",
			escapeSingleQuote(req.Data[i].Plan_state),
			escapeSingleQuote(req.Data[i].Group_name),
			escapeSingleQuote(req.Data[i].Conveyer),
			escapeSingleQuote(req.Data[i].RDM_id),
			escapeSingleQuote(req.Data[i].First_procesds),
			escapeSingleQuote(req.Data[i].Is_img),
			escapeSingleQuote(req.Data[i].Is_materials),
			escapeSingleQuote(req.Data[i].Is_new_gauge),
			escapeSingleQuote(usrinfo.Department),
			escapeSingleQuote(req.Data[i].Remarks),
			escapeSingleQuote(req.Data[i].Task_id),
			req.Data[i].Demand_date,
			req.Data[i].Total_num,
			"0",
			req.Data[i].Promise_date,
			req.Data[i].FileCheck)

		mu.Lock()
		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			mu.Unlock()
			logs.Info("importKpi Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}

		//获取id
		sqlstr = fmt.Sprintf(`SELECT top 1 [ID] FROM [plan] order by ID desc`)
		rows, err = sqlConn.Query(sqlstr)
		if err == nil {

			for rows.Next() {
				if err = rows.Scan(&maxid); err != nil {
					logs.Info("addKpi scan Error:", err.Error())
				}
			}

			rows.Close()
		}
		mu.Unlock()

		if maxid > 0 {

			now_time := time.Now().Format("2006-01-02 15:04:05")
			update_context := fmt.Sprintf(`任务导入`)
			sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, maxid, now_time, req.OpUser, update_context)
			_, err = sqlConn.Exec(sqlstr)
			if err != nil {
				logs.Info("importKpi Exec Error:", err.Error())
				goto exit
			}

			if stay_department_id != start_department_id {
				stay_did_name := get_department_name_from_did(stay_department_id)
				update_context = fmt.Sprintf(`任务从%s转到%s`, usrinfo.Department, stay_did_name)
				sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, maxid, now_time, req.OpUser, update_context)
				_, err = sqlConn.Exec(sqlstr)
				if err != nil {
					logs.Info("importKpi Exec Error:", err.Error())
					goto exit
				}
			}
		}
	}

	// ========== 新增：根据用户账号更新或插入 history_pre_plan，仅保留最后一条数据 ==========
	fmt.Println("len(req.Data)--", len(req.Data))
	if len(req.Data) > 0 {
		// 循环结束后，data、month、scan_flag 已经是最后一条数据的值
		last := req.Data[len(req.Data)-1]

		// 转义函数（前面已定义，这里可直接使用）
		escapeSingleQuote := func(s string) string {
			return strings.Replace(s, "'", "''", -1)
		}
		safeOpUser := escapeSingleQuote(req.OpUser)

		// 检查是否已有该用户的记录
		var cnt int
		countSql := fmt.Sprintf("SELECT COUNT(*) FROM [history_pre_plan] WHERE [user_name]='%s'", safeOpUser)
		err = sqlConn.QueryRow(countSql).Scan(&cnt)
		if err != nil {
			logs.Info("history_pre_plan query count Error:", err.Error())
			resp.Ret = -1
			goto exit
		}
		fmt.Println("cnt----", cnt)

		if cnt > 0 {
			// 更新
			updateSql := fmt.Sprintf(`UPDATE [history_pre_plan] SET 
                [time]='%s',
                [month]=%d,
                [data]='%s',
                [scan_flag]=%d,
                [del_flag]=0,
                [p_id]='%s',
                [p_name]='%s',
                [group_leader]='',
                [p_state]='%s',
                [group_name]='%s',
                [conveyer]='%s',
                [rmd_id]='%s',
                [is_frist_process]='%s',
                [is_img]='%s',
                [is_materials]='%s',
                [is_new_gauge]='%s',
                [start_dept]='%s',
                [remarks]='%s',
                [task_id]='%s',
                [demand_date]='%s',
                [total_num]='%s',
                [commit_flag]='0',
                [promise_date]='%s',
                [file_check]='%s'
                WHERE [user_name]='%s'`,
				time.Now().Format("2006-01-02 15:04:05"),
				month,
				escapeSingleQuote(string(data)),
				1,
				escapeSingleQuote(last.Product_id),
				escapeSingleQuote(last.Product_name),
				escapeSingleQuote(last.Plan_state),
				escapeSingleQuote(last.Group_name),
				escapeSingleQuote(last.Conveyer),
				escapeSingleQuote(last.RDM_id),
				escapeSingleQuote(last.First_procesds),
				escapeSingleQuote(last.Is_img),
				escapeSingleQuote(last.Is_materials),
				escapeSingleQuote(last.Is_new_gauge),
				escapeSingleQuote(usrinfo.Department),
				escapeSingleQuote(last.Remarks),
				escapeSingleQuote(last.Task_id),
				last.Demand_date,
				last.Total_num,
				last.Promise_date,
				last.FileCheck,
				safeOpUser)
			fmt.Println("updateSql----", updateSql)

			_, err = sqlConn.Exec(updateSql)
			if err != nil {
				fmt.Println("history_pre_plan update Error:", err.Error())
				resp.Ret = -1
				goto exit
			}
		} else {
			// 新增
			insertSql := fmt.Sprintf(`INSERT INTO [history_pre_plan] 
                ([time],[month],[data],[scan_flag],[del_flag],
                [p_id],[p_name],[group_leader],[p_state],[group_name],
                [conveyer],[rmd_id],[is_frist_process],[is_img],[is_materials],
                [is_new_gauge],[start_dept],[remarks],[task_id],[demand_date],
                [total_num],[commit_flag],[promise_date],[file_check],[user_name])
                VALUES ('%s',%d,'%s',%d,0,
                '%s','%s','','%s','%s',
                '%s','%s','%s','%s','%s',
                '%s','%s','%s','%s','%s',
                '%s','0','%s','%s','%s')`,
				time.Now().Format("2006-01-02 15:04:05"),
				month,
				escapeSingleQuote(string(data)),
				1,
				escapeSingleQuote(last.Product_id),
				escapeSingleQuote(last.Product_name),
				escapeSingleQuote(last.Plan_state),
				escapeSingleQuote(last.Group_name),
				escapeSingleQuote(last.Conveyer),
				escapeSingleQuote(last.RDM_id),
				escapeSingleQuote(last.First_procesds),
				escapeSingleQuote(last.Is_img),
				escapeSingleQuote(last.Is_materials),
				escapeSingleQuote(last.Is_new_gauge),
				escapeSingleQuote(usrinfo.Department),
				escapeSingleQuote(last.Remarks),
				escapeSingleQuote(last.Task_id),
				last.Demand_date,
				last.Total_num,
				last.Promise_date,
				last.FileCheck,
				safeOpUser)
			fmt.Println("updateSql----", insertSql)

			_, err = sqlConn.Exec(insertSql)
			if err != nil {
				fmt.Println("history_pre_plan insert Error:", err.Error())
				resp.Ret = -1
				goto exit
			}
		}
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("importKpi recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

// func importPreKpi(response http.ResponseWriter, request *http.Request) {
// 	beginTime := time.Now().UnixNano()
// 	fmt.Println("importKpi recv req begin", time.Now().Format("2006-01-02 15:04:05"))

// 	var data []byte
// 	var month int

// 	var err error
// 	var sqlstr string
// 	var resp import_kpi_resp

// 	var usrinfo useInfo
// 	var err_context1 string
// 	var err_context2 string
// 	var err_context3 string
// 	var err_context4 string
// 	// var err_context5 string

// 	reqdata, _ := ioutil.ReadAll(request.Body)
// 	var req importKpiReq
// 	json.Unmarshal(reqdata, &req)
// 	fmt.Println("Data------", req.Data)

// 	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
// 	if !b {
// 		logs.Info(fmt.Sprintf("用户%s不在线"))
// 		resp.Ret = -1
// 		goto exit
// 	}

// 	usrinfo, err = getUserInfo(req.OpUser)
// 	if err != nil {
// 		logs.Info(fmt.Sprintf("importKpi getUserInfo err:%s", err.Error()))
// 		resp.Ret = -1
// 		goto exit
// 	}

// 	for i := 0; i < len(req.Data); i++ {
// 		v := req.Data[i]

// 		if v.Total_num != "" {
// 			n, err := strconv.Atoi(v.Total_num)
// 			if err != nil {
// 				if err_context1 == "" {
// 					err_context1 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
// 				} else {
// 					err_context1 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
// 				}
// 			} else {
// 				if n > 9999 {
// 					if err_context1 == "" {
// 						err_context1 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
// 					} else {
// 						err_context1 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
// 					}
// 				}
// 			}
// 		}

// 		if v.RDM_id != "" {
// 			v.RDM_id = strings.ReplaceAll(v.RDM_id, "#", "")
// 			n, err := strconv.Atoi(v.RDM_id)
// 			if err != nil {
// 				if err_context2 == "" {
// 					err_context2 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
// 				} else {
// 					err_context2 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
// 				}
// 			} else {
// 				if n > 9999999 {
// 					if err_context2 == "" {
// 						err_context2 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
// 					} else {
// 						err_context2 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
// 					}
// 				}
// 			}
// 		}

// 		sqlstr = fmt.Sprintf("select [p_name] from [sap] where p_id='%s'", v.Product_id)
// 		fmt.Println(sqlstr)
// 		logs.Error("导入产品编号-------------", sqlstr)
// 		rdRow, err := sqlConn.Query(sqlstr)
// 		if err != nil {
// 			logs.Error(fmt.Sprintf("importKpi Query err:%v", err.Error()))
// 			goto exit
// 		}

// 		var p_name string
// 		for rdRow.Next() {
// 			if err := rdRow.Scan(&p_name); err == nil {
// 			} else {
// 				logs.Error("importKpi scan Error", err.Error())
// 			}
// 		}
// 		logs.Error("导入产品名称-------------", p_name)
// 		rdRow.Close()

// 		if p_name == "" {
// 			if err_context3 == "" {
// 				err_context3 += fmt.Sprintf(`产品编号:%s`, v.Product_id)
// 			} else {
// 				err_context3 += fmt.Sprintf(`;产品编号:%s`, v.Product_id)
// 			}
// 		} else {
// 			req.Data[i].Product_name = p_name
// 		}

// 		demand_t := req.Data[i].Promise_date
// 		demand_t = strings.ReplaceAll(demand_t, "-", "/")
// 		t := strings.Split(demand_t, "/")
// 		if len(t) == 3 {
// 			month, _ := strconv.Atoi(t[1])
// 			day, _ := strconv.Atoi(t[2])
// 			demand_time := fmt.Sprintf(`%s-%02d-%02d 00:00:00`, t[0], month, day)
// 			fmt.Println(demand_time)

// 			timeLayout := "2006-01-02 15:04:05"
// 			loc, _ := time.LoadLocation("Local")

// 			bt, _ := time.ParseInLocation(timeLayout, demand_time, loc)
// 			fmt.Println("importPreKpibt:", bt)
// 			fmt.Println("importPreKpihour:", bt.Sub(time.Now()).Hours())
// 		}
// 		if req.Data[i].Promise_date != "" {
// 			promise_date := req.Data[i].Promise_date
// 			promise_date = strings.ReplaceAll(promise_date, "-", "/")
// 			s := strings.Split(promise_date, "/")
// 			if len(s) == 3 {
// 				month, _ := strconv.Atoi(s[1])
// 				day, _ := strconv.Atoi(s[2])
// 				promise_date := fmt.Sprintf(`%s-%02d-%02d 00:00:00`, s[0], month, day)
// 				fmt.Println(promise_date)

// 				timeLayout := "2006-01-02 15:04:05"
// 				loc, _ := time.LoadLocation("Local")

// 				bt, _ := time.ParseInLocation(timeLayout, promise_date, loc)
// 				fmt.Println("hour:", bt.Sub(time.Now()).Hours())
// 				if int(bt.Sub(time.Now()).Hours()) < 72 {
// 					if err_context4 == "" {
// 						err_context4 += fmt.Sprintf(`生产确认日期必须大于当前日期三天及以上！`)
// 					} else {
// 						err_context4 += fmt.Sprintf(`生产确认日期必须大于当前日期三天及以上！`)
// 					}
// 				}
// 			}
// 		}

// 	}

// 	if err_context1 != "" {
// 		err_context1 += " 数量含非数字或大于9999，请仔细核对！"
// 	}
// 	if err_context2 != "" {
// 		err_context2 += " RDM任务号只允许1-9999999，请仔细核对！"
// 	}

// 	if err_context1 != "" || err_context2 != "" || err_context4 != "" {
// 		resp.Err_text = err_context2 + err_context1 + err_context4
// 		resp.Ret = 1
// 		goto exit
// 	}
// 	for i := 0; i < len(req.Data); i++ {
// 		req.Data[i].RDM_id = strings.ReplaceAll(req.Data[i].RDM_id, "#", "")

// 		demand_t := req.Data[i].Demand_date
// 		demand_t = strings.ReplaceAll(demand_t, "-", "/")
// 		t := strings.Split(demand_t, "/")
// 		if len(t) == 3 {
// 			month, _ := strconv.Atoi(t[1])
// 			day, _ := strconv.Atoi(t[2])
// 			req.Data[i].Demand_date = fmt.Sprintf(`%s/%02d/%02d`, t[0], month, day)
// 		}

// 		var maxid int
// 		var rows *sql.Rows

// 		var start_department_id int
// 		var stay_department_id int
// 		var scan_flag int
// 		//mark stay did
// 		text := req.Data[i].Plan_state
// 		if text == "" {
// 			start_department_id = usrinfo.DepartmentId
// 			stay_department_id = start_department_id
// 			scan_flag = 1 << (usrinfo.DepartmentId - 1)

// 			task_transfer_update_time(0, usrinfo.DepartmentId, &req.Data[i])
// 		} else {
// 			start_department_id = usrinfo.DepartmentId
// 			task_transfer_update_time(0, usrinfo.DepartmentId, &req.Data[i])

// 			if strings.Contains(text, "核对物料") {
// 				stay_department_id = 3
// 			} else {
// 				stay_department_id = start_department_id
// 			}
// 			task_transfer_update_time(start_department_id, stay_department_id, &req.Data[i])

// 			scan_flag = (1 << (start_department_id - 1)) | (1 << (stay_department_id - 1))
// 		}

// 		req.Data[i].Department_name = usrinfo.Department
// 		req.Data[i].Plan_state = ""
// 		if req.Data[i].Plan_state == "" {
// 			req.Data[i].Plan_state = "待生产部回复加工周期"
// 		}
// 		data, _ = json.Marshal(req.Data[i])
// 		month = time.Now().Year()*100 + int(time.Now().Month())

// 		// 对包含单引号的字符串进行转义
// 		escapeSingleQuote := func(s string) string {
// 			return strings.Replace(s, "'", "''", -1)
// 		}

// 		//插入数据之前，如果不存在产品数据，则插入sap基础数据表中
// 		countSql := fmt.Sprintf(`SELECT COUNT(*) from sap where p_id='%s'`, req.Data[i].Product_id)
// 		fmt.Println(countSql)

// 		var count int
// 		err := sqlConn.QueryRow(countSql).Scan(&count)
// 		if err != nil {
// 			return
// 		}
// 		if count == 0 {
// 			sqlstr = fmt.Sprintf(`INSERT INTO [sap] ([p_id],[p_name] , [flag]) VALUES ('%s','%s','0')`,
// 				req.Data[i].Product_id, req.Data[i].Product_name)
// 			_, err = sqlConn.Exec(sqlstr)
// 			if err != nil {
// 				mu.Unlock()
// 				resp.Ret = -1
// 				goto exit
// 			}
// 		}

// 		sqlstr = fmt.Sprintf(`INSERT INTO [pre_plan]
//          ([time]
//          ,[month]
//          ,[data]
//          ,[scan_flag]
//          ,[del_flag]
//         ,[p_id]
//         ,[p_name]
//         ,[group_leader]
//         ,[p_state]
//         ,[group_name]
//         ,[conveyer]
//         ,[rmd_id]
//         ,[is_frist_process]
//         ,[is_img]
//         ,[is_materials]
//         ,[is_new_gauge]
//         ,[start_dept]
// 		,[remarks]
// 		,[task_id]
// 		,[demand_date]
// 		,[total_num]
// 		,[commit_flag]
// 		,[promise_date]
// 		,[file_check])
//            VALUES ('%s', %d, '%s', %d,  %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s')`,
// 			time.Now().Format("2006-01-02 15:04:05"),
// 			month,
// 			escapeSingleQuote(string(data)),
// 			scan_flag,
// 			0,
// 			escapeSingleQuote(req.Data[i].Product_id),
// 			escapeSingleQuote(req.Data[i].Product_name),
// 			"",
// 			escapeSingleQuote(req.Data[i].Plan_state),
// 			escapeSingleQuote(req.Data[i].Group_name),
// 			escapeSingleQuote(req.Data[i].Conveyer),
// 			escapeSingleQuote(req.Data[i].RDM_id),
// 			escapeSingleQuote(req.Data[i].First_procesds),
// 			escapeSingleQuote(req.Data[i].Is_img),
// 			escapeSingleQuote(req.Data[i].Is_materials),
// 			escapeSingleQuote(req.Data[i].Is_new_gauge),
// 			escapeSingleQuote(usrinfo.Department),
// 			escapeSingleQuote(req.Data[i].Remarks),
// 			escapeSingleQuote(req.Data[i].Task_id),
// 			req.Data[i].Demand_date,
// 			req.Data[i].Total_num,
// 			"0",
// 			req.Data[i].Promise_date,
// 			req.Data[i].FileCheck)

// 		mu.Lock()
// 		_, err = sqlConn.Exec(sqlstr)
// 		if err != nil {
// 			mu.Unlock()
// 			logs.Info("importKpi Exec Error:", err.Error())
// 			resp.Ret = -1
// 			goto exit
// 		}

// 		//插入计划成功之后，根据账号作为唯一标识符，记录这次填写的信息。

// 		//获取id
// 		sqlstr = fmt.Sprintf(`SELECT top 1 [ID] FROM [plan] order by ID desc`)
// 		rows, err = sqlConn.Query(sqlstr)
// 		if err == nil {

// 			for rows.Next() {
// 				if err = rows.Scan(&maxid); err != nil {
// 					logs.Info("addKpi scan Error:", err.Error())
// 				}
// 			}

// 			rows.Close()
// 		}
// 		mu.Unlock()

// 		if maxid > 0 {

// 			now_time := time.Now().Format("2006-01-02 15:04:05")
// 			update_context := fmt.Sprintf(`任务导入`)
// 			sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, maxid, now_time, req.OpUser, update_context)
// 			_, err = sqlConn.Exec(sqlstr)
// 			if err != nil {
// 				logs.Info("importKpi Exec Error:", err.Error())
// 				goto exit
// 			}

// 			if stay_department_id != start_department_id {
// 				stay_did_name := get_department_name_from_did(stay_department_id)
// 				update_context = fmt.Sprintf(`任务从%s转到%s`, usrinfo.Department, stay_did_name)
// 				sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, maxid, now_time, req.OpUser, update_context)
// 				_, err = sqlConn.Exec(sqlstr)
// 				if err != nil {
// 					logs.Info("importKpi Exec Error:", err.Error())
// 					goto exit
// 				}
// 			}
// 		}
// 	}

// 	resp.Ret = 0

// exit:

// 	jdata, _ := json.Marshal(resp)
// 	fmt.Fprintf(response, string(jdata))

// 	endTime := time.Now().UnixNano()
// 	fmt.Println(fmt.Sprintf("importKpi recv req end, use time: %v ms", (endTime-beginTime)/1e6))

// }

func get_time(search_time string) (whereSql string) {
	t := strings.Split(search_time, "-")
	if len(t) == 2 {
		var if_where bool
		t0 := strings.Split(t[0], "/")
		if len(t0) == 2 {
			year, _ := strconv.Atoi(t0[0])
			month, _ := strconv.Atoi(t0[1])
			t := (year+2000)*100 + month
			whereSql += fmt.Sprintf(` [month] >= %d `, t)
			if_where = true
		} else if len(t0) == 3 {
			year, _ := strconv.Atoi(t0[0])
			month, _ := strconv.Atoi(t0[1])
			day, _ := strconv.Atoi(t0[2])

			t := fmt.Sprintf(`20%02d-%02d-%02d 00:00:00`, year, month, day)
			whereSql += fmt.Sprintf(` [time]>='%s' `, t)
			if_where = true
		}

		t1 := strings.Split(t[1], "/")
		if len(t1) == 2 {
			year, _ := strconv.Atoi(t1[0])
			month, _ := strconv.Atoi(t1[1])
			t := (year+2000)*100 + month
			if if_where {
				whereSql += fmt.Sprintf(` and [month] <= %d `, t)
			} else {
				whereSql += fmt.Sprintf(` [month] <= %d `, t)
			}
		} else if len(t1) == 3 {
			year, _ := strconv.Atoi(t1[0])
			month, _ := strconv.Atoi(t1[1])
			day, _ := strconv.Atoi(t1[2])

			t := fmt.Sprintf(`20%02d-%02d-%02d 23:59:59`, year, month, day)

			if if_where {
				whereSql += fmt.Sprintf(` and [time]<='%s' `, t)
			} else {
				whereSql += fmt.Sprintf(` [time]<='%s' `, t)
			}

			if_where = true
		}

	} else if len(t) == 1 {
		tt := strings.Split(t[0], "/")
		if len(tt) == 2 {
			year, _ := strconv.Atoi(tt[0])
			month, _ := strconv.Atoi(tt[1])
			search_month := (year+2000)*100 + month
			whereSql = fmt.Sprintf(` [month] = %d`, search_month)
		} else if len(tt) == 3 {
			year, _ := strconv.Atoi(tt[0])
			month, _ := strconv.Atoi(tt[1])
			day, _ := strconv.Atoi(tt[2])

			bt := fmt.Sprintf(`20%02d-%02d-%02d 00:00:00`, year, month, day)
			et := fmt.Sprintf(`20%02d-%02d-%02d 23:59:59`, year, month, day)
			whereSql = fmt.Sprintf(` [time]>='%s' and [time] <='%s' `, bt, et)
		}
	}

	return
}

func getKpi(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("getKpi recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var scan_flag int

	var req getKpiReq
	var resp getKpiResp

	var ifwhere bool
	var whereSql string

	var sqlstr string
	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error
	var usrinfo useInfo

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	logs.Info(string(reqdata))
	logs.Info(req)

	query_cnt := req.Index * req.Count
	logs.Info("query_cnt:", query_cnt)
	var cnt int

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		goto exit
	}

	usrinfo, err = getUserInfo(req.OpUser)

	if err != nil {
		logs.Info(fmt.Sprintf("getKpi getUserInfo err:%s", err.Error()))
		goto exit
	}

	if req.SapId != "" { //编码
		likeStr := "%" + req.SapId + "%"
		whereSql += fmt.Sprintf(` [task_id] like '%s'`, likeStr)
		ifwhere = true
	}

	//序号
	if req.Id != "" {
		likeStr := "%" + req.Id + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [ID] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [ID] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	//产品编号
	if req.Pid != "" {
		likeStr := "%" + req.Pid + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [p_id] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [p_id] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	//产品名称
	if req.Pname != "" {
		likeStr := "%" + req.Pname + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [p_name] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [p_name] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	//交付人
	if req.Conveyer != "" {
		likeStr := "%" + req.Conveyer + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [conveyer] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [conveyer] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	//交付人
	if req.Rdm_id != "" {
		likeStr := "%" + req.Rdm_id + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [rmd_id] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [rmd_id] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	if req.Product_user != "" {
		likeStr := "%" + req.Product_user + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [p_user] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [p_user] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	if req.Bt != "" {
		s := get_time(req.Bt)
		if s != "" {
			if ifwhere {
				whereSql += fmt.Sprintf(` and %s`, s)
			} else {
				whereSql += fmt.Sprintf(` %s`, s)
			}
			ifwhere = true
		}
	}

	if req.Promise_date != "" {
		t, _ := get_time_ex(req.Promise_date)
		if len(t) == 2 {
			if ifwhere {
				whereSql += fmt.Sprintf(` and promise_date >='%s' and promise_date<='%s'`, t[0], t[1])
			} else {
				whereSql += fmt.Sprintf(` promise_date >='%s' and promise_date<='%s'`, t[0], t[1])
			}
			ifwhere = true
		}
	}

	if req.Plan_state != "" {
		likeStr := "%" + req.Plan_state + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [p_state] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [p_state] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	if req.Group_name != "" && req.Group_name != "待分解" {
		likeStr := "%" + req.Group_name + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [group_name] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [group_name] like '%s'`, likeStr)
		}
		ifwhere = true
	} else if req.Group_name == "待分解" {
		if ifwhere {
			whereSql += fmt.Sprintf(` and ([group_name] is null or group_name ='')`)
		} else {
			whereSql += fmt.Sprintf(` ([group_name] is null or group_name ='')`)
		}
		ifwhere = true
	}

	if req.If_del {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [del_flag] = %d`, 1)
		} else {
			whereSql += fmt.Sprintf(` [del_flag] = %d`, 1)
		}
		ifwhere = true
	} else {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [del_flag] != %d`, 1)
		} else {
			whereSql += fmt.Sprintf(` [del_flag] != %d`, 1)
		}
		ifwhere = true
	}

	//已处理
	scan_flag = 1 << (usrinfo.DepartmentId - 1)
	if req.If_finished {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [scan_flag]&%d>0 and [stay_department_id]!=%d`, scan_flag, usrinfo.DepartmentId)
		} else {
			whereSql += fmt.Sprintf(` [scan_flag]&%d>0 and [stay_department_id]!=%d`, scan_flag, usrinfo.DepartmentId)
		}
		ifwhere = true
	} else {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [scan_flag]&%d>0 and [stay_department_id]=%d`, scan_flag, usrinfo.DepartmentId)
		} else {
			whereSql += fmt.Sprintf(` [scan_flag]&%d>0 and [stay_department_id]=%d`, scan_flag, usrinfo.DepartmentId)
		}
		ifwhere = true
	}

	if ifwhere {
		sqlstr = fmt.Sprintf("select count(ID) from [plan] where %s ", whereSql)
	} else {
		sqlstr = fmt.Sprintf("select count(ID) from [plan] ")
	}

	logs.Info(sqlstr)
	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getKpi query %s err:%v", sqlstr, err.Error()))
		goto exit
	}

	for cntRow.Next() {
		var cnt int
		if err = cntRow.Scan(&cnt); err != nil {
			logs.Error(fmt.Sprintf("getKpi scan %s err:%v", sqlstr, err.Error()))
			goto exit
		} else {
			resp.Total = cnt
		}
	}
	cntRow.Close()

	/*if query_cnt > resp.Total {
		cnt = resp.Total + req.Count - query_cnt
	} else {
		cnt = req.Count
	}*/

	cnt = req.Count
	if ifwhere {
		sqlstr = fmt.Sprintf("select top %v [ID],[time],[data],[start_department_id],[stay_department_id] from [plan] where ID not in (select top %v ID from [plan] where %s order by ID desc) and %s order by [ID] desc",
			cnt, (req.Index-1)*req.Count, whereSql, whereSql)
	} else {
		sqlstr = fmt.Sprintf("select top %v [ID],[time],[data],[start_department_id],[stay_department_id] from [plan] where ID not in (select top %v ID from [plan] order by ID desc) order by [ID] desc",
			cnt, (req.Index-1)*req.Count)
	}

	logs.Info(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getKpi Query err:%v", err.Error()))
		goto exit
	}

	for rdRow.Next() {
		var d kpi
		var id int
		var v string
		var createTime string
		var start_did int
		var stay_did int
		if err := rdRow.Scan(&id, &createTime, &v, &start_did, &stay_did); err == nil {

			json.Unmarshal([]byte(v), &d)

			if req.If_finished {
				d.If_show_del = false
				//d.If_show_update = false

				if usrinfo.DepartmentId == 1 && d.Plan_state == "入库" {
					d.If_show_update = true
				} else {
					d.If_show_update = false
				}

			} else if req.If_del {
				d.If_show_del = false
				d.If_show_update = false

				d.If_show_del_his = true
			} else {
				if usrinfo.RoleId == 1 && usrinfo.DepartmentId == 1 {
					d.If_show_del = true
					d.If_show_update = true
				} else {
					if start_did == stay_did {
						d.If_show_del = true
					}

					if stay_did == usrinfo.DepartmentId {
						d.If_show_update = true
					}
				}
			}

			d.ID = id

			t := strings.Split(createTime[:10], "-")
			for i := 0; i < len(t); i++ {
				if i == 0 {
					d.CreateTime += t[i][2:]
				} else {
					d.CreateTime += "/" + t[i]
				}
			}
			//+ " " + createTime[11:19]
			d.Time = createTime[11:19]

			if len(d.Plan_dispath_date) > 2 {
				d.Plan_dispath_date = d.Plan_dispath_date[2:]
			}

			if d.Plan_actual_finished_date != "" && d.Plan_finished_date != "" {
				if d.Plan_actual_finished_date > d.Plan_finished_date {
					d.Overdue = "是"
				}
			}

			if d.Plan_actual_finished_date == "" && d.Plan_finished_date != "" {
				now_t := time.Now().Format(g_loc)

				now_t = strings.ReplaceAll(string(now_t[:10]), "-", "/")
				if now_t > d.Plan_finished_date {
					d.Overdue = "是"
				}
			}

			if len(d.Plan_finished_date) > 2 {
				d.Plan_finished_date = d.Plan_finished_date[2:]
			}

			if len(d.Plan_actual_finished_date) > 2 {
				d.Plan_actual_finished_date = d.Plan_actual_finished_date[2:]
			}

			if len(d.Promise_date) > 2 {
				d.Promise_date = d.Promise_date[2:]
			}

			if len(d.Promised_date) > 2 {
				d.Promised_date = d.Promised_date[2:]
			}

			if len(d.Demand_date) > 2 {
				d.Demand_date = d.Demand_date[2:]
			}

			if d.Feishu_link != "" {
				d.Flink_color = "color: #409EFF;"
			} else {
				d.Flink_color = "color: #C0C4CC;"
			}

			rdm_id, _ := strconv.Atoi(d.RDM_id)
			if rdm_id < 10000 {
				d.Redmine_color = "color: #C0C4CC;"
			} else {
				d.Redmine_color = "color: #409EFF;"
			}

			if file, ok := file_cache_data[d.Product_id+"车"]; ok {
				var pf plan_file_d
				if file.Plan_process_file != "" {
					pf.FileName = file.Plan_process_file
					pf.Filing_time = file.Filing_time
					d.Files_c = append(d.Files_c, pf)
				}

				if file.Project_file != "" {
					pf.FileName = file.Project_file
					pf.Filing_time = file.P_filing_time
					d.Files_c = append(d.Files_c, pf)
				}

				if len(d.Files_c) == 0 {
					d.Files_c = []plan_file_d{}
				}
			} else {
				d.Files_c = []plan_file_d{}
			}

			if file, ok := file_cache_data[d.Product_id+"铣"]; ok {
				var pf plan_file_d
				if file.Plan_process_file != "" {
					pf.FileName = file.Plan_process_file
					pf.Filing_time = file.Filing_time
					d.Files_x = append(d.Files_x, pf)
				}

				if file.Project_file != "" {
					pf.FileName = file.Project_file
					pf.Filing_time = file.P_filing_time
					d.Files_x = append(d.Files_x, pf)
				}

				if len(d.Files_x) == 0 {
					d.Files_x = []plan_file_d{}
				}
			} else {
				d.Files_x = []plan_file_d{}
			}

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("getKpi scan Error", err.Error())
		}
	}
	rdRow.Close()

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("getKpi recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func getPrekpi(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("getPrekpi recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req getPreKpiReq
	var resp getPreKpiResp

	var ifwhere bool
	var whereSql string
	var department string // 将department变量声明提到前面

	var sqlstr string
	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	logs.Info(string(reqdata))
	logs.Info(req)

	query_cnt := req.Index * req.Count
	logs.Info("query_cnt:", query_cnt)
	var cnt int

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线", req.OpUser))
		goto exit
	}

	// 查询用户的department
	sqlstr = fmt.Sprintf("SELECT department FROM [user] WHERE username = '%s'", req.OpUser)
	logs.Info("查询用户department SQL:", sqlstr)

	// department变量已经在前面的var声明中声明了
	err = sqlConn.QueryRow(sqlstr).Scan(&department)
	if err != nil {
		if err == sql.ErrNoRows {
			logs.Info(fmt.Sprintf("用户%s不存在", req.OpUser))
			resp.Department = ""
		} else {
			logs.Error(fmt.Sprintf("查询用户department失败:%s", err.Error()))
			resp.Department = ""
		}
	} else {
		resp.Department = department
		logs.Info(fmt.Sprintf("用户%s的department为:%s", req.OpUser, department))
	}

	if req.SapId != "" { //编码
		likeStr := "%" + req.SapId + "%"
		whereSql += fmt.Sprintf(` [task_id] like '%s'`, likeStr)
		ifwhere = true
	}

	//序号
	if req.Id != "" {
		likeStr := "%" + req.Id + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [ID] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [ID] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	//产品编号
	if req.Pid != "" {
		likeStr := "%" + req.Pid + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [p_id] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [p_id] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	//产品名称
	if req.Pname != "" {
		likeStr := "%" + req.Pname + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [p_name] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [p_name] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	//需求人
	if req.Conveyer != "" {
		likeStr := "%" + req.Conveyer + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [conveyer] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [conveyer] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	//Rdm
	if req.Rdm_id != "" {
		likeStr := "%" + req.Rdm_id + "%"
		if ifwhere {
			whereSql += fmt.Sprintf(` and [rmd_id] like '%s'`, likeStr)
		} else {
			whereSql += fmt.Sprintf(` [rmd_id] like '%s'`, likeStr)
		}
		ifwhere = true
	}

	if req.Bt != "" && req.Et != "" {
		fmt.Println("req.Bt-------", req.Bt)
		fmt.Println("req.Et-------", req.Et)

		timeCondition := fmt.Sprintf(" [time] >= '%s 00:00:00' and [time] <= '%s 23:59:59' ", req.Bt, req.Et)

		if ifwhere {
			whereSql += fmt.Sprintf(" and %s", timeCondition)
		} else {
			whereSql += fmt.Sprintf(" %s", timeCondition)
		}
		ifwhere = true
	}

	if req.If_finished {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [commit_flag] = 1 `)
		} else {
			whereSql += fmt.Sprintf(`  [commit_flag] = 1`)
		}
		ifwhere = true
	} else {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [commit_flag] = 0 `)
		} else {
			whereSql += fmt.Sprintf(`  [commit_flag] = 0`)
		}
		ifwhere = true
	}

	if req.If_del {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [del_flag] = %d`, 1)
		} else {
			whereSql += fmt.Sprintf(` [del_flag] = %d`, 1)
		}
		ifwhere = true
	} else {
		if ifwhere {
			whereSql += fmt.Sprintf(` and [del_flag] != %d`, 1)
		} else {
			whereSql += fmt.Sprintf(` [del_flag] != %d`, 1)
		}
		ifwhere = true
	}

	if ifwhere {
		sqlstr = fmt.Sprintf("select count(ID) from [pre_plan] where %s ", whereSql)
	} else {
		sqlstr = fmt.Sprintf("select count(ID) from [pre_plan] ")
	}

	logs.Info(sqlstr)
	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getKpi query %s err:%v", sqlstr, err.Error()))
		goto exit
	}

	for cntRow.Next() {
		var cnt int
		if err = cntRow.Scan(&cnt); err != nil {
			logs.Error(fmt.Sprintf("getKpi scan %s err:%v", sqlstr, err.Error()))
			goto exit
		} else {
			resp.Total = cnt
		}
	}
	cntRow.Close()

	/*if query_cnt > resp.Total {
		cnt = resp.Total + req.Count - query_cnt
	} else {
		cnt = req.Count
	}*/

	cnt = req.Count
	if ifwhere {
		sqlstr = fmt.Sprintf("SELECT [ID],[time],[p_id],[p_name],[p_state],[group_name],[rmd_id],[promise_date],[conveyer],[is_img],[is_materials],[is_frist_process],[is_new_gauge],[start_dept],[task_id],[total_num],[remarks],[demand_date],[commit_flag],[file_check] FROM [pre_plan] WHERE %s ORDER BY [ID] DESC OFFSET %d ROWS FETCH NEXT %d ROWS ONLY",
			whereSql, (req.Index-1)*req.Count, cnt)
	} else {
		sqlstr = fmt.Sprintf("SELECT [ID],[time],[p_id],[p_name],[p_state],[group_name],[rmd_id],[promise_date],[conveyer],[is_img],[is_materials],[is_frist_process],[is_new_gauge],[start_dept],[task_id],[total_num],[remarks],[demand_date],[commit_flag],[file_check] FROM [pre_plan] ORDER BY [ID] DESC OFFSET %d ROWS FETCH NEXT %d ROWS ONLY",
			(req.Index-1)*req.Count, cnt)
	}
	fmt.Println("sqlstr数据----------", sqlstr)
	logs.Info(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getKpi Query err:%v", err.Error()))
		fmt.Println("getPreKpi Query err:%v", err.Error())
		goto exit
	}

	for rdRow.Next() {
		var d preKpi
		if err := rdRow.Scan(&d.ID, &d.CreateTime, &d.Product_id, &d.Product_name, &d.Product_state, &d.Group_name, &d.RDM_id, &d.Promise_date, &d.Conveyer, &d.Is_img, &d.Is_materials, &d.First_procesds, &d.Is_new_gauge, &d.Department_name, &d.Task_id, &d.Total_num, &d.Remarks, &d.Demand_date, &d.Commit_flag, &d.File_check); err == nil {

			if d.CreateTime != "" {
				// 如果 CreateTime 是字符串类型
				if t, err := time.Parse("2006-01-02 15:04:05", d.CreateTime); err == nil {
					d.CreateTime = t.Format("2006-01-02")
				} else if t, err := time.Parse(time.RFC3339, d.CreateTime); err == nil {
					// 如果是 RFC3339 格式（如数据库的 datetime 格式）
					d.CreateTime = t.Format("2006-01-02")
				} else if t, err := time.Parse("2006-01-02", d.CreateTime); err == nil {
					// 如果本来就是只有日期的格式，保持原样
					d.CreateTime = t.Format("2006-01-02")
				}
				// 可以根据需要添加其他时间格式的解析
			}

			rdm_id, _ := strconv.Atoi(d.RDM_id)
			if rdm_id < 10000 {
				d.Redmine_color = "color: #C0C4CC;"
			} else {
				d.Redmine_color = "color: #409EFF;"
			}

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("getPrekpi scan Error", err.Error())
			fmt.Println("getPrekpi scan Error", err.Error())
		}
	}
	rdRow.Close()

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("getPrekpi recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func getHistoryPrekpi(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("getHistoryPrekpi recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req getPreKpiReq
	var resp getPreKpiResp

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	logs.Info(string(reqdata))
	logs.Info(req)

	// 只保留 OpUser 非空校验
	if req.OpUser == "" {
		logs.Info("OpUser is empty")
		goto exit
	}

	// 直接查询 history_pre_plan 表中 user_name 匹配且 del_flag=0 的第一条记录（按 ID 倒序）
	sqlstr = fmt.Sprintf(`SELECT TOP 1 
		[ID],[time],[p_id],[p_name],[p_state],[group_name],[rmd_id],[promise_date],
		[conveyer],[is_img],[is_materials],[is_frist_process],[is_new_gauge],
		[start_dept],[task_id],[total_num],[remarks],[demand_date],[commit_flag],
		[file_check],[user_name] 
		FROM [history_pre_plan] 
		WHERE [user_name]='%s' 
		ORDER BY [ID] DESC`, req.OpUser)

	logs.Info("sqlstr----", sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getHistoryPrekpi Query err:%v", err.Error()))
		fmt.Println("getHistoryPrekpi Query err:%v", err.Error())
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d preKpi
		err = rdRow.Scan(&d.ID, &d.CreateTime, &d.Product_id, &d.Product_name, &d.Product_state,
			&d.Group_name, &d.RDM_id, &d.Promise_date, &d.Conveyer, &d.Is_img, &d.Is_materials,
			&d.First_procesds, &d.Is_new_gauge, &d.Department_name, &d.Task_id, &d.Total_num,
			&d.Remarks, &d.Demand_date, &d.Commit_flag, &d.File_check, &d.User_Name)
		if err == nil {
			// 格式化 CreateTime（与原逻辑一致）
			if d.CreateTime != "" {
				if t, err := time.Parse("2006-01-02 15:04:05", d.CreateTime); err == nil {
					d.CreateTime = t.Format("2006-01-02")
				}
			}
			// 设置 Redmine_color
			rdm_id, _ := strconv.Atoi(d.RDM_id)
			if rdm_id < 10000 {
				d.Redmine_color = "color: #C0C4CC;"
			} else {
				d.Redmine_color = "color: #409EFF;"
			}
			resp.Data = append(resp.Data, d)
			resp.Total = 1
		} else {
			logs.Error("getHistoryPrekpi scan Error", err.Error())
			fmt.Println("getHistoryPrekpi scan Error", err.Error())
		}
	}

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("getHistoryPrekpi recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func addKpi(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("addKpi recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var total_num int

	var dispath_num int
	var dispath_total_num int

	var plan_f_date time.Time
	var plan_actual_f_data time.Time

	var promise_date time.Time
	var promised_date time.Time

	var maxid int

	var data []byte
	var month int

	var err error
	var sqlstr string
	var resp AddKpiResp

	var usrinfo useInfo
	//	var now_time string
	//	var update_context string

	var rows *sql.Rows
	var if_exist bool

	timeLayout := "2006-01-02 15:04:05"
	loc, _ := time.LoadLocation("Local")

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req AddKpiReq
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线"))
		resp.Ret = -1
		goto exit
	}

	usrinfo, err = getUserInfo(req.OpUser)
	if err != nil {
		logs.Info(fmt.Sprintf("getUserInfo err:%s", err.Error()))
		resp.Ret = -1
		goto exit
	}

	req.Data.Product_name, if_exist = get_p_info(req.Data.Product_id)
	if !if_exist {
		logs.Info(fmt.Sprintf("产品编号:%s 不存在，请联系生产管理员添加！", req.Data.Product_id))
		resp.Err_text = fmt.Sprintf("产品编号:%s 不存在，请联系生产管理员添加！", req.Data.Product_id)
		resp.Ret = 2
		goto exit
	}

	task_transfer_update_time(0, usrinfo.DepartmentId, &req.Data)

	req.Data.Department_name = usrinfo.Department

	total_num, _ = strconv.Atoi(req.Data.Total_num)
	dispath_total_num, _ = strconv.Atoi(req.Data.Dispath_num)
	for i := 0; i < len(req.Data.Produce_plan_data); i++ {

		num, _ := strconv.Atoi(req.Data.Produce_plan_data[i].Dispath_num)
		dispath_num += num

		bt := strings.ReplaceAll(req.Data.Produce_plan_data[i].P_plan_finished_t, "/", "-") + " 00:00:00"
		plan_finished_date, _ := time.ParseInLocation(timeLayout, bt, loc)

		et := strings.ReplaceAll(req.Data.Produce_plan_data[i].P_actual_finished_t, "/", "-") + " 00:00:00"
		actual_finished_t, _ := time.ParseInLocation(timeLayout, et, loc)
		total_h := actual_finished_t.Sub(plan_finished_date).Hours()
		if total_h > 0 {
			req.Data.Produce_plan_data[i].P_finished_overdue_day = int(total_h) / 24
		}

		if i == 0 {
			req.Data.Plan_dispath_date = req.Data.Produce_plan_data[i].Plan_dispath_date
			req.Data.Plan_finished_date = req.Data.Produce_plan_data[i].P_plan_finished_t
			req.Data.Plan_actual_finished_date = req.Data.Produce_plan_data[i].P_actual_finished_t
		} else {
			if req.Data.Plan_dispath_date > req.Data.Produce_plan_data[i].Plan_dispath_date {
				req.Data.Plan_dispath_date = req.Data.Produce_plan_data[i].Plan_dispath_date
			}

			if req.Data.Plan_finished_date < req.Data.Produce_plan_data[i].P_plan_finished_t {
				req.Data.Plan_finished_date = req.Data.Produce_plan_data[i].P_plan_finished_t
			}

			if req.Data.Plan_actual_finished_date < req.Data.Produce_plan_data[i].P_actual_finished_t {
				req.Data.Plan_actual_finished_date = req.Data.Produce_plan_data[i].P_actual_finished_t
			}
		}
	}

	if total_num < dispath_total_num {
		resp.Ret = 3
		goto exit
	}

	if dispath_total_num < dispath_num {
		resp.Ret = 1
		goto exit
	}

	plan_f_date, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(req.Data.Plan_finished_date, "/", "-")+" 00:00:00", loc)
	plan_actual_f_data, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(req.Data.Plan_actual_finished_date, "/", "-")+" 00:00:00", loc)
	if plan_actual_f_data.Sub(plan_f_date).Hours() > 0 {
		req.Data.Overdue = "是"
	} else {
		req.Data.Overdue = "否"
	}

	promise_date, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(req.Data.Promise_date, "/", "-")+" 00:00:00", loc)
	promised_date, _ = time.ParseInLocation(timeLayout, strings.ReplaceAll(req.Data.Promised_date, "/", "-")+" 00:00:00", loc)
	if promised_date.Sub(promise_date).Hours() > 0 {
		req.Data.Material_overdue = "是"
	} else {
		req.Data.Material_overdue = "否"
	}

	if req.Data.Plan_state == "做账" {
		req.Data.Group_name = "保障组"
	}

	data, _ = json.Marshal(req.Data)
	month = time.Now().Year()*100 + int(time.Now().Month())
	sqlstr = fmt.Sprintf(`INSERT INTO [plan]
           ([time]
           ,[month]
           ,[data]
           ,[start_department_id]
           ,[stay_department_id]
           ,[scan_flag]
           ,[del_flag]
        	,[p_id]
      		,[p_name]
      		,[group_leader]
			,[p_state]
      		,[group_name]
			,[task_id])
     		VALUES ('%s',%d,'%s',%d,%d,%d,%d,'%s','%s','%s','%s','%s','%s')`,
		time.Now().Format("2006-01-02 15:04:05"), month,
		string(data), usrinfo.DepartmentId, usrinfo.DepartmentId,
		1<<(usrinfo.DepartmentId-1), 0,
		req.Data.Product_id, req.Data.Product_name, req.Data.Group_leader,
		req.Data.Plan_state, req.Data.Group_name, req.Data.Task_id)
	fmt.Println(sqlstr)

	mu.Lock()
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		mu.Unlock()
		logs.Info("addKpi Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

	//获取id
	sqlstr = fmt.Sprintf(`SELECT top 1 [ID] FROM [plan] order by ID desc`)
	rows, err = sqlConn.Query(sqlstr)
	if err == nil {

		for rows.Next() {
			if err = rows.Scan(&maxid); err != nil {
				logs.Info("addKpi scan Error:", err.Error())
			}
		}

		rows.Close()
	}
	mu.Unlock()

exit:

	if resp.Ret == 0 {

		if maxid > 0 {
			now_time := time.Now().Format("2006-01-02 15:04:05")
			update_context := fmt.Sprintf(`任务建立`)
			sqlstr = fmt.Sprintf(`INSERT INTO [update_history] ([ID],[op_time],[op_user],[data])  VALUES (%d,'%s','%s','%s')`, maxid, now_time, req.OpUser, update_context)
			_, err = sqlConn.Exec(sqlstr)
			if err != nil {
				logs.Info("addKpi Exec Error:", err.Error())
				resp.Ret = -1
			}
		}
	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("addKpi recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

//用户管理相关接口

func getUserNames(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("getUserNames recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req getUserNamesReq
	var resp getUserNamesResp

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	sqlstr = fmt.Sprintf("select [username] from [user] order by ID asc")
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getUserNames Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var name string
		var v usernams
		if err := rdRow.Scan(&name); err == nil {
			v.Label = name
			v.Value = name
			resp.Names = append(resp.Names, v)
		} else {
			logs.Error("getUserNames scan Error", err.Error())
		}
	}

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("getUserNames recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func checkIsSysUserOnline(username string, op_uuid string) bool {

	deesUserStatMaplck.RLock()
	if v, ok := deesUserStatMap[username]; ok {
		deesUserStatMaplck.RUnlock()

		v.RLock()
		refreshTime := v.RefreshTime
		userrole := v.UserRole
		uuid := v.Uuid
		v.RUnlock()
		if int64(time.Since(refreshTime).Seconds()) > int64(refreshSpan+1) {
			return false
		}

		if op_uuid != uuid {
			return false
		}

		if userrole != 1 {
			return false
		}

		return true
	} else {
		deesUserStatMaplck.RUnlock()

		return false
	}
}

func postUser(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("postUser recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	//	var opContent string
	//	var opType int

	var roleid int
	var err error
	var sqlstr string
	var resp PostUserResp
	var departmentid int

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req PostUserReq
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	if (req.OperType == 2 || req.OperType == 3) && req.Id == 0 {
		logs.Info("update userinfo req id ==0")
		resp.Ret = -1
		goto exit
	}

	//add op check user for same username
	if req.OperType == 1 {
		var cnt int
		row, err := sqlConn.Query(fmt.Sprintf(`select ID from [user] where [username] = '%s'`, req.Username))
		if err != nil {
			logs.Error(fmt.Sprintf("postUser get user cnt err:%v", err.Error()))
			resp.Ret = -1
			goto exit
		}

		for row.Next() {
			cnt++
		}
		row.Close()

		if cnt > 0 {
			resp.Ret = 1
			goto exit
		}
	}

	roleid = 2
	if req.Role == "管理员" {
		roleid = 1
	} else if req.Role == "审核员" {
		roleid = 3
	} else if req.Role == "查询" {
		roleid = 4
	}

	//1生产 2质检 3供应链 4交付 5研发 6 保温瓶 7技术 8生产订单
	if req.Department == "生产" {
		departmentid = 1
	} else if req.Department == "质检" {
		departmentid = 2
	} else if req.Department == "供应链" {
		departmentid = 3
	} else if req.Department == "交付" {
		departmentid = 4
	} else if req.Department == "研发" {
		departmentid = 5
	} else if req.Department == "保温瓶" {
		departmentid = 6
	} else if req.Department == "技术" {
		departmentid = 7
	} else if req.Department == "生产订单" {
		departmentid = 8
	} else if req.Department == "质量检验" {
		departmentid = 9
	} else {
		if req.OperType != 3 {
			goto exit
		}
	}

	if req.OperType == 1 { //add
		//opType = 10001
		//opContent = fmt.Sprintf(`新增用户%s`, req.Username)
		sqlstr = fmt.Sprintf(`INSERT INTO [user] ([username],[password],[role_name],[role_id],[department],[department_id],[state]) VALUES ('%s','%s','%s',%d,'%s',%d,'%s')`,
			req.Username, req.Password, req.Role, roleid, req.Department, departmentid,
			req.State)
	} else if req.OperType == 2 { //update
		//opType = 10002
		//opContent = fmt.Sprintf(`修改用户%s`, req.Username)
		sqlstr = fmt.Sprintf(`UPDATE [user] SET [username] = '%s',[password] = '%s',[role_name] = '%s',[role_id] = %d,[department]='%s',[department_id]=%d ,[state]='%s' WHERE ID=%d`,
			req.Username, req.Password, req.Role, roleid, req.Department, departmentid, req.State,
			req.Id)
	} else if req.OperType == 3 {
		//opType = 10003
		//		opContent = fmt.Sprintf(`删除用户%s`, req.Username)
		sqlstr = fmt.Sprintf(`DELETE FROM [user] WHERE ID=%d`, req.Id)
	} else {
		resp.Ret = -1
		goto exit
	}
	fmt.Println(sqlstr)

	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("postUser Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("postUser recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func getUsers(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("getUsers recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req getUsersReq
	var resp GetUsersResp

	var sqlstr string
	var rcnt int
	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.Id == "" {
		sqlstr = "select count(ID) from [user] where state='状态1'"
	} else {
		likeStr := "%" + req.Id + "%"
		sqlstr = fmt.Sprintf("select count(ID) from [user] where [username] like '%s'", likeStr)
	}
	fmt.Println(sqlstr)

	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getUsers query %s err:%v", sqlstr, err.Error()))
		goto exit
	}
	defer cntRow.Close()

	for cntRow.Next() {
		if err = cntRow.Scan(&rcnt); err != nil {
			logs.Error(fmt.Sprintf("getUsers scan %s err:%v", sqlstr, err.Error()))
			goto exit
		}
	}
	resp.Total = rcnt

	if req.Id == "" {
		sqlstr = fmt.Sprintf("select top %v [ID],[username],[password],[role_name],[role_id],[department] ,[state] from [user] where ID not in (select top %v ID from [user] where state='状态1' order by ID asc) and state='状态1' order by ID asc", req.Count, (req.Index-1)*req.Count)
	} else {
		likeStr := "%" + req.Id + "%"
		sqlstr = fmt.Sprintf("select top %v [ID],[username],[password],[role_name],[role_id],[department] ,[state] from [user] where username like '%s' and ID not in (select top %v ID from [user] where username like '%s' order by ID asc) order by ID asc", req.Count, likeStr, (req.Index-1)*req.Count, likeStr)
	}
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getUsers Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d useInfo

		if err := rdRow.Scan(&d.Userid, &d.Username, &d.Password, &d.RoleName, &d.RoleId,
			&d.Department, &d.State); err == nil {
			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("getUsers scan Error", err.Error())
		}
	}

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("getUsers recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func checkUserIfOnline(username string, uuid string) bool {

	deesUserStatMaplck.RLock()
	if v, ok := deesUserStatMap[username]; ok {
		deesUserStatMaplck.RUnlock()

		v.RLock()
		refreshTime := v.RefreshTime
		lastuuid := v.Uuid
		v.RUnlock()

		if uuid != lastuuid {
			return false
		}

		if int64(time.Since(refreshTime).Seconds()) > int64(refreshSpan+1) {
			return false
		}
		return true
	} else {
		deesUserStatMaplck.RUnlock()

		return false
	}
}

func getUserInfo(username string) (d useInfo, err error) {

	var sql string
	sql = fmt.Sprintf("select [username],[password],[role_name],[role_id],[department],[department_id] from [user] where [username] = '%s'", username)
	row, err := sqlConn.Query(sql)
	if err != nil {
		logs.Info("getUserInfo Query Error", err.Error())
		return
	}

	for row.Next() {

		if err = row.Scan(&d.Username, &d.Password, &d.RoleName, &d.RoleId, &d.Department, &d.DepartmentId); err == nil {
		} else {
			logs.Info("Query Error", err.Error())
		}
	}
	row.Close()

	return
}

func get_all_user() (resp []useInfo, err error) {

	var sql string
	sql = fmt.Sprintf("select [username],[password],[role_name],[role_id],[department],[department_id],[state] from [user] ")
	row, err := sqlConn.Query(sql)
	if err != nil {
		logs.Info("get_all_user Query Error", err.Error())
		return
	}

	for row.Next() {

		var d useInfo
		if err = row.Scan(&d.Username, &d.Password, &d.RoleName, &d.RoleId, &d.Department, &d.DepartmentId,
			&d.State); err == nil {
			resp = append(resp, d)
		} else {
			logs.Info("get_all_user scan Error", err.Error())
		}
	}
	row.Close()

	return
}

//菜单

func get_menu_9(req GetMenuReq, userInfo useInfo) (resp GetMenuResp) {

	var menu GetMenuRespData
	var mItem menuItem

	menu.Title = "质量检测管理"
	menu.Index = "2"
	//menu.Class = "el-icon-s-data"
	//menu.SvgData.First = "M992.256 960 960 960 960 576.192C960 540.032 931.072 512 895.424 512l-126.784 0C732.352 512 704 540.736 704 576.192L704 960l-64 0L640 64.448C640 28.736 611.072 0 575.424 0L448.576 0C412.352 0 384 28.864 384 64.448L384 960 320 960 320 319.744C320 284.48 291.072 256 255.424 256L128.576 256C92.352 256 64 284.544 64 319.744L64 960 31.744 960C14.464 960 0 974.336 0 992 0 1009.152 14.208 1024 31.744 1024l960.448 0C1009.536 1024 1024 1009.664 1024 992 1024 974.848 1009.792 960 992.256 960z"
	menu.SvgData.First = "M955.3 77.1H798.1V59.3c0-16.6-13.4-30-30-30s-30 13.4-30 30v17.8H278.3V59.3c0-16.6-13.4-30-30-30s-30 13.4-30 30v17.8H69.2c-22.1 0-40 17.9-40 40v837.1c0 22.1 17.9 40 40 40h886.1c22.1 0 40-17.9 40-40V117.1c0-22.1-17.9-40-40-40z m-29.9 847.1H99.2V376.4h826.2v547.8z m0-607.8H99.2V137.1h119.1v17.8c0 16.6 13.4 30 30 30s30-13.4 30-30v-17.8h459.9v17.8c0 16.6 13.4 30 30 30s30-13.4 30-30v-17.8h127.2v179.3z"
	menu.SvgData.Second = "M470.4 551.3h321.4c18.2 0 33-14.8 33-33s-14.8-33-33-33H470.4c-18.2 0-33 14.8-33 33s14.8 33 33 33zM210.3 562.6l64.8 64.8 110.8-110.8c9.5-9.5 9.5-25 0-34.5s-25-9.5-34.5 0l-76.3 76.3-30.3-30.3c-9.5-9.5-25-9.5-34.5 0s-9.5 25 0 34.5zM470.4 785h321.4c18.2 0 33-14.8 33-33s-14.8-33-33-33H470.4c-18.2 0-33 14.8-33 33s14.8 33 33 33zM316.8 719.2h-67.9c-18.2 0-33 14.8-33 33s14.8 33 33 33h67.9c18.2 0 33-14.8 33-33s-14.8-33-33-33z"
	menu.Key = menu.Index

	mItem.Index = "/ledger"
	mItem.Title = "入库检验台账"
	mItem.Key = mItem.Index
	menu.Items = append(menu.Items, mItem)

	mItem.Index = "/ledger_out"
	mItem.Title = "出库检验台账"
	mItem.Key = mItem.Index
	menu.Items = append(menu.Items, mItem)

	mItem.Index = "/ledger_r"
	mItem.Title = "退库检验台账"
	mItem.Key = mItem.Index
	menu.Items = append(menu.Items, mItem)

	resp.MenuData = append(resp.MenuData, menu)

	if userInfo.RoleId == 1 {
		menu.Title = "基础数据管理"
		menu.Index = "3"
		//menu.Class = "el-icon-user"
		menu.SvgData.First = "M64 192V896h896V192H64zM0 128h1024v832H0V128z"
		menu.SvgData.Second = "M64 384h896v64H64zM64 640h896v64H64zM128 256h192v64H128zM128 512h192v64H128zM128 768h192v64H128z"
		menu.Key = menu.Index
		menu.Items = []menuItem{}

		mItem.Index = "/ibase"
		mItem.Title = "产品检测依据管理"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)

		mItem.Index = "/tpm"
		mItem.Title = "产品检测项管理"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)

		/*mItem.Index = "/imm"
		mItem.Title = "检验方法管理"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)*/

		resp.MenuData = append(resp.MenuData, menu)
	}

	if userInfo.RoleId == 1 {
		menu.Title = "用户管理"
		menu.Index = "1"
		//menu.Class = "el-icon-user"
		menu.SvgData.First = "M955.456 765.12a41.792 41.792 0 0 0-34.368-32.64 8.256 8.256 0 0 1-6.08-3.904 8.256 8.256 0 0 1-0.384-7.104 41.856 41.856 0 0 0-11.136-45.696 165.76 165.76 0 0 0-60.096-34.56 41.728 41.728 0 0 0-45.056 13.12c-1.216 1.472-3.328 3.264-6.336 3.264s-5.12-1.728-6.336-3.264a41.6 41.6 0 0 0-45.056-13.184 166.4 166.4 0 0 0-60.224 34.624 41.728 41.728 0 0 0-11.136 45.632 8.064 8.064 0 0 1-0.384 7.104 8.256 8.256 0 0 1-6.08 3.904 41.728 41.728 0 0 0-34.304 32.64 166.72 166.72 0 0 0 0 68.928c3.584 16.96 17.28 29.952 34.432 32.64 1.92 0.32 4.544 1.216 6.08 3.904a8.256 8.256 0 0 1 0.384 7.104 41.6 41.6 0 0 0 11.136 45.696c17.344 15.616 37.568 27.2 60.096 34.56a41.728 41.728 0 0 0 45.056-13.056c1.216-1.472 3.328-3.264 6.336-3.264s5.12 1.728 6.336 3.264a41.728 41.728 0 0 0 45.056 13.12c22.528-7.296 42.688-18.88 59.968-34.432 12.8-11.52 17.216-29.696 11.136-45.76a8.192 8.192 0 0 1 0.384-7.168 8.256 8.256 0 0 1 6.08-3.904 41.728 41.728 0 0 0 34.496-32.64 166.144 166.144 0 0 0 0-68.928z m-40.832 60.288a49.92 49.92 0 0 0-35.904 24.256 49.92 49.92 0 0 0-3.264 42.752 123.584 123.584 0 0 1-44.992 25.792 49.92 49.92 0 0 0-38.528-18.432 49.664 49.664 0 0 0-38.528 18.432 125.44 125.44 0 0 1-45.056-25.856 49.728 49.728 0 0 0-39.04-66.944 123.712 123.712 0 0 1 0-51.776 49.92 49.92 0 0 0 35.648-24.256 49.92 49.92 0 0 0 3.328-42.624c12.928-11.648 28.224-20.416 45.12-25.92a49.92 49.92 0 0 0 38.528 18.432c15.68 0 29.44-7.296 38.592-18.432 16.896 5.504 32.128 14.272 45.056 25.856a49.728 49.728 0 0 0 39.04 66.944 122.624 122.624 0 0 1 0 51.776z"
		menu.SvgData.Second = "M791.936 736.96c-34.496 0-62.592 28.096-62.592 62.592s28.096 62.592 62.592 62.592 62.592-28.096 62.592-62.592-28.096-62.592-62.592-62.592z m0 83.456a20.864 20.864 0 1 1 0-41.728 20.864 20.864 0 0 1 0 41.728zM670.336 588.736c0.256 0.128 0.512 0.064 0.768 0.128l1.472 0.512 0.064-0.256a35.392 35.392 0 0 0 22.912-67.008l-0.384-0.064c-8.512-3.392-17.472-6.144-26.304-9.088a247.424 247.424 0 0 0 104.192-201.472 248.192 248.192 0 1 0-496.384 0c0 83.072 41.216 156.224 103.936 201.28-175.68 57.984-304.832 218.368-315.776 410.688 0 0.128 0.256 0.192 0.256 0.256a35.328 35.328 0 0 0 68.608 13.504c1.344-3.456 1.536-7.04 1.728-10.56l0.256-0.192a390.016 390.016 0 0 1 389.248-366.336c51.264 0 100.032 10.176 144.832 28.16 0.192 0.192 0.32 0.384 0.576 0.448zM347.648 311.424a177.28 177.28 0 1 1 354.56 0 177.28 177.28 0 0 1-354.56 0z"
		menu.Key = menu.Index
		menu.Items = []menuItem{}

		mItem.Index = "/user"
		mItem.Title = "用户信息"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)

		resp.MenuData = append(resp.MenuData, menu)
	}

	return
}

func getMenu(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("getMenu recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var err error
	var req GetMenuReq
	var resp GetMenuResp

	var menu GetMenuRespData
	var mItem menuItem

	var userInfo useInfo

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	ifOnline := checkUserIfOnline(req.UserName, req.Uuid)
	if !ifOnline {
		goto exit
	}

	userInfo, err = getUserInfo(req.UserName)
	if err != nil {
		goto exit
	}

	if userInfo.DepartmentId == 9 {
		resp = get_menu_9(req, userInfo)
		goto exit
	}

	menu.Title = "生产计划管理"
	menu.Index = "2"
	//menu.Class = "el-icon-s-data"
	//menu.SvgData.First = "M992.256 960 960 960 960 576.192C960 540.032 931.072 512 895.424 512l-126.784 0C732.352 512 704 540.736 704 576.192L704 960l-64 0L640 64.448C640 28.736 611.072 0 575.424 0L448.576 0C412.352 0 384 28.864 384 64.448L384 960 320 960 320 319.744C320 284.48 291.072 256 255.424 256L128.576 256C92.352 256 64 284.544 64 319.744L64 960 31.744 960C14.464 960 0 974.336 0 992 0 1009.152 14.208 1024 31.744 1024l960.448 0C1009.536 1024 1024 1009.664 1024 992 1024 974.848 1009.792 960 992.256 960z"
	menu.SvgData.First = "M955.3 77.1H798.1V59.3c0-16.6-13.4-30-30-30s-30 13.4-30 30v17.8H278.3V59.3c0-16.6-13.4-30-30-30s-30 13.4-30 30v17.8H69.2c-22.1 0-40 17.9-40 40v837.1c0 22.1 17.9 40 40 40h886.1c22.1 0 40-17.9 40-40V117.1c0-22.1-17.9-40-40-40z m-29.9 847.1H99.2V376.4h826.2v547.8z m0-607.8H99.2V137.1h119.1v17.8c0 16.6 13.4 30 30 30s30-13.4 30-30v-17.8h459.9v17.8c0 16.6 13.4 30 30 30s30-13.4 30-30v-17.8h127.2v179.3z"
	menu.SvgData.Second = "M470.4 551.3h321.4c18.2 0 33-14.8 33-33s-14.8-33-33-33H470.4c-18.2 0-33 14.8-33 33s14.8 33 33 33zM210.3 562.6l64.8 64.8 110.8-110.8c9.5-9.5 9.5-25 0-34.5s-25-9.5-34.5 0l-76.3 76.3-30.3-30.3c-9.5-9.5-25-9.5-34.5 0s-9.5 25 0 34.5zM470.4 785h321.4c18.2 0 33-14.8 33-33s-14.8-33-33-33H470.4c-18.2 0-33 14.8-33 33s14.8 33 33 33zM316.8 719.2h-67.9c-18.2 0-33 14.8-33 33s14.8 33 33 33h67.9c18.2 0 33-14.8 33-33s-14.8-33-33-33z"
	menu.Key = menu.Index

	mItem.Index = "/scb"
	mItem.Title = "生产计划"
	mItem.Key = mItem.Index
	menu.Items = append(menu.Items, mItem)

	mItem.Index = "/pre"
	mItem.Title = "生产前置计划"
	mItem.Key = mItem.Index
	menu.Items = append(menu.Items, mItem)
	resp.MenuData = append(resp.MenuData, menu)

	if userInfo.RoleId == 1 && userInfo.DepartmentId == 1 {
		menu.Title = "用户管理"
		menu.Index = "1"
		//menu.Class = "el-icon-user"
		menu.SvgData.First = "M955.456 765.12a41.792 41.792 0 0 0-34.368-32.64 8.256 8.256 0 0 1-6.08-3.904 8.256 8.256 0 0 1-0.384-7.104 41.856 41.856 0 0 0-11.136-45.696 165.76 165.76 0 0 0-60.096-34.56 41.728 41.728 0 0 0-45.056 13.12c-1.216 1.472-3.328 3.264-6.336 3.264s-5.12-1.728-6.336-3.264a41.6 41.6 0 0 0-45.056-13.184 166.4 166.4 0 0 0-60.224 34.624 41.728 41.728 0 0 0-11.136 45.632 8.064 8.064 0 0 1-0.384 7.104 8.256 8.256 0 0 1-6.08 3.904 41.728 41.728 0 0 0-34.304 32.64 166.72 166.72 0 0 0 0 68.928c3.584 16.96 17.28 29.952 34.432 32.64 1.92 0.32 4.544 1.216 6.08 3.904a8.256 8.256 0 0 1 0.384 7.104 41.6 41.6 0 0 0 11.136 45.696c17.344 15.616 37.568 27.2 60.096 34.56a41.728 41.728 0 0 0 45.056-13.056c1.216-1.472 3.328-3.264 6.336-3.264s5.12 1.728 6.336 3.264a41.728 41.728 0 0 0 45.056 13.12c22.528-7.296 42.688-18.88 59.968-34.432 12.8-11.52 17.216-29.696 11.136-45.76a8.192 8.192 0 0 1 0.384-7.168 8.256 8.256 0 0 1 6.08-3.904 41.728 41.728 0 0 0 34.496-32.64 166.144 166.144 0 0 0 0-68.928z m-40.832 60.288a49.92 49.92 0 0 0-35.904 24.256 49.92 49.92 0 0 0-3.264 42.752 123.584 123.584 0 0 1-44.992 25.792 49.92 49.92 0 0 0-38.528-18.432 49.664 49.664 0 0 0-38.528 18.432 125.44 125.44 0 0 1-45.056-25.856 49.728 49.728 0 0 0-39.04-66.944 123.712 123.712 0 0 1 0-51.776 49.92 49.92 0 0 0 35.648-24.256 49.92 49.92 0 0 0 3.328-42.624c12.928-11.648 28.224-20.416 45.12-25.92a49.92 49.92 0 0 0 38.528 18.432c15.68 0 29.44-7.296 38.592-18.432 16.896 5.504 32.128 14.272 45.056 25.856a49.728 49.728 0 0 0 39.04 66.944 122.624 122.624 0 0 1 0 51.776z"
		menu.SvgData.Second = "M791.936 736.96c-34.496 0-62.592 28.096-62.592 62.592s28.096 62.592 62.592 62.592 62.592-28.096 62.592-62.592-28.096-62.592-62.592-62.592z m0 83.456a20.864 20.864 0 1 1 0-41.728 20.864 20.864 0 0 1 0 41.728zM670.336 588.736c0.256 0.128 0.512 0.064 0.768 0.128l1.472 0.512 0.064-0.256a35.392 35.392 0 0 0 22.912-67.008l-0.384-0.064c-8.512-3.392-17.472-6.144-26.304-9.088a247.424 247.424 0 0 0 104.192-201.472 248.192 248.192 0 1 0-496.384 0c0 83.072 41.216 156.224 103.936 201.28-175.68 57.984-304.832 218.368-315.776 410.688 0 0.128 0.256 0.192 0.256 0.256a35.328 35.328 0 0 0 68.608 13.504c1.344-3.456 1.536-7.04 1.728-10.56l0.256-0.192a390.016 390.016 0 0 1 389.248-366.336c51.264 0 100.032 10.176 144.832 28.16 0.192 0.192 0.32 0.384 0.576 0.448zM347.648 311.424a177.28 177.28 0 1 1 354.56 0 177.28 177.28 0 0 1-354.56 0z"
		menu.Key = menu.Index
		menu.Items = []menuItem{}

		mItem.Index = "/user"
		mItem.Title = "用户信息"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)

		mItem.Index = "/puser"
		mItem.Title = "生产人员录入"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)

		mItem.Index = "/buser"
		mItem.Title = "采购人员录入"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)

		resp.MenuData = append(resp.MenuData, menu)
	}

	if userInfo.RoleId == 1 && userInfo.DepartmentId == 1 {
		menu.Title = "基础数据管理"
		menu.Index = "3"
		//menu.Class = "el-icon-user"
		menu.SvgData.First = "M64 192V896h896V192H64zM0 128h1024v832H0V128z"
		menu.SvgData.Second = "M64 384h896v64H64zM64 640h896v64H64zM128 256h192v64H128zM128 512h192v64H128zM128 768h192v64H128z"
		menu.Key = menu.Index
		menu.Items = []menuItem{}

		mItem.Index = "/base_data"
		mItem.Title = "产品信息管理"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)

		mItem.Index = "/pf"
		mItem.Title = "程序文件管理"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)

		mItem.Index = "/ds"
		mItem.Title = "定向传感器数据"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)

		resp.MenuData = append(resp.MenuData, menu)
	}

	// ============== 添加日志页面 ====================
	if userInfo.RoleId == 1 && userInfo.DepartmentId == 1 {
		menu.Title = "日志管理"
		menu.Index = "5"
		//menu.Class = "el-icon-user"
		menu.SvgData.First = "M512 986.387692a148.361846 148.361846 0 0 1-147.101538-130.520615h-287.901539a39.384615 39.384615 0 0 1-39.384615-39.384615 39.384615 39.384615 0 0 1 39.384615-39.384616h91.136V381.479385A344.300308 344.300308 0 0 1 512 37.572923a344.300308 344.300308 0 0 1 343.906462 343.906462v395.657846h91.136a39.384615 39.384615 0 0 1 39.384615 39.384615 39.384615 39.384615 0 0 1-39.384615 39.384616h-287.940924A148.361846 148.361846 0 0 1 512 986.387692z m-66.953846-130.520615a69.474462 69.474462 0 0 0 66.953846 51.751385 69.474462 69.474462 0 0 0 66.953846-51.751385z m175.852308-78.769231h156.396307V381.479385A265.452308 265.452308 0 0 0 512 116.342154a265.452308 265.452308 0 0 0-265.137231 265.137231v395.657846z"
		menu.SvgData.Second = "M512 986.387692a148.361846 148.361846 0 0 1-147.101538-130.520615h-287.901539a39.384615 39.384615 0 0 1-39.384615-39.384615 39.384615 39.384615 0 0 1 39.384615-39.384616h91.136V381.479385A344.300308 344.300308 0 0 1 512 37.572923a344.300308 344.300308 0 0 1 343.906462 343.906462v395.657846h91.136a39.384615 39.384615 0 0 1 39.384615 39.384615 39.384615 39.384615 0 0 1-39.384615 39.384616h-287.940924A148.361846 148.361846 0 0 1 512 986.387692z m-66.953846-130.520615a69.474462 69.474462 0 0 0 66.953846 51.751385 69.474462 69.474462 0 0 0 66.953846-51.751385z m175.852308-78.769231h156.396307V381.479385A265.452308 265.452308 0 0 0 512 116.342154a265.452308 265.452308 0 0 0-265.137231 265.137231v395.657846z"
		menu.Key = menu.Index
		menu.Items = []menuItem{}

		mItem.Index = "/log"
		mItem.Title = "用户日志"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)

		resp.MenuData = append(resp.MenuData, menu)
	}

exit:
	jdata, _ := json.Marshal(resp)

	_, err = response.Write(jdata)
	if err != nil {
		logs.Error("getMenu:", err.Error())
	}

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("getMenu recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func checkFileExpired() {
	defer func() {
		if r := recover(); r != nil {
			logs.Error("checkFileExpired panic:", r)
		}
	}()

	t := time.NewTicker(time.Minute * 3)
	defer t.Stop() // 确保Ticker被正确释放

	for {
		select {
		case <-t.C:
			modelePath, err := ModulePath.GetModuleCurrentPath()
			if err != nil {
				logs.Error("GetModuleCurrentPath() failed err:", err.Error())
				return
			}

			fileInfoList, err := ioutil.ReadDir(modelePath + "/file")
			if err != nil {
				logs.Error("ioutil.ReadDir err:", err.Error())
				continue
			}

			for i := range fileInfoList {
				index := strings.Index(fileInfoList[i].Name(), ".")
				if index == -1 {
					continue
				}
				filename := fileInfoList[i].Name()[:index]
				logs.Info(filename)
				t, err := strconv.ParseInt(filename, 10, 64)
				if err == nil {
					t = t / 1e9
					if time.Now().Unix()-t > 60 {
						os.Remove(modelePath + "/file/" + fileInfoList[i].Name())
					}
				}
			}
		}
	}
}

// func checkFileExpired() {

// 	t := time.NewTicker(time.Minute * 3)
// 	for {
// 		select {
// 		case <-t.C:
// 			modelePath, err := ModulePath.GetModuleCurrentPath()
// 			if err != nil {
// 				logs.Error("GetModuleCurrentPath() failed err:", err.Error())
// 				return
// 			}

// 			fileInfoList, err := ioutil.ReadDir(modelePath + "/file")
// 			if err != nil {
// 				logs.Error("ioutil.ReadDir err:", err.Error())
// 			}

// 			for i := range fileInfoList {
// 				index := strings.Index(fileInfoList[i].Name(), ".")
// 				filename := fileInfoList[i].Name()[:index]
// 				//filename := strings.TrimSuffix(fileInfoList[i].Name(), ".auf")
// 				logs.Info(filename) //打印当前文件或目录下的文件或目录名

// 				t, err := strconv.ParseInt(filename, 10, 64)
// 				if err == nil {
// 					t = t / 1e9

// 					if time.Now().Unix()-t > 60 {
// 						os.Remove(modelePath + "/file/" + fileInfoList[i].Name())
// 					}
// 				} else {
// 					//logs.Error("checkFileExpired err:", err.Error())
// 				}
// 			}

// 		default:
// 			time.Sleep(time.Minute * 1)
// 		}
// 	}
// }

// 登录
func getUuid() string {
	return uuid.NewV4().String()
}

func refreshUser(response http.ResponseWriter, request *http.Request) {
	//beginTime := time.Now().UnixNano()
	//logs.Info("refreshUser recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp CommonResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req RefreshUserReq
	json.Unmarshal(reqdata, &req)

	deesUserStatMaplck.RLock()
	if v, ok := deesUserStatMap[req.Username]; ok {
		deesUserStatMaplck.RUnlock()

		v.Lock()
		if v.Uuid == req.Uuid {

			if time.Now().Before(v.ExpireTime) {
				v.RefreshTime = time.Now()
				v.ExpireTime = time.Now().Add(ExpireTimeSpan)
			} else {
				resp.Ret = -1
			}

			//logs.Info(fmt.Sprintf("refreshTime:%v expiretime:%v", v.RefreshTime.Format("2006-01-02 15:04:05"), v.ExpireTime.Format("2006-01-02 15:04:05")))

			v.Unlock()
		} else {
			v.Unlock()
			resp.Ret = -1

			//fmt.Println("uuid:", v.Uuid)
			//fmt.Println("req.uuid", req.Uuid)
		}

	} else {
		deesUserStatMaplck.RUnlock()

		resp.Ret = -1
	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	//	endTime := time.Now().UnixNano()
	//logs.Info(fmt.Sprintf("refreshUser recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func LoginOut(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("LoginOut recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp CommonResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req LoginOutReq
	json.Unmarshal(reqdata, &req)

	/*
		deesUserStatMaplck.Lock()
		if _, ok := deesUserStatMap[req.Username]; ok {
			delete(deesUserStatMap, req.Username)
		}
		deesUserStatMaplck.Unlock()
	*/
	resp.Ret = 0

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("LoginOut recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func Login(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("Login recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req LoginReq
	var resp LoginResp
	var err error
	var uuid string

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)
	userinfo, err := getUserInfo(req.Username)
	if err != nil {
		resp.Ret = -1
		logs.Error("login::getUserInfo err:", err.Error())
		goto exit
	}

	deesUserStatMaplck.RLock()
	if v, ok := deesUserStatMap[req.Username]; ok {
		deesUserStatMaplck.RUnlock()

		v.RLock()
		uuid = v.Uuid

		if time.Now().Before(v.ExpireTime) {
			refreshTime := v.RefreshTime
			v.RUnlock()

			if int64(time.Since(refreshTime).Seconds()) <= refreshSpan {
				resp.Ret = 1
				goto exit
			}

			//online user nojust refresh
			//...
		} else {
			v.RUnlock()
		}

		uuid = getUuid()

	} else {
		deesUserStatMaplck.RUnlock()

		uuid = getUuid()
	}

	if req.Password != userinfo.Password {
		resp.Ret = -1
		goto exit
	}

exit:

	if resp.Ret == 0 {

		resp.RoleId = userinfo.RoleId
		resp.DId = userinfo.DepartmentId

		//refresh user state
		var v DeesUserStat
		v.Username = req.Username
		v.RefreshTime = time.Now()
		v.ExpireTime = time.Now().Add(ExpireTimeSpan)
		v.Uuid = uuid
		v.UserRole = userinfo.RoleId

		resp.Uuid = uuid

		deesUserStatMaplck.Lock()
		deesUserStatMap[req.Username] = &v
		deesUserStatMaplck.Unlock()
	}

	if userinfo.DepartmentId == 9 {
		resp.Url = "main1.html"
	} else {
		resp.Url = "main.html"
	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("Login recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

// ============ 日志操作 start ==================
func add_operation_log(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("add_operation_log recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req AddOperationLogReq
	var resp AddOperationLogResp

	var sqlstr string
	var err error

	// 获取当前时间
	currentTime := time.Now()
	// 格式化时间
	formattedTime := currentTime.Format("2006-01-02 15:04:05")

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	sqlstr = fmt.Sprintf(`INSERT INTO [operation_log] ([username],[operation],[operation_time]) VALUES ('%s','%s','%s')`, req.OpUser, req.Operation, formattedTime)
	fmt.Println(sqlstr)

	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("add_operation_log Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))
	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("add_operation_log recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func get_operation_log(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("get_operation_log recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req GetOperationLogReq
	var resp GetOperationLogResp

	var sqlstr string
	var rcnt int
	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	if req.Username == "" {
		sqlstr = "select count(ID) from [operation_log] "
	} else {
		likeStr := req.Username
		sqlstr = fmt.Sprintf("select count(ID) from [operation_log] where username IN %s", likeStr)
	}
	fmt.Println(sqlstr)

	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_operation_log query %s err:%v", sqlstr, err.Error()))
		goto exit
	}
	defer cntRow.Close()

	for cntRow.Next() {
		if err = cntRow.Scan(&rcnt); err != nil {
			logs.Error(fmt.Sprintf("get_operation_log scan %s err:%v", sqlstr, err.Error()))
			goto exit
		}
	}
	resp.Total = rcnt

	if req.Username == "" {
		sqlstr = fmt.Sprintf("select top %v [ID],[username],[operation],[operation_time] from [operation_log] where ID not in (select top %v ID from [operation_log] order by ID desc) order by ID desc", req.Count, (req.Index-1)*req.Count)
	} else {
		likeStr := req.Username
		sqlstr = fmt.Sprintf("select top %v [ID],[username],[operation],[operation_time] from [operation_log] where username IN %s and ID not in (select top %v ID from [operation_log] where username IN %s order by ID desc) order by ID desc", req.Count, likeStr, (req.Index-1)*req.Count, likeStr)
	}
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_operation_log Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d LogInfo
		if err := rdRow.Scan(&d.ID, &d.Username, &d.Operation, &d.OperationTime); err == nil {
			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_operation_log scan Error", err.Error())
		}
	}

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))
	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_operation_log recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func del_operation_log(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("del_operation_log recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req DelOperationLogReq
	var resp DelOperationLogResp

	var sqlstr string
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	sqlstr = fmt.Sprintf("delete from [operation_log] where ID = %v", req.ID) //fmt.Println(sqlstr)

	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("del_operation_log Exec err:%v", err.Error()))
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))
	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("del_operation_log recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

// 获取所有日志用户名
func get_operation_log_user(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("get_operation_log_user recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp GetOperationLogUserResp

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	sqlstr = "select distinct username from [operation_log] "
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_operation_log_user Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d string
		if err := rdRow.Scan(&d); err == nil {
			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_operation_log_user scan Error", err.Error())
		}
	}
	resp.Ret = 0

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))
	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_operation_log_user recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func export_operation_log(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("export_operation_log recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var csv_data [][]string
	filename := fmt.Sprintf(`./file/%v.csv`, "export_operation_log")
	f, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	var req GetOperationLogReq
	var resp download_file_Resp

	var log_data []LogInfo

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	var sqlstr string

	if req.Username == "" {
		sqlstr = "select [ID],[username],[operation],[operation_time] from [operation_log] order by ID desc"
	} else {
		likeStr := req.Username
		sqlstr = fmt.Sprintf("select [ID],[username],[operation],[operation_time] from [operation_log] where username IN %s order by ID desc", likeStr)
	}
	fmt.Println(sqlstr)

	rdRow, err := sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("export_operation_log Query err:%v", err.Error()))
		return
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d LogInfo
		if err := rdRow.Scan(&d.ID, &d.Username, &d.Operation, &d.OperationTime); err == nil {
			log_data = append(log_data, d)
		} else {
			logs.Error("export_operation_log scan Error", err.Error())
		}
	}

	csv_data = append(csv_data, []string{"用户名", "操作时间", "操作记录"})

	for _, v := range log_data {
		csv_data = append(csv_data, []string{v.Username, v.OperationTime, v.Operation})
	}

	f.WriteString("\xEF\xBB\xBF") // 写入一个UTF-8 BOM 防止中文乱码
	w := csv.NewWriter(f)         //创建一个新的写入文件流
	w.WriteAll(csv_data)
	w.Flush()
	resp.FileId = fmt.Sprintf(`%v.csv`, "export_operation_log")

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("export_operation_log recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func getPrePlanMess(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	var req getPrePlanMessReq
	var resp getPrePlanMessResp
	var usrinfo useInfo
	var err error // 修复：声明 err 变量
	var name string

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	logs.Info(string(reqdata))

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		logs.Info(fmt.Sprintf("用户%s不在线", req.OpUser))
		goto exit
	}

	usrinfo, err = getUserInfo(req.OpUser)
	name = usrinfo.Username
	if err != nil {
		logs.Error("getPrePlanMess getUserInfo err:", err.Error())
		resp.Ret = -1
		goto exit
	}

	// TODO: 添加获取前置计划消息的业务逻辑
	if name == "尚永强" {
		var sqlstr = "select count([ID]) from [pre_plan] where [promise_date] IS NULL or promise_date = '' and commit_flag = '0' and del_flag = '0'"
		fmt.Println(sqlstr)

		rdRow, err := sqlConn.Query(sqlstr)
		if err != nil {
			logs.Error(fmt.Sprintf("查询条数出错:%v", err.Error()))
			return
		}
		defer rdRow.Close()

		// 读取查询结果
		var count int
		if rdRow.Next() {
			err = rdRow.Scan(&count)
			if err != nil {
				logs.Error(fmt.Sprintf("读取查询结果出错:%v", err.Error()))
				return
			}
		}
		if count > 0 {
			resp.Mess = fmt.Sprintf("您当前有 %d 条未回复的前置计划，请及时处理!", count)
		} else {
			resp.Mess = " "
			// 或者直接不设置 resp.Mess，让前端根据 Mess 是否为空来判断
		}

		// 设置返回消息
	}
	resp.Ret = 0

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("getPrePlanMess recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func ConfirmBaseData(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("ConfirmBaseData recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp CommonResp
	var req struct {
		Ids        []int  `json:"ids"`
		OpUser     string `json:"opUser"`
		OpUserUuid string `json:"opUserUuid"`
	}

	// 提前声明所有变量
	var idsStr []string
	var idsList string
	var sqlstr string
	var jdata []byte
	var reqdata []byte
	var b bool
	var err error

	// 初始化响应，确保总是有值
	resp.Ret = -1 // 默认失败

	reqdata, err = ioutil.ReadAll(request.Body)
	if err != nil {
		logs.Error("ConfirmBaseData ReadAll Error:", err.Error())
		goto exit
	}

	err = json.Unmarshal(reqdata, &req)
	if err != nil {
		logs.Error("ConfirmBaseData Unmarshal Error:", err.Error())
		goto exit
	}

	b = checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if len(req.Ids) == 0 {
		goto exit
	}

	// 构造IN查询语句
	idsStr = make([]string, 0, len(req.Ids))
	for _, id := range req.Ids {
		idsStr = append(idsStr, strconv.Itoa(id))
	}
	idsList = strings.Join(idsStr, ",")

	sqlstr = fmt.Sprintf("UPDATE [sap] SET [flag] = 1 WHERE [ID] IN (%s)", idsList)

	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Error("ConfirmBaseData Exec Error:", err.Error())
		fmt.Println("ConfirmBaseData Exec Error:", err.Error())
		goto exit
	}

	resp.Ret = 0

exit:
	jdata, _ = json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("ConfirmBaseData recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

// ================== 日志操作 end ==============================

// 跨域测试
func test(response http.ResponseWriter, request *http.Request) {
	fmt.Println("recv test req")

	response.Header().Set("Access-Control-Allow-Origin", "*")             //允许访问所有域
	response.Header().Add("Access-Control-Allow-Headers", "Content-Type") //header的类型
	response.Header().Set("content-type", "application/json")             //返回数据格式是json

	fmt.Fprintf(response, "3")

}
