Tinger 1 年之前
父节点
当前提交
9c8cc228a9
共有 45 个文件被更改,包括 1522 次插入298 次删除
  1. 12 1
      handlers/manager/admin/trade/handler.go
  2. 21 0
      handlers/manager/admin/trade/params.go
  3. 85 0
      handlers/manager/admin/trade/worker.go
  4. 15 1
      handlers/manager/admin/worker/handler.go
  5. 20 0
      handlers/manager/admin/worker/params.go
  6. 115 0
      handlers/manager/admin/worker/worker.go
  7. 13 15
      handlers/manager/super/config/advertise/params.go
  8. 57 41
      handlers/manager/super/config/advertise/worker.go
  9. 1 1
      handlers/manager/super/config/device/worker.go
  10. 8 0
      handlers/manager/super/config/handler.go
  11. 7 0
      handlers/manager/super/config/param/params.go
  12. 65 0
      handlers/manager/super/config/param/worker.go
  13. 13 13
      handlers/manager/super/config/wine/params.go
  14. 8 5
      handlers/manager/super/config/wine/worker.go
  15. 26 0
      handlers/manager/super/order/change/params.go
  16. 14 0
      handlers/manager/super/order/change/worker.go
  17. 22 1
      handlers/manager/super/order/handler.go
  18. 21 0
      handlers/manager/super/order/trade/params.go
  19. 101 0
      handlers/manager/super/order/trade/worker.go
  20. 20 0
      handlers/manager/super/role/admin/params.go
  21. 121 0
      handlers/manager/super/role/admin/worker.go
  22. 23 2
      handlers/manager/super/role/handler.go
  23. 8 0
      handlers/manager/super/role/worker/params.go
  24. 31 0
      handlers/manager/super/role/worker/worker.go
  25. 1 1
      handlers/seller/params.go
  26. 4 2
      handlers/seller/worker.go
  27. 3 1
      handlers/setup.go
  28. 二进制
      static/adv/20230929.mp4
  29. 二进制
      static/adv/20230931.mp4
  30. 二进制
      static/images/wine/10104.png
  31. 二进制
      static/images/wine/10105.png
  32. 二进制
      static/images/wine/10106.png
  33. 二进制
      static/images/wine/10107.png
  34. 10 7
      utils/lib.go
  35. 16 24
      utils/tables/advertise.go
  36. 7 24
      utils/tables/device.go
  37. 64 43
      utils/tables/manager.go
  38. 71 0
      utils/tables/operation.go
  39. 27 26
      utils/tables/params.go
  40. 73 0
      utils/tables/refund.go
  41. 71 46
      utils/tables/trade.go
  42. 137 0
      utils/tables/user.go
  43. 6 24
      utils/tables/version.go
  44. 5 20
      utils/tables/wine.go
  45. 200 0
      utils/tables/worker.go

+ 12 - 1
handlers/manager/admin/trade/handler.go

@@ -8,6 +8,17 @@ import (
 
 func Handle(msg utils.WsMsg, conn *websocket.Conn, manager *tables.ManagerTable) {
 	switch msg.Event {
-
+	case "adminTradeQueryUser":
+		queryUser(conn, msg.Data)
+		break
+	case "adminTradeQueryTrade":
+		queryTrade(conn, msg.Data)
+		break
+	case "adminTradeRefund":
+		refund(conn, manager, msg.Data)
+		break
+	default:
+		_ = conn.WriteJSON(utils.WsError("unrecognized event"))
+		break
 	}
 }

+ 21 - 0
handlers/manager/admin/trade/params.go

@@ -0,0 +1,21 @@
+package trade
+
+type queryUserParam struct {
+	Id    string `json:"id"`
+	Vip   int    `json:"vip"`
+	Page  int    `json:"page"`
+	Limit int    `json:"limit"`
+}
+
+type queryTradeParam struct {
+	Cond  string `json:"cond"`
+	Uid   string `json:"uid"`
+	Page  int    `json:"page"`
+	Limit int    `json:"limit"`
+}
+
+type refundParam struct {
+	Tid    string `json:"tid"`
+	Cash   uint32 `json:"cash"`
+	Reason string `json:"reason"`
+}

+ 85 - 0
handlers/manager/admin/trade/worker.go

@@ -0,0 +1,85 @@
+package trade
+
+import (
+	"Wine-Server/utils"
+	"Wine-Server/utils/tables"
+	"github.com/gorilla/websocket"
+)
+
+// queryUser @super.order.QueryUser
+func queryUser(conn *websocket.Conn, data any) {
+	var param queryUserParam
+	err := utils.AnyTrans(data, &param)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminTradeQueryUserRes", utils.Fail("参数错误")))
+		return
+	}
+	total, users, err := tables.UserQuery(param.Id, param.Vip, param.Limit, param.Page)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminTradeQueryUserRes", utils.Fail("查询用户失败")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent(
+		"adminTradeQueryUserRes",
+		utils.Success(utils.JsonType{"total": total, "list": users}),
+	))
+}
+
+// queryTrade @super.order.QueryTrade
+func queryTrade(conn *websocket.Conn, data any) {
+	var param queryTradeParam
+	err := utils.AnyTrans(data, &param)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminTradeQueryTradeRes", utils.Fail("参数错误")))
+		return
+	}
+	total, trades, err := tables.TradeQuery(param.Cond, param.Uid, param.Limit, param.Page)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminTradeQueryTradeRes", utils.Fail("查询订单失败")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent(
+		"adminTradeQueryTradeRes",
+		utils.Success(utils.JsonType{"total": total, "list": trades}),
+	))
+}
+
+// refund @super.order.Refund
+func refund(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+	var param refundParam
+	err := utils.AnyTrans(data, &param)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminTradeRefundRes", utils.Fail("参数错误")))
+		return
+	}
+	trade := tables.TradeTable{Id: param.Tid}
+	err = trade.Get()
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminTradeRefundRes", utils.Fail("订单查询失败")))
+		return
+	}
+	if trade.Cash < param.Cash {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminTradeRefundRes", utils.Fail("超出原订单金额")))
+		return
+	}
+	refund := tables.RefundTable{Tid: param.Tid, Manager: manager.Id, Cash: param.Cash, Reason: param.Reason}
+	err = refund.Insert()
+	if err != nil {
+		err = refund.Get()
+		refund.Manager, refund.Cash, refund.Reason = manager.Id, param.Cash, param.Reason
+		err = refund.UpdateSelf()
+	}
+	_ = conn.WriteJSON(utils.WsEvent("adminTradeRefundRes", utils.Success(nil)))
+	// update user table
+	user := tables.UserTable{Id: trade.Payer}
+	_ = user.Get()
+	user.RefundCount++
+	user.RefundCost += uint64(param.Cash)
+}

+ 15 - 1
handlers/manager/admin/worker/handler.go

@@ -8,6 +8,20 @@ import (
 
 func Handle(msg utils.WsMsg, conn *websocket.Conn, manager *tables.ManagerTable) {
 	switch msg.Event {
-
+	case "adminWorkerQuery":
+		query(conn, manager, msg.Data)
+		break
+	case "adminWorkerUpdate":
+		update(conn, msg.Data)
+		break
+	case "adminWorkerDelete":
+		remove(conn, msg.Data)
+		break
+	case "adminWorkerAdd":
+		add(conn, manager, msg.Data)
+		break
+	default:
+		_ = conn.WriteJSON(utils.WsError("unrecognized event"))
+		break
 	}
 }

+ 20 - 0
handlers/manager/admin/worker/params.go

@@ -0,0 +1,20 @@
+package worker
+
+type queryParam struct {
+	Cond  string `json:"cond"`
+	Page  int    `json:"page"`
+	Limit int    `json:"limit"`
+}
+
+type updateParam struct {
+	Id       string `json:"id"`
+	Name     string `json:"name"`
+	Phone    string `json:"phone"`
+	Password string `json:"password"`
+}
+
+type addParam struct {
+	Name     string `json:"name"`
+	Phone    string `json:"phone"`
+	Password string `json:"password"`
+}

+ 115 - 0
handlers/manager/admin/worker/worker.go

@@ -0,0 +1,115 @@
+package worker
+
+import (
+	"Wine-Server/utils"
+	"Wine-Server/utils/tables"
+	"github.com/gorilla/websocket"
+)
+
+func query(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+	var param queryParam
+	err := utils.AnyTrans(data, &param)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminWorkerQueryRes", utils.Fail("参数错误")))
+		return
+	}
+	total, workers, err := tables.WorkerQueryForAdmin(manager.Id, param.Cond, param.Limit, param.Page)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminWorkerQueryRes", utils.Fail("查询上酒工失败")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent(
+		"adminWorkerQueryRes",
+		utils.Success(utils.JsonType{"total": total, "list": workers}),
+	))
+}
+
+func update(conn *websocket.Conn, data any) {
+	var param updateParam
+	err := utils.AnyTrans(data, &param)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminWorkerUpdateRes", utils.Fail("参数错误")))
+		return
+	}
+	if param.Phone == "" {
+		_ = conn.WriteJSON(utils.WsEvent("adminWorkerUpdateRes", utils.Fail("联系电话不可为空")))
+		return
+	}
+	worker := tables.WorkerTable{Id: param.Id}
+	err = worker.Get()
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminWorkerUpdateRes", utils.Fail("更新失败 01")))
+		return
+	}
+	if param.Password != "" {
+		password, err := utils.Decrypt(param.Password)
+		if err != nil {
+			utils.Logger.Println(err)
+			_ = conn.WriteJSON(utils.WsEvent("adminWorkerUpdateRes", utils.Fail("解密失败")))
+			return
+		}
+		worker.Password = utils.HashPassword(password)
+	}
+	worker.Name, worker.Phone = param.Name, param.Phone
+	err = worker.UpdateSelf()
+	if err != nil {
+		_ = conn.WriteJSON(utils.WsEvent("adminWorkerUpdateRes", utils.Fail("更新失败 02")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent("adminWorkerUpdateRes", utils.Success(nil)))
+	// TODO: inform worker login expired
+}
+
+func remove(conn *websocket.Conn, data any) {
+	var ids []string
+	err := utils.AnyTrans(data, &ids)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminWorkerDeleteRes", utils.Fail("参数错误")))
+		return
+	}
+	err = tables.WorkersDelete(ids)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminWorkerDeleteRes", utils.Fail("删除失败")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent("adminWorkerDeleteRes", utils.Success(nil)))
+}
+
+func add(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+	var param addParam
+	err := utils.AnyTrans(data, &param)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminWorkerAddRes", utils.Fail("参数错误")))
+		return
+	}
+	if param.Name == "" || param.Phone == "" || param.Password == "" {
+		_ = conn.WriteJSON(utils.WsEvent("adminWorkerAddRes", utils.Fail("数据不可为空")))
+		return
+	}
+	var password string
+	password, err = utils.Decrypt(param.Password)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminWorkerAddRes", utils.Fail("解密失败")))
+		return
+	}
+	id := utils.RandomString(16, utils.AlphaNumPatten)
+	worker := &tables.WorkerTable{
+		Id: id, Name: param.Name, Phone: param.Phone,
+		Password: utils.HashPassword(password), Manager: manager.Id,
+	}
+	err = worker.Insert()
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("adminWorkerAddRes", utils.Fail("添加失败")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent("adminWorkerAddRes", utils.Success(nil)))
+}

+ 13 - 15
handlers/manager/super/config/advertise/params.go

@@ -7,21 +7,19 @@ type queryParam struct {
 	Limit int    `json:"limit"`
 }
 
-type addParam struct {
-	Name     string
-	Price    uint16
-	Degree   uint16
-	Density  uint16
-	Image    string
-	Describe string
+type updateParam struct {
+	Id       uint32 `json:"id"`
+	Order    uint8  `json:"order"`
+	Base64   string `json:"base64"`
+	Type     bool   `json:"type"`
+	Duration uint16 `json:"duration"`
+	Describe string `json:"describe"`
 }
 
-type updateParam struct {
-	Id       uint16
-	Name     string
-	Price    uint16
-	Degree   uint16
-	Density  uint16
-	Image    string
-	Describe string
+type addParam struct {
+	Order    uint8  `json:"order"`
+	Base64   string `json:"base64"`
+	Type     bool   `json:"type"`
+	Duration uint16 `json:"duration"`
+	Describe string `json:"describe"`
 }

+ 57 - 41
handlers/manager/super/config/advertise/worker.go

@@ -70,81 +70,97 @@ func Delete(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
 		return
 	}
 	_ = conn.WriteJSON(utils.WsEvent("superConfigAdvertiseDeleteRes", utils.Success(nil)))
+	go informDevices()
 }
 
-// Add TODO: below
-func Add(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+func Update(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
 	if !manager.Super {
 		_ = conn.WriteJSON(utils.WsError("auth failed."))
 		return
 	}
-	var param addParam
+	var param updateParam
 	err := utils.AnyTrans(data, &param)
 	if err != nil {
 		_ = conn.WriteJSON(utils.WsError("param error"))
 		return
 	}
-	if param.Image == "" {
-		_ = conn.WriteJSON(utils.WsEvent("superConfigWineAddRes", utils.Fail("图片数据不可为空")))
-		return
-	}
-	var id uint16
-	id, err = tables.WineQueryMaxId()
-	if err != nil {
-		_ = conn.WriteJSON(utils.WsEvent("superConfigWineAddRes", utils.Fail("添加失败 01")))
-		return
-	}
-	var reason string
-	reason, err = utils.SaveBase64(param.Image, utils.Format("static/images/wine/%d.png", id))
+	adv := tables.AdvertiseTable{Id: param.Id}
+	err = adv.Get()
 	if err != nil {
-		_ = conn.WriteJSON(utils.WsEvent("superConfigWineAddRes", utils.Fail(reason)))
+		_ = conn.WriteJSON(utils.WsEvent("superConfigAdvertiseUpdateRes", utils.Fail("no such advertise")))
 		return
 	}
-	wine := tables.WineTable{
-		Id: id + 1, Name: param.Name, Price: param.Price, Degree: param.Degree,
-		Density: param.Density, Describe: param.Describe,
-		Picture: utils.Format("%s/static/images/wine/%d.png", utils.ServerPrefix, id),
+	if param.Base64 != "" {
+		var ext string
+		var reason string
+		ext, reason, err = utils.SaveBase64(param.Base64, utils.Format("static/adv/%d", param.Id))
+		if err != nil {
+			_ = conn.WriteJSON(utils.WsEvent("superConfigAdvertiseUpdateRes", utils.Fail(reason)))
+			return
+		}
+		adv.Src = utils.Format("%s/static/adv/%d.%s", utils.ServerPrefix, param.Id, ext)
 	}
-	err = wine.Insert()
+	adv.Order, adv.Type, adv.Time = param.Order, param.Type, utils.TimeNow()
+	adv.Duration, adv.Describe = param.Duration, param.Describe
+	err = adv.UpdateSelf()
 	if err != nil {
-		_ = conn.WriteJSON(utils.WsEvent("superConfigWineAddRes", utils.Fail("添加失败 02")))
+		_ = conn.WriteJSON(utils.WsEvent("superConfigAdvertiseUpdateRes", utils.Fail("更新失败")))
 		return
 	}
-	_ = conn.WriteJSON(utils.WsEvent("superConfigWineAddRes", utils.Success(nil)))
+	_ = conn.WriteJSON(utils.WsEvent("superConfigAdvertiseUpdateRes", utils.Success(nil)))
+	go informDevices()
 }
 
-func Update(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+func Add(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
 	if !manager.Super {
 		_ = conn.WriteJSON(utils.WsError("auth failed."))
 		return
 	}
-	var param updateParam
+	var param addParam
 	err := utils.AnyTrans(data, &param)
 	if err != nil {
 		_ = conn.WriteJSON(utils.WsError("param error"))
 		return
 	}
-	wine := tables.WineTable{Id: param.Id}
-	err = wine.Get()
+	if param.Base64 == "" {
+		_ = conn.WriteJSON(utils.WsEvent("superConfigAdvertiseAddRes", utils.Fail("资源不可为空")))
+		return
+	}
+	var id uint32
+	id, err = tables.AdvertiseQueryMaxId()
 	if err != nil {
-		_ = conn.WriteJSON(utils.WsEvent("superConfigWineUpdateRes", utils.Fail("no such wine")))
+		_ = conn.WriteJSON(utils.WsEvent("superConfigAdvertiseAddRes", utils.Fail("添加失败 01")))
 		return
 	}
-	if param.Image != "" {
-		var reason string
-		reason, err = utils.SaveBase64(param.Image, utils.Format("static/images/wine/%d.png", param.Id))
-		if err != nil {
-			_ = conn.WriteJSON(utils.WsEvent("superConfigWineUpdateRes", utils.Fail(reason)))
-			return
-		}
-		wine.Picture = utils.Format("%s/static/images/wine/%d.png", utils.ServerPrefix, param.Id)
+	id++
+	var ext string
+	var reason string
+	ext, reason, err = utils.SaveBase64(param.Base64, utils.Format("static/adv/%d", id))
+	if err != nil {
+		_ = conn.WriteJSON(utils.WsEvent("superConfigAdvertiseAddRes", utils.Fail(reason)))
+		return
 	}
-	wine.Name, wine.Price, wine.Degree = param.Name, param.Price, param.Degree
-	wine.Density, wine.Describe = param.Density, param.Describe
-	err = wine.UpdateSelf()
+	adv := tables.AdvertiseTable{
+		Id: id, Order: param.Order, Type: param.Type, Duration: param.Duration, Describe: param.Describe,
+		Src: utils.Format("%s/static/adv/%d.%s", utils.ServerPrefix, id, ext),
+	}
+	err = adv.Insert()
+	if err != nil {
+		_ = conn.WriteJSON(utils.WsEvent("superConfigAdvertiseAddRes", utils.Fail("添加失败 02")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent("superConfigAdvertiseAddRes", utils.Success(nil)))
+	go informDevices()
+}
+
+func informDevices() {
+	ads, err := tables.AdvertiseListAll()
 	if err != nil {
-		_ = conn.WriteJSON(utils.WsEvent("superConfigWineUpdateRes", utils.Fail("更新失败")))
 		return
 	}
-	_ = conn.WriteJSON(utils.WsEvent("superConfigWineUpdateRes", utils.Success(nil)))
+	for _, item := range utils.SellerDevices {
+		if item.Online {
+			_ = item.Conn.WriteJSON(utils.WsEvent("advertiseUpdate", ads))
+		}
+	}
 }

+ 1 - 1
handlers/manager/super/config/device/worker.go

@@ -12,7 +12,7 @@ func QueryManager(conn *websocket.Conn, manager *tables.ManagerTable, data any)
 		return
 	}
 	name, _ := data.(string)
-	res, err := tables.QueryManager(name)
+	res, err := tables.ManagerQuery(name)
 	if err != nil {
 		utils.Logger.Println(err)
 		_ = conn.WriteJSON(utils.WsError("query manager failed"))

+ 8 - 0
handlers/manager/super/config/handler.go

@@ -3,6 +3,7 @@ package config
 import (
 	"Wine-Server/handlers/manager/super/config/advertise"
 	"Wine-Server/handlers/manager/super/config/device"
+	"Wine-Server/handlers/manager/super/config/param"
 	"Wine-Server/handlers/manager/super/config/wine"
 	"Wine-Server/utils"
 	"Wine-Server/utils/tables"
@@ -50,6 +51,13 @@ func Handle(msg utils.WsMsg, conn *websocket.Conn, manager *tables.ManagerTable)
 	case "superConfigAdvertiseAdd":
 		advertise.Add(conn, manager, msg.Data)
 		break
+	// param:
+	case "superConfigParamList":
+		param.List(conn, manager, msg.Data)
+		break
+	case "superConfigParamUpdate":
+		param.Update(conn, manager, msg.Data)
+		break
 	default:
 		_ = conn.WriteJSON(utils.WsError("unrecognized event"))
 		break

+ 7 - 0
handlers/manager/super/config/param/params.go

@@ -0,0 +1,7 @@
+package param
+
+type updateParam struct {
+	Id    uint32 `json:"id"`
+	Name  string `json:"name"`
+	Value uint32 `json:"value"`
+}

+ 65 - 0
handlers/manager/super/config/param/worker.go

@@ -0,0 +1,65 @@
+package param
+
+import (
+	"Wine-Server/utils"
+	"Wine-Server/utils/tables"
+	"github.com/gorilla/websocket"
+)
+
+func List(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+	if !manager.Super {
+		_ = conn.WriteJSON(utils.WsError("auth failed."))
+		return
+	}
+	list, err := tables.ParamsListAllForSuper()
+	if err != nil {
+		_ = conn.WriteJSON(utils.WsEvent("superConfigParamListRes", utils.Fail("查询参数失败")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent("superConfigParamListRes", utils.Success(list)))
+}
+
+func Update(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+	if !manager.Super {
+		_ = conn.WriteJSON(utils.WsError("auth failed."))
+		return
+	}
+	var params []updateParam
+	err := utils.AnyTrans(data, &params)
+	if err != nil {
+		_ = conn.WriteJSON(utils.WsError("param error"))
+		return
+	}
+	for _, param := range params {
+		if param.Name == "" {
+			_ = conn.WriteJSON(utils.WsEvent("superConfigParamUpdateRes", utils.Fail("参数名不可为空")))
+			return
+		}
+		pra := tables.ParamsTable{Id: param.Id}
+		err = pra.Get()
+		if err != nil {
+			_ = conn.WriteJSON(utils.WsEvent("superConfigParamUpdateRes", utils.Fail("no such param")))
+			return
+		}
+		pra.Describe, pra.Value = param.Name, param.Value
+		err = pra.UpdateSelf()
+		if err != nil {
+			_ = conn.WriteJSON(utils.WsEvent("superConfigParamUpdateRes", utils.Fail("更新失败")))
+			return
+		}
+	}
+	_ = conn.WriteJSON(utils.WsEvent("superConfigParamUpdateRes", utils.Success(nil)))
+	go informDevices()
+}
+
+func informDevices() {
+	pra, err := tables.ParamsListAll()
+	if err != nil {
+		return
+	}
+	for _, item := range utils.SellerDevices {
+		if item.Online {
+			_ = item.Conn.WriteJSON(utils.WsEvent("paramsUpdate", pra))
+		}
+	}
+}

+ 13 - 13
handlers/manager/super/config/wine/params.go

@@ -7,20 +7,20 @@ type queryParam struct {
 }
 
 type addParam struct {
-	Name     string
-	Price    uint16
-	Degree   uint16
-	Density  uint16
-	Image    string
-	Describe string
+	Name     string `json:"name"`
+	Price    uint16 `json:"price"`
+	Degree   uint16 `json:"degree"`
+	Density  uint16 `json:"density"`
+	Image    string `json:"image"`
+	Describe string `json:"describe"`
 }
 
 type updateParam struct {
-	Id       uint16
-	Name     string
-	Price    uint16
-	Degree   uint16
-	Density  uint16
-	Image    string
-	Describe string
+	Id       uint16 `json:"id"`
+	Name     string `json:"name"`
+	Price    uint16 `json:"price"`
+	Degree   uint16 `json:"degree"`
+	Density  uint16 `json:"density"`
+	Image    string `json:"image"`
+	Describe string `json:"describe"`
 }

+ 8 - 5
handlers/manager/super/config/wine/worker.go

@@ -67,16 +67,18 @@ func Add(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
 		_ = conn.WriteJSON(utils.WsEvent("superConfigWineAddRes", utils.Fail("添加失败 01")))
 		return
 	}
+	id++
+	var ext string
 	var reason string
-	reason, err = utils.SaveBase64(param.Image, utils.Format("static/images/wine/%d.png", id))
+	ext, reason, err = utils.SaveBase64(param.Image, utils.Format("static/wine/%d", id))
 	if err != nil {
 		_ = conn.WriteJSON(utils.WsEvent("superConfigWineAddRes", utils.Fail(reason)))
 		return
 	}
 	wine := tables.WineTable{
-		Id: id + 1, Name: param.Name, Price: param.Price, Degree: param.Degree,
+		Id: id, Name: param.Name, Price: param.Price, Degree: param.Degree,
 		Density: param.Density, Describe: param.Describe,
-		Picture: utils.Format("%s/static/images/wine/%d.png", utils.ServerPrefix, id),
+		Picture: utils.Format("%s/static/wine/%d.%s", utils.ServerPrefix, id, ext),
 	}
 	err = wine.Insert()
 	if err != nil {
@@ -104,13 +106,14 @@ func Update(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
 		return
 	}
 	if param.Image != "" {
+		var ext string
 		var reason string
-		reason, err = utils.SaveBase64(param.Image, utils.Format("static/images/wine/%d.png", param.Id))
+		ext, reason, err = utils.SaveBase64(param.Image, utils.Format("static/wine/%d", param.Id))
 		if err != nil {
 			_ = conn.WriteJSON(utils.WsEvent("superConfigWineUpdateRes", utils.Fail(reason)))
 			return
 		}
-		wine.Picture = utils.Format("%s/static/images/wine/%d.png", utils.ServerPrefix, param.Id)
+		wine.Picture = utils.Format("%s/static/wine/%d.%s", utils.ServerPrefix, param.Id, ext)
 	}
 	wine.Name, wine.Describe = param.Name, param.Describe
 	wine.Price, wine.Degree, wine.Density = param.Price, param.Degree, param.Density

+ 26 - 0
handlers/manager/super/order/change/params.go

@@ -0,0 +1,26 @@
+package change
+
+type queryParam struct {
+	Cond  string `json:"cond"`
+	Page  int    `json:"page"`
+	Limit int    `json:"limit"`
+}
+
+type addParam struct {
+	Name     string `json:"name"`
+	Price    uint16 `json:"price"`
+	Degree   uint16 `json:"degree"`
+	Density  uint16 `json:"density"`
+	Image    string `json:"image"`
+	Describe string `json:"describe"`
+}
+
+type updateParam struct {
+	Id       uint16 `json:"id"`
+	Name     string `json:"name"`
+	Price    uint16 `json:"price"`
+	Degree   uint16 `json:"degree"`
+	Density  uint16 `json:"density"`
+	Image    string `json:"image"`
+	Describe string `json:"describe"`
+}

+ 14 - 0
handlers/manager/super/order/change/worker.go

@@ -0,0 +1,14 @@
+package change
+
+import (
+	"Wine-Server/utils/tables"
+	"github.com/gorilla/websocket"
+)
+
+func QueryWorker(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+
+}
+
+func QueryOrder(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+
+}

+ 22 - 1
handlers/manager/super/order/handler.go

@@ -1,6 +1,8 @@
 package order
 
 import (
+	"Wine-Server/handlers/manager/super/order/change"
+	"Wine-Server/handlers/manager/super/order/trade"
 	"Wine-Server/utils"
 	"Wine-Server/utils/tables"
 	"github.com/gorilla/websocket"
@@ -8,6 +10,25 @@ import (
 
 func Handle(msg utils.WsMsg, conn *websocket.Conn, manager *tables.ManagerTable) {
 	switch msg.Event {
-
+	// trade:
+	case "superOrderTradeQueryUser":
+		trade.QueryUser(conn, manager, msg.Data)
+		break
+	case "superOrderTradeQueryTrade":
+		trade.QueryTrade(conn, manager, msg.Data)
+		break
+	case "superOrderTradeRefund":
+		trade.Refund(conn, manager, msg.Data)
+		break
+	// order:
+	case "superOrderChangeQueryWorker":
+		change.QueryWorker(conn, manager, msg.Data)
+		break
+	case "superOrderChangeQueryOrder":
+		change.QueryOrder(conn, manager, msg.Data)
+		break
+	default:
+		_ = conn.WriteJSON(utils.WsError("unrecognized event"))
+		break
 	}
 }

+ 21 - 0
handlers/manager/super/order/trade/params.go

@@ -0,0 +1,21 @@
+package trade
+
+type queryUserParam struct {
+	Id    string `json:"id"`
+	Vip   int    `json:"vip"`
+	Page  int    `json:"page"`
+	Limit int    `json:"limit"`
+}
+
+type queryTradeParam struct {
+	Cond  string `json:"cond"`
+	Uid   string `json:"uid"`
+	Page  int    `json:"page"`
+	Limit int    `json:"limit"`
+}
+
+type refundParam struct {
+	Tid    string `json:"tid"`
+	Cash   uint32 `json:"cash"`
+	Reason string `json:"reason"`
+}

+ 101 - 0
handlers/manager/super/order/trade/worker.go

@@ -0,0 +1,101 @@
+package trade
+
+import (
+	"Wine-Server/utils"
+	"Wine-Server/utils/tables"
+	"github.com/gorilla/websocket"
+)
+
+// QueryUser @admin.trade.queryUser
+func QueryUser(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+	if !manager.Super {
+		_ = conn.WriteJSON(utils.WsEvent("superOrderTradeQueryUserRes", utils.Fail("权限不足")))
+		return
+	}
+	var param queryUserParam
+	err := utils.AnyTrans(data, &param)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superOrderTradeQueryUserRes", utils.Fail("参数错误")))
+		return
+	}
+	total, users, err := tables.UserQuery(param.Id, param.Vip, param.Limit, param.Page)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superOrderTradeQueryUserRes", utils.Fail("查询用户失败")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent(
+		"superOrderTradeQueryUserRes",
+		utils.Success(utils.JsonType{"total": total, "list": users}),
+	))
+}
+
+// QueryTrade @admin.trade.queryTrade
+func QueryTrade(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+	if !manager.Super {
+		_ = conn.WriteJSON(utils.WsEvent("superOrderTradeQueryTradeRes", utils.Fail("权限不足")))
+		return
+	}
+	var param queryTradeParam
+	err := utils.AnyTrans(data, &param)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superOrderTradeQueryTradeRes", utils.Fail("参数错误")))
+		return
+	}
+	total, trades, err := tables.TradeQuery(param.Cond, param.Uid, param.Limit, param.Page)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superOrderTradeQueryTradeRes", utils.Fail("查询订单失败")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent(
+		"superOrderTradeQueryTradeRes",
+		utils.Success(utils.JsonType{"total": total, "list": trades}),
+	))
+}
+
+// Refund @admin.trade.refund
+func Refund(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+	if !manager.Super {
+		_ = conn.WriteJSON(utils.WsEvent("superOrderTradeRefundRes", utils.Fail("权限不足")))
+		return
+	}
+	var param refundParam
+	err := utils.AnyTrans(data, &param)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superOrderTradeRefundRes", utils.Fail("参数错误")))
+		return
+	}
+	trade := tables.TradeTable{Id: param.Tid}
+	err = trade.Get()
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superOrderTradeRefundRes", utils.Fail("订单查询失败")))
+		return
+	}
+	if trade.Cash < param.Cash {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superOrderTradeRefundRes", utils.Fail("超出原订单金额")))
+		return
+	}
+	refund := tables.RefundTable{Tid: param.Tid, Manager: manager.Id, Cash: param.Cash, Reason: param.Reason}
+	err = refund.Insert()
+	if err != nil {
+		err = refund.Get()
+		refund.Manager, refund.Cash, refund.Reason = manager.Id, param.Cash, param.Reason
+		err = refund.UpdateSelf()
+	}
+	_ = conn.WriteJSON(utils.WsEvent("superOrderTradeRefundRes", utils.Success(nil)))
+	// update user table
+	user := tables.UserTable{Id: trade.Payer}
+	err = user.Get()
+	if err != nil {
+		utils.Logger.Println(err)
+	}
+	user.RefundCount++
+	user.RefundCost += uint64(param.Cash)
+	_ = user.UpdateSelf()
+}

+ 20 - 0
handlers/manager/super/role/admin/params.go

@@ -0,0 +1,20 @@
+package admin
+
+type queryParam struct {
+	Cond  string `json:"cond"`
+	Page  int    `json:"page"`
+	Limit int    `json:"limit"`
+}
+
+type updateParam struct {
+	Id       string `json:"id"`
+	Name     string `json:"name"`
+	Account  string `json:"account"`
+	Password string `json:"password"`
+}
+
+type addParam struct {
+	Name     string `json:"name"`
+	Account  string `json:"account"`
+	Password string `json:"password"`
+}

+ 121 - 0
handlers/manager/super/role/admin/worker.go

@@ -0,0 +1,121 @@
+package admin
+
+import (
+	"Wine-Server/utils"
+	"Wine-Server/utils/tables"
+	"github.com/gorilla/websocket"
+)
+
+func Query(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+	if !manager.Super {
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminQueryRes", utils.Fail("权限不足")))
+		return
+	}
+	var param queryParam
+	err := utils.AnyTrans(data, &param)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminQueryRes", utils.Fail("参数错误")))
+		return
+	}
+	total, men, err := tables.ManagerQueryForAdmin(param.Cond, param.Limit, param.Page)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminQueryRes", utils.Fail("查询管理员失败")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent(
+		"superRoleAdminQueryRes",
+		utils.Success(utils.JsonType{"total": total, "list": men}),
+	))
+}
+
+func Update(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+	if !manager.Super {
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminUpdateRes", utils.Fail("权限不足")))
+		return
+	}
+	var param updateParam
+	err := utils.AnyTrans(data, &param)
+	if err != nil {
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminUpdateRes", utils.Fail("参数错误")))
+		return
+	}
+	man := &tables.ManagerTable{Id: param.Id}
+	err = man.Get()
+	if err != nil {
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminUpdateRes", utils.Fail("管理员不存在")))
+		return
+	}
+	if param.Password != "" {
+		password, err := utils.Decrypt(param.Password)
+		if err != nil {
+			_ = conn.WriteJSON(utils.WsEvent("superRoleAdminUpdateRes", utils.Fail("解密失败")))
+			return
+		}
+		man.Password = utils.HashPassword(password)
+	}
+	man.Name, man.Account = param.Name, param.Account
+	err = man.UpdateSelf()
+	if err != nil {
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminUpdateRes", utils.Fail("更新失败")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent("superRoleAdminUpdateRes", utils.Success(nil)))
+	// TODO: inform admin login expired
+}
+
+func Delete(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+	if !manager.Super {
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminDeleteRes", utils.Fail("权限不足")))
+		return
+	}
+	var ids []string
+	err := utils.AnyTrans(data, &ids)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminDeleteRes", utils.Fail("参数错误")))
+		return
+	}
+	err = tables.ManagersDelete(ids)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminDeleteRes", utils.Fail("删除失败")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent("superRoleAdminDeleteRes", utils.Success(nil)))
+}
+
+func Add(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+	if !manager.Super {
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminAddRes", utils.Fail("权限不足")))
+		return
+	}
+	var param addParam
+	err := utils.AnyTrans(data, &param)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminAddRes", utils.Fail("参数错误")))
+		return
+	}
+	if param.Name == "" || param.Account == "" || param.Password == "" {
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminAddRes", utils.Fail("数据不可为空")))
+		return
+	}
+	var password string
+	password, err = utils.Decrypt(param.Password)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminAddRes", utils.Fail("解密失败")))
+		return
+	}
+	id := utils.RandomString(16, utils.AlphaNumPatten)
+	man := &tables.ManagerTable{Id: id, Name: param.Name, Account: param.Account, Password: utils.HashPassword(password)}
+	err = man.Insert()
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superRoleAdminAddRes", utils.Fail("添加失败")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent("superRoleAdminAddRes", utils.Success(nil)))
+}

+ 23 - 2
handlers/manager/super/role/handler.go

@@ -1,6 +1,8 @@
-package role
+package config
 
 import (
+	"Wine-Server/handlers/manager/super/role/admin"
+	"Wine-Server/handlers/manager/super/role/worker"
 	"Wine-Server/utils"
 	"Wine-Server/utils/tables"
 	"github.com/gorilla/websocket"
@@ -8,6 +10,25 @@ import (
 
 func Handle(msg utils.WsMsg, conn *websocket.Conn, manager *tables.ManagerTable) {
 	switch msg.Event {
-
+	// admin:
+	case "superRoleAdminQuery":
+		admin.Query(conn, manager, msg.Data)
+		break
+	case "superRoleAdminUpdate":
+		admin.Update(conn, manager, msg.Data)
+		break
+	case "superRoleAdminDelete":
+		admin.Delete(conn, manager, msg.Data)
+		break
+	case "superRoleAdminAdd":
+		admin.Add(conn, manager, msg.Data)
+		break
+	// worker:
+	case "superRoleWorkerQuery":
+		worker.Query(conn, manager, msg.Data)
+		break
+	default:
+		_ = conn.WriteJSON(utils.WsError("unrecognized event"))
+		break
 	}
 }

+ 8 - 0
handlers/manager/super/role/worker/params.go

@@ -0,0 +1,8 @@
+package worker
+
+type queryParam struct {
+	Cond    string `json:"cond"`
+	Manager string `json:"manager"`
+	Page    int    `json:"page"`
+	Limit   int    `json:"limit"`
+}

+ 31 - 0
handlers/manager/super/role/worker/worker.go

@@ -0,0 +1,31 @@
+package worker
+
+import (
+	"Wine-Server/utils"
+	"Wine-Server/utils/tables"
+	"github.com/gorilla/websocket"
+)
+
+func Query(conn *websocket.Conn, manager *tables.ManagerTable, data any) {
+	if !manager.Super {
+		_ = conn.WriteJSON(utils.WsEvent("superRoleWorkerQueryRes", utils.Fail("权限不足")))
+		return
+	}
+	var param queryParam
+	err := utils.AnyTrans(data, &param)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superRoleWorkerQueryRes", utils.Fail("参数错误")))
+		return
+	}
+	total, workers, err := tables.WorkerQuery(param.Manager, param.Cond, param.Limit, param.Page)
+	if err != nil {
+		utils.Logger.Println(err)
+		_ = conn.WriteJSON(utils.WsEvent("superRoleWorkerQueryRes", utils.Fail("查询上酒工失败")))
+		return
+	}
+	_ = conn.WriteJSON(utils.WsEvent(
+		"superRoleWorkerQueryRes",
+		utils.Success(utils.JsonType{"total": total, "list": workers}),
+	))
+}

+ 1 - 1
handlers/seller/params.go

@@ -14,7 +14,7 @@ type tradeRedis struct {
 	Cell   uint8  `json:"cell"`
 	Wine   uint16 `json:"wine"`
 	Weight uint16 `json:"weight"`
-	Cash   int    `json:"cash"`
+	Cash   uint32 `json:"cash"`
 }
 
 type qrcodeParam struct {

+ 4 - 2
handlers/seller/worker.go

@@ -107,10 +107,12 @@ func WxPayHandler(ctx *gin.Context) {
 	volume, err := updateWineInfo(&dbTrade)
 	manager, err := updateDeviceInfo(&dbTrade, volume)
 	err = updateManagerInfo(manager, &dbTrade)
+	wine := tables.WineTable{Id: dbTrade.Wine}
+	_ = wine.Get()
 
 	table := tables.TradeTable{
 		Id: wxNotify.TransactionId, Trade: wxNotify.TradeNo, Device: dbTrade.Device, Payer: wxNotify.Payer.Openid,
-		Wine: dbTrade.Wine, Weight: dbTrade.Weight, Cash: dbTrade.Cash, Manager: manager,
+		Wine: dbTrade.Wine, Price: wine.Price, Weight: dbTrade.Weight, Cash: dbTrade.Cash, Manager: manager,
 	}
 	err = table.Insert()
 	if err != nil {
@@ -187,7 +189,7 @@ func getQrcode(device *tables.DeviceTable, conn *websocket.Conn, data any) {
 	}
 	_ = device.Get()
 	trade := device.Id + utils.TimeString()
-	store := tradeRedis{Device: device.Id, Cell: param.Cell, Wine: wine.Id, Weight: param.Weight, Cash: cash}
+	store := tradeRedis{Device: device.Id, Cell: param.Cell, Wine: wine.Id, Weight: param.Weight, Cash: uint32(cash)}
 	marshal, err := json.Marshal(store)
 	if err != nil {
 		utils.Logger.Println("marshal trade failed:", err)

+ 3 - 1
handlers/setup.go

@@ -128,7 +128,9 @@ func initDatabase(config *utils.Config) {
 	// create
 	toCreate := []createTableFn{
 		tables.CreateAdvertiseTable, tables.CreateDeviceTable, tables.CreateManagerTable,
-		tables.CreateParamsTable, tables.CreateVersionTable, tables.CreateWineTable, tables.CreateTradeTable,
+		tables.CreateParamsTable, tables.CreateVersionTable, tables.CreateWineTable,
+		tables.CreateTradeTable, tables.CreateWorkerTable, tables.CreateUserTable,
+		tables.CreateRefundTable, tables.CreateOperationTable,
 	}
 	for _, Fn := range toCreate {
 		err = Fn()

二进制
static/adv/20230929.mp4


二进制
static/adv/20230931.mp4


二进制
static/images/wine/10104.png


二进制
static/images/wine/10105.png


二进制
static/images/wine/10106.png


二进制
static/images/wine/10107.png


+ 10 - 7
utils/lib.go

@@ -287,15 +287,18 @@ func Query(SQL string) ([]JsonType, error) {
 	return ret, nil
 }
 
-func SaveBase64(image, filepath string) (string, error) {
-	encoded := strings.Split(image, ",")[1]
-	decoded, err := base64.StdEncoding.DecodeString(encoded)
+func SaveBase64(image, filepath string) (string, string, error) {
+	split := strings.Split(image, ",")
+	info, data := split[0], split[1]
+	decoded, err := base64.StdEncoding.DecodeString(data)
 	if err != nil {
-		return "Base64 格式错误", err
+		return "", "Base64 格式错误", err
 	}
-	err = os.WriteFile(filepath, decoded, 0644)
+	ext := strings.Split(info, "/")[1]
+	ext = strings.Split(ext, ";")[0]
+	err = os.WriteFile(filepath+"."+ext, decoded, 0644)
 	if err != nil {
-		return "图片存储失败", err
+		return "", "文件存储失败", err
 	}
-	return "", nil
+	return ext, "", nil
 }

+ 16 - 24
utils/tables/advertise.go

@@ -25,10 +25,7 @@ func CreateAdvertiseTable() error {
 		"`duration` SMALLINT UNSIGNED DEFAULT 3000," +
 		"`describe` VARCHAR(64) DEFAULT '');"
 	_, err := utils.Mysql.Exec(SQL)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *AdvertiseTable) Insert() error {
@@ -38,10 +35,7 @@ func (row *AdvertiseTable) Insert() error {
 		return err
 	}
 	_, err = pre.Exec(row.Order, row.Type, row.Src, row.Duration, row.Describe)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *AdvertiseTable) Delete() error {
@@ -50,10 +44,7 @@ func (row *AdvertiseTable) Delete() error {
 		return err
 	}
 	_, err = pre.Exec(row.Id)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *AdvertiseTable) Update(args utils.JsonType) error {
@@ -64,10 +55,7 @@ func (row *AdvertiseTable) Update(args utils.JsonType) error {
 		return err
 	}
 	_, err = pre.Exec(values...)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *AdvertiseTable) UpdateSelf() error {
@@ -77,10 +65,7 @@ func (row *AdvertiseTable) UpdateSelf() error {
 		return err
 	}
 	_, err = pre.Exec(row.Order, row.Src, row.Type, row.Duration, row.Describe, row.Id)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *AdvertiseTable) Get() error {
@@ -90,10 +75,7 @@ func (row *AdvertiseTable) Get() error {
 		return err
 	}
 	err = pre.QueryRow(row.Id).Scan(&row.Order, &row.Time, &row.Src, &row.Type, &row.Duration, &row.Describe)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func AdvertiseListAll() ([]AdvertiseTable, error) {
@@ -156,3 +138,13 @@ func AdvertisesQuery(cond string, kind, limit, page int) (int, []AdvertiseTable,
 	_ = rows.Close()
 	return total, res, nil
 }
+
+func AdvertiseQueryMaxId() (uint32, error) {
+	SQL := "SELECT MAX(`id`) FROM `advertise`;"
+	var max uint32
+	err := utils.Mysql.QueryRow(SQL).Scan(&max)
+	if err != nil {
+		return 0, err
+	}
+	return max, nil
+}

+ 7 - 24
utils/tables/device.go

@@ -61,10 +61,7 @@ func CreateDeviceTable() error {
 		"`manager` VARCHAR(16) DEFAULT '',`mark` VARCHAR(256) DEFAULT ''," +
 		"`order` INT UNSIGNED DEFAULT 0,`income` BIGINT UNSIGNED DEFAULT 0);"
 	_, err := utils.Mysql.Exec(SQL)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *DeviceTable) Insert() error {
@@ -73,22 +70,17 @@ func (row *DeviceTable) Insert() error {
 		return err
 	}
 	_, err = pre.Exec(row.Id)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
+// Delete deprecated
 func (row *DeviceTable) Delete() error {
 	pre, err := utils.Mysql.Prepare("DELETE FROM `device` WHERE `id`=?;")
 	if err != nil {
 		return err
 	}
 	_, err = pre.Exec(row.Id)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *DeviceTable) Update(args utils.JsonType) error {
@@ -99,10 +91,7 @@ func (row *DeviceTable) Update(args utils.JsonType) error {
 		return err
 	}
 	_, err = pre.Exec(values...)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *DeviceTable) UpdateSelf() error {
@@ -122,10 +111,7 @@ func (row *DeviceTable) UpdateSelf() error {
 		row.Wines[3].Id, row.Wines[3].Remain, row.Wines[3].Ppv,
 		row.Manager, row.Mark, row.Order, row.Income, row.Id,
 	)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *DeviceTable) Get() error {
@@ -144,10 +130,7 @@ func (row *DeviceTable) Get() error {
 		&row.Wines[3].Id, &row.Wines[3].Remain, &row.Wines[3].Ppv,
 		&row.Manager, &row.Mark, &row.Order, &row.Income,
 	)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func DevicesQuery(manager, cond string, limit, page int) (int, []utils.JsonType, error) {

+ 64 - 43
utils/tables/manager.go

@@ -2,6 +2,7 @@ package tables
 
 import (
 	"Wine-Server/utils"
+	"database/sql"
 )
 
 type ManagerTable struct {
@@ -19,7 +20,7 @@ type ManagerTable struct {
 }
 
 func CreateManagerTable() error {
-	sql := "CREATE TABLE IF NOT EXISTS `manager`(" +
+	SQL := "CREATE TABLE IF NOT EXISTS `manager`(" +
 		"`id` VARCHAR(16) PRIMARY KEY," +
 		"`super` BOOL DEFAULT FALSE," +
 		"`first` DATETIME DEFAULT CURRENT_TIMESTAMP," +
@@ -29,24 +30,18 @@ func CreateManagerTable() error {
 		"`password` CHAR(128) NOT NULL," +
 		"`order` INT UNSIGNED DEFAULT 0," +
 		"`income` BIGINT UNSIGNED DEFAULT 0);"
-	_, err := utils.Mysql.Exec(sql)
-	if err != nil {
-		return err
-	}
-	return nil
+	_, err := utils.Mysql.Exec(SQL)
+	return err
 }
 
 func (row *ManagerTable) Insert() error {
-	sql := "INSERT INTO `manager`(`id`,`name`,`account`,`password`) VALUES(?,?,?,?);"
-	pre, err := utils.Mysql.Prepare(sql)
+	SQL := "INSERT INTO `manager`(`id`,`name`,`account`,`password`) VALUES(?,?,?,?);"
+	pre, err := utils.Mysql.Prepare(SQL)
 	if err != nil {
 		return err
 	}
 	_, err = pre.Exec(row.Id, row.Name, row.Account, row.Password)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *ManagerTable) Delete() error {
@@ -55,43 +50,34 @@ func (row *ManagerTable) Delete() error {
 		return err
 	}
 	_, err = pre.Exec(row.Id)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *ManagerTable) Update(args utils.JsonType) error {
 	keys, values := utils.UnZip(args)
-	sql := utils.Format("UPDATE `manager` SET %s WHERE `id`='%s';", utils.SqlFields(keys), row.Id)
-	pre, err := utils.Mysql.Prepare(sql)
+	SQL := utils.Format("UPDATE `manager` SET %s WHERE `id`='%s';", utils.SqlFields(keys), row.Id)
+	pre, err := utils.Mysql.Prepare(SQL)
 	if err != nil {
 		return err
 	}
 	_, err = pre.Exec(values...)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *ManagerTable) UpdateSelf() error {
-	sql := "UPDATE `manager` SET `super`=?,`last`=?,`name`=?,`account`=?,`password`=?,`order`=?,`income`=? WHERE `id`=?;"
-	pre, err := utils.Mysql.Prepare(sql)
+	SQL := "UPDATE `manager` SET `super`=?,`last`=?,`name`=?,`account`=?,`password`=?,`order`=?,`income`=? WHERE `id`=?;"
+	pre, err := utils.Mysql.Prepare(SQL)
 	if err != nil {
 		return err
 	}
 	row.Last = utils.TimeNow()
 	_, err = pre.Exec(row.Super, row.Last, row.Name, row.Account, row.Password, row.Order, row.Income, row.Id)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *ManagerTable) Get() error {
-	sql := "SELECT `super`,`first`,`last`,`name`,`account`,`password`,`order`,`income` FROM `manager` WHERE `id`=?;"
-	pre, err := utils.Mysql.Prepare(sql)
+	SQL := "SELECT `super`,`first`,`last`,`name`,`account`,`password`,`order`,`income` FROM `manager` WHERE `id`=?;"
+	pre, err := utils.Mysql.Prepare(SQL)
 	if err != nil {
 		return err
 	}
@@ -99,15 +85,12 @@ func (row *ManagerTable) Get() error {
 		&row.Super, &row.First, &row.Last, &row.Name,
 		&row.Account, &row.Password, &row.Order, &row.Income,
 	)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *ManagerTable) GetByAcc() error {
-	sql := "SELECT `id`,`super`,`first`,`last`,`name`,`password`,`order`,`income` FROM `manager` WHERE `account`=? LIMIT 1;"
-	pre, err := utils.Mysql.Prepare(sql)
+	SQL := "SELECT `id`,`super`,`first`,`last`,`name`,`password`,`order`,`income` FROM `manager` WHERE `account`=? LIMIT 1;"
+	pre, err := utils.Mysql.Prepare(SQL)
 	if err != nil {
 		return err
 	}
@@ -115,16 +98,13 @@ func (row *ManagerTable) GetByAcc() error {
 		&row.Id, &row.Super, &row.First, &row.Last,
 		&row.Name, &row.Password, &row.Order, &row.Income,
 	)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
-func QueryManager(name string) ([]utils.JsonType, error) {
+func ManagerQuery(name string) ([]utils.JsonType, error) {
 	like := utils.Format("%%%s%%", name)
-	sql := "SELECT `id`,`name` FROM `manager` WHERE `super`=0 AND `name` LIKE ? LIMIT 10;"
-	pre, err := utils.Mysql.Prepare(sql)
+	SQL := "SELECT `id`,`name` FROM `manager` WHERE `super`=0 AND `name` LIKE ? LIMIT 10;"
+	pre, err := utils.Mysql.Prepare(SQL)
 	if err != nil {
 		return nil, err
 	}
@@ -141,3 +121,44 @@ func QueryManager(name string) ([]utils.JsonType, error) {
 	_ = rows.Close()
 	return res, nil
 }
+
+func ManagerQueryForAdmin(cond string, limit, page int) (int, []utils.JsonType, error) {
+	SQL := utils.Format(
+		"SELECT COUNT(`id`) AS `total` FROM `manager` WHERE `super`=0 AND (`name` LIKE '%%%s%%' OR `account` LIKE '%%%s%%');",
+		cond, cond,
+	)
+	total := 0
+	err := utils.Mysql.QueryRow(SQL).Scan(&total)
+	if err != nil {
+		return 0, nil, err
+	}
+	if total == 0 {
+		return 0, []utils.JsonType{}, nil
+	}
+	SQL = utils.Format(
+		"SELECT `id`,`first`,`last`,`name`,`account`,`order`,`income` FROM `manager` "+
+			"WHERE `super`=0 AND (`name` LIKE '%%%s%%' OR `account` LIKE '%%%s%%') LIMIT %d OFFSET %d;",
+		cond, cond, limit, (page-1)*limit,
+	)
+	var rows *sql.Rows
+	res := make([]utils.JsonType, 0)
+	rows, err = utils.Mysql.Query(SQL)
+	if err != nil {
+		return 0, nil, err
+	}
+	for rows.Next() {
+		var one ManagerTable
+		_ = rows.Scan(&one.Id, &one.First, &one.Last, &one.Name, &one.Account, &one.Order, &one.Income)
+		res = append(res, utils.JsonType{
+			"id": one.Id, "name": one.Name, "first": one.First, "last": one.Last,
+			"account": one.Account, "order": one.Order, "income": one.Income,
+		})
+	}
+	return total, res, nil
+}
+
+func ManagersDelete(ids []string) error {
+	SQL := utils.Format("DELETE FROM `manager` WHERE `id` IN (%s);", utils.SqlStringListJoin(ids))
+	_, err := utils.Mysql.Exec(SQL)
+	return err
+}

+ 71 - 0
utils/tables/operation.go

@@ -0,0 +1,71 @@
+package tables
+
+import "Wine-Server/utils"
+
+type OperationTable struct {
+	Id       string         `json:"id"`
+	Who      string         `json:"who"`
+	Time     utils.TimeType `json:"time"`
+	Describe string         `json:"describe"`
+}
+
+func CreateOperationTable() error {
+	SQL := "CREATE TABLE IF NOT EXISTS `operation`(" +
+		"`id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL," +
+		"`who` VARCHAR(32) NOT NULL," +
+		"`time` DATETIME DEFAULT CURRENT_TIMESTAMP," +
+		"`describe` VARCHAR(128) DEFAULT '');"
+	_, err := utils.Mysql.Exec(SQL)
+	return err
+}
+
+func (row *OperationTable) Insert() error {
+	SQL := "INSERT INTO `operation`(`who`,`describe`) VALUES(?,?);"
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	_, err = pre.Exec(row.Who, row.Describe)
+	return err
+}
+
+func (row *OperationTable) Delete() error {
+	pre, err := utils.Mysql.Prepare("DELETE FROM `operation` WHERE `id`=?;")
+	if err != nil {
+		return err
+	}
+	_, err = pre.Exec(row.Id)
+	return err
+}
+
+func (row *OperationTable) Update(args utils.JsonType) error {
+	keys, values := utils.UnZip(args)
+	SQL := utils.Format("UPDATE `operation` SET %s WHERE `id`=%d;", utils.SqlFields(keys), row.Id)
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	_, err = pre.Exec(values...)
+	return err
+}
+
+func (row *OperationTable) UpdateSelf() error {
+	SQL := "UPDATE `operation` SET `who`=?,`time`=?,`describe`=? WHERE `id`=?;"
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	row.Time = utils.TimeNow()
+	_, err = pre.Exec(row.Who, row.Time, row.Describe, row.Id)
+	return err
+}
+
+func (row *OperationTable) Get() error {
+	SQL := "SELECT `who`,`time`,`describe` FROM `operation` WHERE `id`=?;"
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	err = pre.QueryRow(row.Id).Scan(&row.Who, &row.Time, &row.Describe)
+	return err
+}

+ 27 - 26
utils/tables/params.go

@@ -13,40 +13,33 @@ type ParamsTable struct {
 
 func CreateParamsTable() error {
 	sql := "CREATE TABLE IF NOT EXISTS `params`(" +
-		"`id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY," +
+		"`id` SMALLINT UNSIGNED PRIMARY KEY," +
 		"`key` VARCHAR(32) NOT NULL," +
 		"`value` INT UNSIGNED NOT NULL," +
 		"`describe` VARCHAR(32) DEFAULT '');"
 	_, err := utils.Mysql.Exec(sql)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
+// Insert deprecated
 func (row *ParamsTable) Insert() error {
-	sql := "INSERT INTO `params`(`key`,`value`,``) VALUES(?,?,?);"
+	sql := "INSERT INTO `params`(`key`,`value`,`describe`) VALUES(?,?,?);"
 	pre, err := utils.Mysql.Prepare(sql)
 	if err != nil {
 		return err
 	}
 	_, err = pre.Exec(row.Key, row.Value, row.Describe)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
+// Delete deprecated
 func (row *ParamsTable) Delete() error {
 	pre, err := utils.Mysql.Prepare("DELETE FROM `params` WHERE `id`=?;")
 	if err != nil {
 		return err
 	}
 	_, err = pre.Exec(row.Id)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *ParamsTable) Update(args utils.JsonType) error {
@@ -57,10 +50,7 @@ func (row *ParamsTable) Update(args utils.JsonType) error {
 		return err
 	}
 	_, err = pre.Exec(values...)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *ParamsTable) UpdateSelf() error {
@@ -70,10 +60,7 @@ func (row *ParamsTable) UpdateSelf() error {
 		return err
 	}
 	_, err = pre.Exec(row.Key, row.Value, row.Describe, row.Id)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *ParamsTable) Get() error {
@@ -83,10 +70,7 @@ func (row *ParamsTable) Get() error {
 		return err
 	}
 	err = pre.QueryRow(row.Id).Scan(&row.Key, &row.Value, &row.Describe)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func ParamsListAll() ([]ParamsTable, error) {
@@ -105,3 +89,20 @@ func ParamsListAll() ([]ParamsTable, error) {
 	}
 	return res, nil
 }
+
+func ParamsListAllForSuper() ([]utils.JsonType, error) {
+	query, err := utils.Mysql.Query("SELECT `id`,`value`,`describe` FROM `params`;")
+	if err != nil {
+		return nil, err
+	}
+	var res []utils.JsonType
+	for query.Next() {
+		var one ParamsTable
+		err = query.Scan(&one.Id, &one.Value, &one.Describe)
+		if err != nil {
+			return nil, err
+		}
+		res = append(res, utils.JsonType{"id": one.Id, "name": one.Describe, "value": one.Value})
+	}
+	return res, nil
+}

+ 73 - 0
utils/tables/refund.go

@@ -0,0 +1,73 @@
+package tables
+
+import (
+	"Wine-Server/utils"
+)
+
+type RefundTable struct {
+	Tid     string
+	Manager string
+	Time    utils.TimeType
+	Cash    uint32
+	Reason  string
+}
+
+func CreateRefundTable() error {
+	SQL := "CREATE TABLE IF NOT EXISTS `refund`(" +
+		"`tid` VARCHAR(32) PRIMARY KEY NOT NULL," +
+		"`manager` VARCHAR(16) DEFAULT ''," +
+		"`time` DATETIME DEFAULT CURRENT_TIMESTAMP," +
+		"`cash` INT UNSIGNED DEFAULT 0," +
+		"`reason` VARCHAR(128) DEFAULT '');"
+	_, err := utils.Mysql.Exec(SQL)
+	return err
+}
+
+func (row *RefundTable) Insert() error {
+	SQL := "INSERT INTO `refund` (`tid`,`manager`,`cash`,`reason`) VALUES (?,?,?,?);"
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	_, err = pre.Exec(row.Tid, row.Manager, row.Cash, row.Reason)
+	return err
+}
+
+// Delete deprecated
+func (row *RefundTable) Delete() error {
+	SQL := utils.Format("DELETE FROM `refund` WHERE `id`='%s';", row.Tid)
+	_, err := utils.Mysql.Exec(SQL)
+	return err
+}
+
+func (row *RefundTable) Update(args utils.JsonType) error {
+	keys, values := utils.UnZip(args)
+	SQL := utils.Format("UPDATE `refund` SET %s WHERE `id`='%s';", utils.SqlFields(keys), row.Tid)
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	_, err = pre.Exec(values...)
+	return err
+}
+
+func (row *RefundTable) UpdateSelf() error {
+	SQL := "UPDATE `refund` SET `manager`=?,`time`=?,`cash`=?,`reason`=? WHERE `tid`=?;"
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	row.Time = utils.TimeNow()
+	_, err = pre.Exec(row.Manager, row.Time, row.Cash, row.Reason, row.Tid)
+	return err
+}
+
+func (row *RefundTable) Get() error {
+	SQL := "SELECT `manager`,`time`,`cash`,`reason` FROM `refund` WHERE `tid`=?;"
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	err = pre.QueryRow(row.Tid).Scan(&row.Manager, &row.Time, &row.Cash, &row.Reason)
+	return err
+}

+ 71 - 46
utils/tables/trade.go

@@ -2,49 +2,46 @@ package tables
 
 import (
 	"Wine-Server/utils"
+	"database/sql"
 )
 
 type TradeTable struct {
-	Id      string         `json:"id"`
-	Trade   string         `json:"trade"`
-	Device  string         `json:"device"`
-	Time    utils.TimeType `json:"time"`
-	Payer   string         `json:"payer"`
-	Wine    uint16         `json:"wine"`
-	Weight  uint16         `json:"weight"`
-	Cash    int            `json:"cash"`
-	Manager string         `json:"manager"`
+	Id      string
+	Trade   string
+	Device  string
+	Time    utils.TimeType
+	Payer   string
+	Wine    uint16
+	Price   uint16
+	Weight  uint16
+	Cash    uint32
+	Manager string
 }
 
 func CreateTradeTable() error {
-	sql := "CREATE TABLE IF NOT EXISTS `trade`(" +
+	SQL := "CREATE TABLE IF NOT EXISTS `trade`(" +
 		"`id` VARCHAR(32) PRIMARY KEY NOT NULL," +
 		"`trade` VARCHAR(64) NOT NULL," +
 		"`device` VARCHAR(32) NOT NULL," +
 		"`time` DATETIME DEFAULT CURRENT_TIMESTAMP," +
 		"`payer` VARCHAR(64) NOT NULL," +
 		"`wine` SMALLINT UNSIGNED NOT NULL," +
+		"`price` SMALLINT UNSIGNED NOT NULL," +
 		"`weight` SMALLINT UNSIGNED NOT NULL," +
 		"`cash` INT UNSIGNED NOT NULL," +
 		"`manager` VARCHAR(16));"
-	_, err := utils.Mysql.Exec(sql)
-	if err != nil {
-		return err
-	}
-	return nil
+	_, err := utils.Mysql.Exec(SQL)
+	return err
 }
 
 func (row *TradeTable) Insert() error {
-	sql := "INSERT INTO `trade`(`id`,`trade`,`device`,`payer`,`wine`,`weight`,`cash`,`manager`) VALUES(?,?,?,?,?,?,?,?);"
-	pre, err := utils.Mysql.Prepare(sql)
+	SQL := "INSERT INTO `trade`(`id`,`trade`,`device`,`payer`,`wine`,`price`,`weight`,`cash`,`manager`) VALUES(?,?,?,?,?,?,?,?,?);"
+	pre, err := utils.Mysql.Prepare(SQL)
 	if err != nil {
 		return err
 	}
-	_, err = pre.Exec(row.Id, row.Trade, row.Device, row.Payer, row.Wine, row.Weight, row.Cash, row.Manager)
-	if err != nil {
-		return err
-	}
-	return nil
+	_, err = pre.Exec(row.Id, row.Trade, row.Device, row.Payer, row.Wine, row.Price, row.Weight, row.Cash, row.Manager)
+	return err
 }
 
 func (row *TradeTable) Delete() error {
@@ -53,53 +50,81 @@ func (row *TradeTable) Delete() error {
 		return err
 	}
 	_, err = pre.Exec(row.Id)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *TradeTable) Update(args utils.JsonType) error {
 	keys, values := utils.UnZip(args)
-	sql := utils.Format("UPDATE `trade` SET %s WHERE `id`=%s;", utils.SqlFields(keys), row.Id)
-	pre, err := utils.Mysql.Prepare(sql)
+	SQL := utils.Format("UPDATE `trade` SET %s WHERE `id`='%s';", utils.SqlFields(keys), row.Id)
+	pre, err := utils.Mysql.Prepare(SQL)
 	if err != nil {
 		return err
 	}
 	_, err = pre.Exec(values...)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *TradeTable) UpdateSelf() error {
-	sql := "UPDATE `trade` SET `trade`=?,`device`=?,`time`=?,`payer`=?,`wine`=?,`weight`=?,`cash`=?,`manager`=? WHERE `id`=?;"
-	pre, err := utils.Mysql.Prepare(sql)
+	SQL := "UPDATE `trade` SET `trade`=?,`device`=?,`time`=?,`payer`=?,`wine`=?`price`=?,`weight`=?,`cash`=?,`manager`=? WHERE `id`=?;"
+	pre, err := utils.Mysql.Prepare(SQL)
 	if err != nil {
 		return err
 	}
-	_, err = pre.Exec(row.Trade, row.Device, row.Time, row.Payer, row.Wine, row.Weight, row.Cash, row.Manager, row.Id)
-	if err != nil {
-		return err
-	}
-	return nil
+	_, err = pre.Exec(row.Trade, row.Device, row.Time, row.Payer, row.Wine, row.Price, row.Weight, row.Cash, row.Manager, row.Id)
+	return err
 }
 
 func (row *TradeTable) Get() error {
-	sql := "SELECT `trade`,`device`,`time`,`payer`,`wine`,`weight`,`cash`,`manager` FROM `trade` WHERE `id`=?;"
-	pre, err := utils.Mysql.Prepare(sql)
+	SQL := "SELECT `trade`,`device`,`time`,`payer`,`wine`,`price`,`weight`,`cash`,`manager` FROM `trade` WHERE `id`=?;"
+	pre, err := utils.Mysql.Prepare(SQL)
 	if err != nil {
 		return err
 	}
 	err = pre.QueryRow(row.Id).Scan(
 		&row.Trade, &row.Device, &row.Time, &row.Payer,
-		&row.Wine, &row.Weight, &row.Cash, &row.Manager,
+		&row.Wine, &row.Price, &row.Weight, &row.Cash, &row.Manager,
 	)
+	return err
+}
+
+func TradeQuery(cond, uid string, limit, page int) (int, []utils.JsonType, error) {
+	like := utils.Format("%%%s%%", cond)
+	SQL := "SELECT COUNT(t.`id`) FROM `trade` AS t LEFT JOIN `wine` AS w ON t.`wine`=w.`id` WHERE t.`payer`=? AND (t.`id` LIKE ? OR w.`name` LIKE ?);"
+	pre, err := utils.Mysql.Prepare(SQL)
 	if err != nil {
-		return err
+		return 0, nil, err
+	}
+	total := 0
+	err = pre.QueryRow(uid, like, like).Scan(&total)
+	if err != nil {
+		return 0, nil, err
+	}
+	if total == 0 {
+		return 0, []utils.JsonType{}, nil
 	}
-	return nil
+	SQL = "SELECT t.`id`,t.`device`,t.`time`,w.`name`,t.`price`,t.`weight`,t.`cash`,r.`cash`,r.`reason` " +
+		"FROM `trade` AS t LEFT JOIN `wine` AS w ON t.`wine`=w.`id` LEFT JOIN `refund` AS r ON t.`id`=r.`tid` " +
+		"WHERE t.`payer`=? AND (t.`id` LIKE ? OR w.`name` LIKE ?) ORDER BY t.`time` DESC LIMIT ? OFFSET ?;"
+	pre, err = utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return 0, nil, err
+	}
+	var rows *sql.Rows
+	rows, err = pre.Query(uid, like, like, limit, (page-1)*limit)
+	if err != nil {
+		return 0, nil, err
+	}
+	res := make([]utils.JsonType, 0)
+	for rows.Next() {
+		var one TradeTable
+		refund := 0
+		wineName, reason := "", ""
+		_ = rows.Scan(&one.Id, &one.Device, &one.Time, &wineName, &one.Price, &one.Weight, &one.Cash, &refund, &reason)
+		res = append(res, utils.JsonType{
+			"id": one.Id, "device": one.Device, "time": one.Time, "wine": wineName, "price": one.Price,
+			"weight": one.Weight, "cash": one.Cash, "refund": refund, "reason": reason,
+		})
+	}
+	_ = rows.Close()
+	return total, res, nil
 }
-
-// TODO: list by: <device>, <manager>, <payer> with time-duration

+ 137 - 0
utils/tables/user.go

@@ -0,0 +1,137 @@
+package tables
+
+import (
+	"Wine-Server/utils"
+	"database/sql"
+)
+
+type UserTable struct {
+	Id    string
+	First utils.TimeType
+	Last  utils.TimeType
+
+	Vip         bool
+	Cash        uint64
+	MaxCost     uint32
+	BuyCount    uint32
+	BuyCost     uint64
+	RefundCount uint32
+	RefundCost  uint64
+}
+
+func CreateUserTable() error {
+	SQL := "CREATE TABLE IF NOT EXISTS `user`(" +
+		"`id` VARCHAR(64) PRIMARY KEY NOT NULL," +
+		"`first` DATETIME DEFAULT CURRENT_TIMESTAMP," +
+		"`last` DATETIME DEFAULT CURRENT_TIMESTAMP," +
+		"`vip` BOOL DEFAULT FALSE," +
+		"`cash` BIGINT UNSIGNED DEFAULT 0," +
+		"`max_cost` INT UNSIGNED DEFAULT 0," +
+		"`buy_count` INT UNSIGNED DEFAULT 0," +
+		"`buy_cost` BIGINT UNSIGNED DEFAULT 0," +
+		"`refund_count` INT UNSIGNED DEFAULT 0," +
+		"`refund_cost` BIGINT UNSIGNED DEFAULT 0);"
+	_, err := utils.Mysql.Exec(SQL)
+	return err
+}
+
+func (row *UserTable) Insert() error {
+	SQL := "INSERT INTO `user` (`id`,`max_cost`,`buy_count`,`buy_cost`) VALUES (?,?,?,?,?);"
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	_, err = pre.Exec(row.Id, row.MaxCost, row.BuyCount, row.BuyCost)
+	return err
+}
+
+// Delete deprecated
+func (row *UserTable) Delete() error {
+	SQL := utils.Format("DELETE FROM `user` WHERE `id`='%s';", row.Id)
+	_, err := utils.Mysql.Exec(SQL)
+	return err
+}
+
+func (row *UserTable) Update(args utils.JsonType) error {
+	keys, values := utils.UnZip(args)
+	SQL := utils.Format("UPDATE `user` SET %s WHERE `id`='%s';", utils.SqlFields(keys), row.Id)
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	_, err = pre.Exec(values...)
+	return err
+}
+
+func (row *UserTable) UpdateSelf() error {
+	SQL := "UPDATE `user` SET `last`=?,`vip`=?,`cash`=?,`max_cost`=?,`buy_count`=?,`buy_cost`=?,`refund_count`=?,`refund_cost`=? WHERE `id`=?;"
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	_, err = pre.Exec(row.Last, row.Vip, row.Cash, row.MaxCost, row.BuyCount, row.BuyCost, row.RefundCount, row.RefundCost, row.Id)
+	return err
+}
+
+func (row *UserTable) Get() error {
+	SQL := "SELECT `first`,`last`,`vip`,`cash`,`max_cost`,`buy_count`,`buy_cost`,`refund_count`,`refund_cost` FROM `user` WHERE `id`=?;"
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	err = pre.QueryRow(row.Id).Scan(
+		&row.First, &row.Last, &row.Vip, &row.Cash, &row.MaxCost,
+		&row.BuyCount, &row.BuyCost, &row.RefundCount, &row.RefundCost,
+	)
+	return err
+}
+
+func UserQuery(id string, vip, limit, page int) (int, []utils.JsonType, error) {
+	SQL := "none"
+	if vip == -1 {
+		SQL = utils.Format("SELECT COUNT(`id`) AS `total` FROM `user` WHERE `id` LIKE '%%%s%%';", id)
+	} else {
+		SQL = utils.Format(
+			"SELECT COUNT(`id`) AS `total` FROM `user` WHERE `vip`=%d AND `id` LIKE '%%%s%%';", vip, id,
+		)
+	}
+	total := 0
+	err := utils.Mysql.QueryRow(SQL).Scan(&total)
+	if err != nil {
+		return 0, nil, err
+	}
+	if total == 0 {
+		return 0, []utils.JsonType{}, err
+	}
+	if vip == -1 {
+		SQL = utils.Format(
+			"SELECT `id`,`first`,`last`,`vip`,`cash`,`max_cost`,`buy_count`,`buy_cost`,`refund_count`,`refund_cost` "+
+				"FROM `user` WHERE `id` LIKE '%%%s%%' LIMIT %d OFFSET %d;", id, limit, (page-1)*limit,
+		)
+	} else {
+		SQL = utils.Format(
+			"SELECT `id`,`first`,`last`,`vip`,`cash`,`max_cost`,`buy_count`,`buy_cost`,`refund_count`,`refund_cost` "+
+				"FROM `user` WHERE `vip`=%d AND `id` LIKE '%%%s%%' LIMIT %d OFFSET %d;", vip, id, limit, (page-1)*limit,
+		)
+	}
+	var rows *sql.Rows
+	res := make([]utils.JsonType, 0)
+	rows, err = utils.Mysql.Query(SQL)
+	if err != nil {
+		return 0, nil, err
+	}
+	for rows.Next() {
+		var tmp UserTable
+		err = rows.Scan(
+			&tmp.Id, &tmp.First, &tmp.Last, &tmp.Vip, &tmp.Cash, &tmp.MaxCost,
+			&tmp.BuyCount, &tmp.BuyCost, &tmp.RefundCount, &tmp.RefundCost,
+		)
+		res = append(res, utils.JsonType{
+			"id": tmp.Id, "first": tmp.First, "last": tmp.Last, "vip": tmp.Vip, "cash": tmp.Cash,
+			"max_cost": tmp.MaxCost, "buy_count": tmp.BuyCount, "buy_cost": tmp.BuyCost,
+			"refund_count": tmp.RefundCount, "refund_cost": tmp.RefundCost,
+		})
+	}
+	_ = rows.Close()
+	return total, res, nil
+}

+ 6 - 24
utils/tables/version.go

@@ -16,10 +16,7 @@ func CreateVersionTable() error {
 		"`name` VARCHAR(32)," +
 		"`url` VARCHAR(128) NOT NULL);"
 	_, err := utils.Mysql.Exec(sql)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *VersionTable) Insert() error {
@@ -29,10 +26,7 @@ func (row *VersionTable) Insert() error {
 		return err
 	}
 	_, err = pre.Exec(row.Ver, row.Name, row.Url)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *VersionTable) Delete() error {
@@ -41,10 +35,7 @@ func (row *VersionTable) Delete() error {
 		return err
 	}
 	_, err = pre.Exec(row.Ver)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *VersionTable) Update(args utils.JsonType) error {
@@ -55,10 +46,7 @@ func (row *VersionTable) Update(args utils.JsonType) error {
 		return err
 	}
 	_, err = pre.Exec(values...)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *VersionTable) UpdateSelf() error {
@@ -68,19 +56,13 @@ func (row *VersionTable) UpdateSelf() error {
 		return err
 	}
 	_, err = pre.Exec(row.Name, row.Url, row.Ver)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *VersionTable) GetLatest() error {
 	sql := "SELECT `ver`,`name`,`url` FROM `version` ORDER BY `ver` DESC LIMIT 1;"
 	err := utils.Mysql.QueryRow(sql).Scan(&row.Ver, &row.Name, &row.Url)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func VersionListAll() ([]VersionTable, error) {

+ 5 - 20
utils/tables/wine.go

@@ -34,10 +34,7 @@ func CreateWineTable() error {
 		"`income` BIGINT UNSIGNED DEFAULT 0," +
 		"`deleted` TINYINT(1) DEFAULT 0);"
 	_, err := utils.Mysql.Exec(SQL)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *WineTable) Insert() error {
@@ -47,10 +44,7 @@ func (row *WineTable) Insert() error {
 		return err
 	}
 	_, err = pre.Exec(row.Id, row.Name, row.Price, row.Degree, row.Density, row.Picture, row.Describe)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *WineTable) Delete() error {
@@ -66,10 +60,7 @@ func (row *WineTable) Update(args utils.JsonType) error {
 		return err
 	}
 	_, err = pre.Exec(values...)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *WineTable) UpdateSelf() error {
@@ -79,10 +70,7 @@ func (row *WineTable) UpdateSelf() error {
 		return err
 	}
 	_, err = pre.Exec(row.Name, row.Price, row.Degree, row.Density, row.Picture, row.Describe, row.Order, row.Income, row.Deleted, row.Id)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func (row *WineTable) Get() error {
@@ -95,10 +83,7 @@ func (row *WineTable) Get() error {
 		&row.Name, &row.Price, &row.Degree, &row.Density, &row.Picture,
 		&row.Describe, &row.Time, &row.Order, &row.Income, &row.Deleted,
 	)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 func extractJson(wine WineTable) utils.JsonType {

+ 200 - 0
utils/tables/worker.go

@@ -0,0 +1,200 @@
+package tables
+
+import (
+	"Wine-Server/utils"
+	"database/sql"
+)
+
+type WorkerTable struct {
+	Id    string
+	First utils.TimeType
+	Last  utils.TimeType
+
+	Name     string
+	Phone    string
+	Password string
+	Manager  string
+
+	Count uint32
+	Cost  uint32
+}
+
+func CreateWorkerTable() error {
+	SQL := "CREATE TABLE IF NOT EXISTS `worker`(" +
+		"`id` VARCHAR(16) PRIMARY KEY NOT NULL," +
+		"`first` DATETIME DEFAULT CURRENT_TIMESTAMP," +
+		"`last` DATETIME DEFAULT CURRENT_TIMESTAMP," +
+		"`name` VARCHAR(16) NOT NULL," +
+		"`phone` VARCHAR(11) NOT NULL," +
+		"`password` VARCHAR(128) NOT NULL," +
+		"`manager` VARCHAR(16) DEFAULT ''," +
+		"`count` INT UNSIGNED DEFAULT 0," +
+		"`cost` INT UNSIGNED DEFAULT 0);"
+	_, err := utils.Mysql.Exec(SQL)
+	return err
+}
+
+func (row *WorkerTable) Insert() error {
+	SQL := "INSERT INTO `worker`(`id`,`name`,`phone`,`password`) VALUES(?,?,?,?);"
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	_, err = pre.Exec(row.Id, row.Name, row.Phone, row.Password)
+	return err
+}
+
+func (row *WorkerTable) Delete() error {
+	pre, err := utils.Mysql.Prepare("DELETE FROM `worker` WHERE `id`=?;")
+	if err != nil {
+		return err
+	}
+	_, err = pre.Exec(row.Id)
+	return err
+}
+
+func (row *WorkerTable) Update(args utils.JsonType) error {
+	keys, values := utils.UnZip(args)
+	SQL := utils.Format("UPDATE `worker` SET %s WHERE `id`='%s';", utils.SqlFields(keys), row.Id)
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	_, err = pre.Exec(values...)
+	return err
+}
+
+func (row *WorkerTable) UpdateSelf() error {
+	SQL := "UPDATE `worker` SET `last`=?,`name`=?,`phone`=?,`password`=?,`manager`=?,`count`=?,`cost`=? WHERE `id`=?;"
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	row.Last = utils.TimeNow()
+	_, err = pre.Exec(row.Last, row.Name, row.Phone, row.Password, row.Manager, row.Count, row.Cost, row.Id)
+	return err
+}
+
+func (row *WorkerTable) Get() error {
+	SQL := "SELECT `first`,`last`,`name`,`phone`,`password`,`manager`,`count`,`cost` FROM `worker` WHERE `id`=?;"
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	err = pre.QueryRow(row.Id).Scan(
+		&row.First, &row.Last, &row.Name, &row.Phone,
+		&row.Password, &row.Count, &row.Cost,
+	)
+	return err
+}
+
+func (row *WorkerTable) GetByPhone() error {
+	SQL := "SELECT `id`,`first`,`last`,`name`,`password`,`manager`,`count`,`cost` FROM `worker` WHERE `phone`=? LIMIT 1;"
+	pre, err := utils.Mysql.Prepare(SQL)
+	if err != nil {
+		return err
+	}
+	err = pre.QueryRow(row.Phone).Scan(
+		&row.Id, &row.First, &row.Last, &row.Name,
+		&row.Password, &row.Manager, &row.Count, &row.Cost,
+	)
+	return err
+}
+
+func WorkerQuery(manager, cond string, limit, page int) (int, []utils.JsonType, error) {
+	SQL := "none"
+	if manager == "" { // any
+		SQL = utils.Format(
+			"SELECT COUNT(`id`) AS `total` FROM `worker` WHERE `name` LIKE '%%%s%%' OR `phone` LIKE '%%%s%%';",
+			cond, cond,
+		)
+	} else { // one
+		SQL = utils.Format(
+			"SELECT COUNT(`id`) AS `total` FROM `worker` WHERE `manager`='%s' AND (`name` LIKE '%%%s%%' OR `phone` LIKE '%%%s%%');",
+			manager, cond, cond,
+		)
+	}
+	total := 0
+	err := utils.Mysql.QueryRow(SQL).Scan(&total)
+	if err != nil {
+		return 0, nil, err
+	}
+	if total == 0 {
+		return 0, []utils.JsonType{}, err
+	}
+	if manager == "" { // any
+		SQL = utils.Format(
+			"SELECT w.`id`,w.`first`,w.`last`,w.`name`,w.`phone`,w.`count`,w.`cost`,m.`id`,m.`name` "+
+				"FROM `worker` AS w LEFT JOIN `manager` AS m "+
+				"ON w.`manager`=m.`id` WHERE w.`name` LIKE '%%%s%%' OR w.`phone` LIKE '%%%s%%' LIMIT %d OFFSET %d;",
+			cond, cond, limit, (page-1)*limit,
+		)
+	} else { // one
+		SQL = utils.Format(
+			"SELECT w.`id`,w.`first`,w.`last`,w.`name`,w.`phone`,w.`count`,w.`cost`,m.`id`,m.`name` "+
+				"FROM `worker` AS w LEFT JOIN `manager` AS m "+
+				"ON w.`manager`=m.`id` WHERE w.`manager`='%s' AND (w.`name` LIKE '%%%s%%' OR w.`phone` LIKE '%%%s%%') LIMIT %d OFFSET %d;",
+			manager, cond, cond, limit, (page-1)*limit,
+		)
+	}
+
+	var rows *sql.Rows
+	rows, err = utils.Mysql.Query(SQL)
+	if err != nil {
+		return 0, nil, err
+	}
+	res := make([]utils.JsonType, 0)
+	for rows.Next() {
+		var worker WorkerTable
+		name := ""
+		_ = rows.Scan(&worker.Id, &worker.First, &worker.Last, &worker.Name, &worker.Phone, &worker.Count, &worker.Cost, &worker.Manager, &name)
+		res = append(res, utils.JsonType{
+			"id": worker.Id, "first": worker.First, "last": worker.Last, "name": worker.Name, "phone": worker.Phone,
+			"count": worker.Count, "cost": worker.Cost, "manager": utils.JsonType{"id": worker.Manager, "name": name},
+		})
+	}
+	_ = rows.Close()
+	return total, res, nil
+}
+
+func WorkerQueryForAdmin(manager, cond string, limit, page int) (int, []utils.JsonType, error) {
+	SQL := utils.Format(
+		"SELECT COUNT(`id`) AS `total` FROM `worker` WHERE `manager`='%s' AND (`name` LIKE '%%%s%%' OR `phone` LIKE '%%%s%%');",
+		manager, cond, cond,
+	)
+	total := 0
+	err := utils.Mysql.QueryRow(SQL).Scan(&total)
+	if err != nil {
+		return 0, nil, err
+	}
+	if total == 0 {
+		return 0, []utils.JsonType{}, err
+	}
+	SQL = utils.Format(
+		"SELECT `id`,`first`,`last`,`name`,`phone`,`count`,`cost` FROM `worker` "+
+			"WHERE `manager`='%s' AND (`name` LIKE '%%%s%%' OR `phone` LIKE '%%%s%%') LIMIT %d OFFSET %d;",
+		manager, cond, cond, limit, (page-1)*limit,
+	)
+	var rows *sql.Rows
+	rows, err = utils.Mysql.Query(SQL)
+	if err != nil {
+		return 0, nil, err
+	}
+	res := make([]utils.JsonType, 0)
+	for rows.Next() {
+		var worker WorkerTable
+		_ = rows.Scan(&worker.Id, &worker.First, &worker.Last, &worker.Name, &worker.Phone, &worker.Count, &worker.Cost)
+		res = append(res, utils.JsonType{
+			"id": worker.Id, "first": worker.First, "last": worker.Last, "name": worker.Name,
+			"phone": worker.Phone, "count": worker.Count, "cost": worker.Cost,
+		})
+	}
+	_ = rows.Close()
+	return total, res, nil
+}
+
+func WorkersDelete(ids []string) error {
+	SQL := utils.Format("DELETE FROM `worker` WHERE `id` IN (%s);", utils.SqlStringListJoin(ids))
+	_, err := utils.Mysql.Exec(SQL)
+	return err
+}