worker.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. package work
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/gogf/gf/v2/util/gconv"
  6. "io"
  7. "log"
  8. "net/http"
  9. "os"
  10. "path/filepath"
  11. "strings"
  12. "time"
  13. "zhiyuan/models"
  14. "zhiyuan/pkg/app"
  15. "zhiyuan/pkg/db"
  16. "zhiyuan/pkg/utils"
  17. "zhiyuan/services/geo"
  18. "zhiyuan/services/work/worker"
  19. "github.com/gin-gonic/gin"
  20. "github.com/tealeg/xlsx/v3"
  21. )
  22. func WorkerList(c *gin.Context) {
  23. page := app.HandlePageNums(c)
  24. where := map[string]string{
  25. "where": "`zy_worker`.`id`>0",
  26. "_group_by": "`zy_worker`.`id`",
  27. "_order_by": "`zy_worker`.`id` desc",
  28. }
  29. if page.PageSize != 0 {
  30. where["_page_size"] = utils.ToStr(page.PageSize)
  31. where["_page_num"] = utils.ToStr(page.PageNum)
  32. }
  33. param := make(map[string]interface{})
  34. name := c.Query("name")
  35. if name != "" {
  36. where["where"] = where["where"] + " AND `zy_worker`.`name` LIKE {{name}}"
  37. param["name"] = "%" + name + "%"
  38. }
  39. phone := c.Query("phone")
  40. if phone != "" {
  41. where["where"] = where["where"] + " AND `zy_worker`.`phone` LIKE {{phone}}"
  42. param["phone"] = "%" + phone + "%"
  43. }
  44. idcode := c.Query("idcode")
  45. if idcode != "" {
  46. where["where"] = where["where"] + " AND `zy_worker`.`idcode` LIKE {{idcode}}"
  47. param["idcode"] = "%" + idcode + "%"
  48. }
  49. typeId := c.Query("type_id")
  50. if typeId != "" {
  51. where["where"] = where["where"] + " AND FIND_IN_SET({{type_id}}, `zy_worker`.`type_ids`)"
  52. param["type_id"] = typeId
  53. }
  54. state := utils.ToInt(c.Query("state"))
  55. if state != 0 {
  56. where["where"] = where["where"] + " AND `zy_worker`.`state`={{state}}"
  57. param["state"] = state
  58. }
  59. total, err := worker.CountRaw(where["where"], param)
  60. if err != nil {
  61. app.Error(c, err.Error())
  62. return
  63. }
  64. type WorkerList struct {
  65. ID int `json:"id"`
  66. Name string `json:"name"`
  67. Phone string `json:"phone"`
  68. TypeIds string `json:"type_ids"`
  69. TypeNames string `json:"type_names"`
  70. Idcode string `json:"idcode"`
  71. Idcard1 string `json:"idcard1"`
  72. Idcard2 string `json:"idcard2"`
  73. State string `json:"state"`
  74. CreatedAt int `json:"created_at"`
  75. UpdatedAt int `json:"updated_at"`
  76. }
  77. workerList := make([]WorkerList, 0)
  78. if err = worker.GetWorkersRaw(where, param, &workerList); err != nil {
  79. app.Error(c, err.Error())
  80. return
  81. }
  82. data := gin.H{
  83. "list": workerList,
  84. "total": total,
  85. "limit": page.PageSize,
  86. }
  87. app.Success(c, data)
  88. }
  89. func WorkerVerify(c *gin.Context) {
  90. id := utils.ToInt(c.Param("id"))
  91. if id <= 0 {
  92. app.ErrorMsg(c, "worker id must be a number", nil)
  93. return
  94. }
  95. err := worker.VerifyByID(id)
  96. if err != nil {
  97. app.ErrorMsg(c, err.Error(), nil)
  98. return
  99. }
  100. app.Success(c, nil)
  101. }
  102. func WorkerImport(c *gin.Context) {
  103. file, err := c.FormFile("file")
  104. if err != nil {
  105. app.Error(c, fmt.Sprintf("get form err: %s", err.Error()))
  106. return
  107. }
  108. fileExt := utils.FileExt(file.Filename)
  109. attachKey := utils.RandomStr() + fileExt
  110. file.Filename = "data/" + attachKey
  111. if err := c.SaveUploadedFile(file, file.Filename); err != nil {
  112. app.Error(c, fmt.Sprintf("上传文件失败%s", err.Error()))
  113. return
  114. }
  115. wb, err := xlsx.OpenFile(file.Filename)
  116. if err != nil {
  117. app.Error(c, err.Error())
  118. return
  119. }
  120. sh, ok := wb.Sheet["Sheet1"]
  121. if !ok {
  122. fmt.Println("Sheet does not exist")
  123. return
  124. }
  125. typeList := make([]models.WorkType, 0)
  126. db.GetModel(map[string]interface{}{}, &typeList)
  127. datas := make([]map[string]interface{}, 0)
  128. headers := make([]string, 0)
  129. err = sh.ForEachRow(func(r *xlsx.Row) error {
  130. if r.GetCoordinate() <= 0 {
  131. err := r.ForEachCell(func(c *xlsx.Cell) error {
  132. headers = append(headers, c.String())
  133. return nil
  134. })
  135. if err != nil {
  136. return err
  137. }
  138. } else {
  139. var data models.Worker
  140. for i, header := range headers {
  141. value := r.GetCell(i).String()
  142. switch header {
  143. case "姓名":
  144. data.Name = value
  145. case "电话号码":
  146. data.Phone = value
  147. case "性别":
  148. sex := 0
  149. if value == "男" {
  150. sex = 1
  151. } else if value == "女" {
  152. sex = 2
  153. }
  154. data.Sex = sex
  155. case "年龄":
  156. age, _ := db.ToInt64(value)
  157. data.Age = int(age)
  158. case "身份证号":
  159. data.Idcode = value
  160. case "工种":
  161. types := make([]string, 0)
  162. nameList := strings.Split(value, ",")
  163. for _, name := range nameList {
  164. if name != "" {
  165. for _, typ := range typeList {
  166. if strings.Index(typ.Name, name) == 0 {
  167. types = append(types, db.ToString(typ.ID))
  168. break
  169. }
  170. }
  171. }
  172. }
  173. data.TypeIds = strings.Join(types, ",")
  174. case "所在区域":
  175. names := strings.Split(value, "/")
  176. code := ""
  177. out:
  178. for _, name := range names {
  179. list, err := geo.Lower(code)
  180. if err != nil {
  181. break
  182. }
  183. for _, l := range list {
  184. if n, ok := l["name"]; ok {
  185. if name == db.ToString(n) {
  186. if c, ok := l["code"]; ok {
  187. code = db.ToString(c)
  188. continue out
  189. }
  190. }
  191. }
  192. }
  193. break
  194. }
  195. data.Areacode = code
  196. case "是否买保险":
  197. insure := 0
  198. if value == "是" {
  199. insure = 1
  200. }
  201. data.Insure = insure
  202. case "保险开始日期":
  203. insure_start, _ := time.ParseInLocation("2006-01-02", value, time.Local)
  204. s := int(insure_start.Unix())
  205. if s > 0 {
  206. s = 0
  207. }
  208. data.InsureStart = s
  209. case "保险结束日期":
  210. insure_end, _ := time.ParseInLocation("2006-01-02", value, time.Local)
  211. s := int(insure_end.Unix())
  212. if s > 0 {
  213. s = 0
  214. }
  215. data.InsureEnd = s
  216. case "开户行":
  217. data.BankName = value
  218. case "银行卡号":
  219. data.BankCardNo = value
  220. default:
  221. }
  222. }
  223. if data.Name == "" || data.Phone == "" {
  224. return nil
  225. }
  226. var worker models.Worker
  227. db.GetModel(map[string]interface{}{
  228. "phone": data.Phone,
  229. "deleted_at": 0,
  230. }, &worker)
  231. da := map[string]interface{}{
  232. "name": data.Name,
  233. "phone": data.Phone,
  234. "sex": data.Sex,
  235. "age": data.Age,
  236. "idcode": data.Idcode,
  237. "type_ids": data.TypeIds,
  238. "areacode": data.Areacode,
  239. "insure": data.Insure,
  240. "insure_start": data.InsureStart,
  241. "insure_end": data.InsureEnd,
  242. "bank_name": data.BankName,
  243. "bank_card_no": data.BankCardNo,
  244. }
  245. if worker.ID == 0 {
  246. datas = append(datas, da)
  247. } else {
  248. if worker.Name == data.Name {
  249. err := db.UpdateModel(db.Type(worker), int64(worker.ID), da)
  250. if err != nil {
  251. return err
  252. }
  253. }
  254. }
  255. }
  256. return nil
  257. })
  258. if err != nil {
  259. app.Error(c, err.Error())
  260. return
  261. }
  262. db.InsertModels(db.Type(models.Worker{}), datas)
  263. app.Success(c, nil)
  264. }
  265. type QuoteOrder2ImportFrom struct {
  266. File string `json:"file"` // 注意:这里的 "file" 字段在 JSON 中是一个数组
  267. }
  268. type Files struct {
  269. Name string `json:"name"`
  270. UploadTime int64 `json:"upload_time"`
  271. URL string `json:"url"`
  272. }
  273. func QualityImport(c *gin.Context) {
  274. id := utils.ToInt(c.Param("id"))
  275. if id <= 0 {
  276. app.ErrorMsg(c, "id must be a number", nil)
  277. return
  278. }
  279. var form QuoteOrder2ImportFrom
  280. if app.Bind(c, &form) != nil {
  281. return
  282. }
  283. // 解析 JSON 数据
  284. files := []Files{}
  285. err := json.Unmarshal([]byte(form.File), &files)
  286. if err != nil {
  287. log.Fatalf("Error parsing JSON: %v", err)
  288. return
  289. }
  290. // 1. 下载到临时文件
  291. file, err := downloadExcelFromURL(files[0].URL)
  292. if err != nil {
  293. panic(err)
  294. }
  295. // 确保程序结束后删除临时文件
  296. defer os.Remove(file.Name())
  297. wb, err := xlsx.OpenFile(file.Name())
  298. if err != nil {
  299. fmt.Printf("读取错误", err.Error())
  300. app.Error(c, err.Error())
  301. return
  302. }
  303. sh, ok := wb.Sheet["Sheet1"]
  304. if !ok {
  305. fmt.Println("Sheet does not exist")
  306. return
  307. }
  308. typeList := make([]models.WorkQualityAccept, 0)
  309. db.GetModel(map[string]interface{}{}, &typeList)
  310. datas := make([]map[string]interface{}, 0)
  311. headers := make([]string, 0)
  312. err = sh.ForEachRow(func(r *xlsx.Row) error {
  313. if r.GetCoordinate() <= 0 {
  314. err := r.ForEachCell(func(c *xlsx.Cell) error {
  315. headers = append(headers, c.String())
  316. return nil
  317. })
  318. if err != nil {
  319. return err
  320. }
  321. } else {
  322. var data models.MatPickWork
  323. for i, header := range headers {
  324. value := r.GetCell(i).String()
  325. switch header {
  326. case "分类":
  327. qualityId := 0
  328. if value == "" {
  329. qualityId = id
  330. } else {
  331. if value == "泥工验收" {
  332. qualityId = 1
  333. } else if value == "真实交房验收" {
  334. qualityId = 2
  335. } else if value == "特殊交房验收" {
  336. qualityId = 3
  337. } else if value == "文明施工(形象)" {
  338. qualityId = 5
  339. } else if value == "放样" {
  340. qualityId = 6
  341. }
  342. }
  343. data.QualityAcceptId = qualityId
  344. case "名称":
  345. data.Name = value
  346. case "内容":
  347. data.Content = value
  348. case "施工标准":
  349. data.Photograph = value
  350. case "工期":
  351. data.Days = gconv.Int(value)
  352. default:
  353. }
  354. }
  355. da := map[string]interface{}{
  356. "quality_accept_id": data.QualityAcceptId,
  357. "name": data.Name,
  358. "content": data.Content,
  359. "photograph": data.Photograph,
  360. "days": data.Days,
  361. }
  362. datas = append(datas, da)
  363. }
  364. return nil
  365. })
  366. if err != nil {
  367. app.Error(c, err.Error())
  368. return
  369. }
  370. fmt.Println("dddd", datas)
  371. db.InsertModels(db.Type(models.WorkQualityAcceptItem{}), datas)
  372. app.Success(c, nil)
  373. }
  374. // 从URL下载Excel到临时文件,返回*os.File
  375. func downloadExcelFromURL(url string) (*os.File, error) {
  376. // 1. 发送HTTP请求获取Excel内容
  377. resp, err := http.Get(url)
  378. if err != nil {
  379. return nil, err
  380. }
  381. defer resp.Body.Close()
  382. // 检查响应状态
  383. if resp.StatusCode != http.StatusOK {
  384. return nil, os.ErrInvalid
  385. }
  386. // 2. 创建临时文件(基于URL中的文件名生成临时文件名)
  387. filename := filepath.Base(url)
  388. tempFile, err := os.CreateTemp("./", "xlsx_"+filename+"_*.xlsx")
  389. if err != nil {
  390. return nil, err
  391. }
  392. // 3. 将下载的内容写入临时文件
  393. _, err = io.Copy(tempFile, resp.Body)
  394. if err != nil {
  395. tempFile.Close()
  396. os.Remove(tempFile.Name()) // 失败时清理临时文件
  397. return nil, err
  398. }
  399. // 关闭临时文件(后续通过xlsx.OpenFile重新打开)
  400. tempFile.Close()
  401. return tempFile, nil
  402. }