|
@@ -0,0 +1,183 @@
|
|
|
+package front
|
|
|
+
|
|
|
+import (
|
|
|
+ util "app.yhyue.com/moapp/jybase/common"
|
|
|
+ "app.yhyue.com/moapp/jybase/encrypt"
|
|
|
+ "app.yhyue.com/moapp/jybase/go-xweb/xweb"
|
|
|
+ "app.yhyue.com/moapp/jybase/redis"
|
|
|
+ "app.yhyue.com/moapp/jypkg/public"
|
|
|
+ "bytes"
|
|
|
+ "encoding/base64"
|
|
|
+ "encoding/json"
|
|
|
+ "errors"
|
|
|
+ "fmt"
|
|
|
+ "image"
|
|
|
+ "image/jpeg"
|
|
|
+ "image/png"
|
|
|
+ "jy/src/jfw/config"
|
|
|
+ "log"
|
|
|
+ "net/http"
|
|
|
+ "sync"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+type Material struct {
|
|
|
+ *xweb.Action
|
|
|
+ //fileDownload xweb.Mapper `xweb:"/material/fileDownload"` //移动端消息三级页
|
|
|
+ linkTransfer xweb.Mapper `xweb:"/material/(\\w+)/(.*)"` //移动端消息三级页 物料id 渠道码
|
|
|
+}
|
|
|
+
|
|
|
+func init() {
|
|
|
+ xweb.AddAction(&Material{})
|
|
|
+ time.AfterFunc(2*time.Minute, SaveLogTask)
|
|
|
+}
|
|
|
+
|
|
|
+func (m *Material) FileDownload() error {
|
|
|
+ ossUrl := m.GetString("ossUrl")
|
|
|
+ if ossUrl == "" {
|
|
|
+ return errors.New("ossUrl参数缺失")
|
|
|
+ }
|
|
|
+ img, imgType, err := downloadImage(ossUrl)
|
|
|
+ if err != nil {
|
|
|
+ log.Println("文件下载失败:", ossUrl)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ imgBase, err := ImageToBase64(img, imgType)
|
|
|
+ if imgBase != "" && err == nil {
|
|
|
+ m.ServeJson(map[string]interface{}{
|
|
|
+ "imgBase": fmt.Sprintf("data:%s;base64,%s", imgType, imgBase),
|
|
|
+ })
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ return err
|
|
|
+}
|
|
|
+
|
|
|
+// 物料二维码链接或者图文链接中转接口 //链接格式 /material?mid=
|
|
|
+func (m *Material) LinkTransfer(mid, personChannel string) error {
|
|
|
+ sess := m.Session().GetMultiple()
|
|
|
+ mlid := encrypt.SE.DecodeString(mid)
|
|
|
+ types, _ := m.GetInteger("types")
|
|
|
+
|
|
|
+ realUrl, imgWebpage := "", ""
|
|
|
+ res := public.Mysql.SelectBySql("SELECT qrcode_url,img_webpage FROM bi_service.operating_materials WHERE id = ?", util.IntAll(mlid))
|
|
|
+ if res != nil && len(*res) > 0 {
|
|
|
+ realUrl = util.InterfaceToStr((*res)[0]["qrcode_url"])
|
|
|
+ imgWebpage = util.InterfaceToStr((*res)[0]["img_webpage"])
|
|
|
+ }
|
|
|
+ if realUrl == "" && imgWebpage == "" {
|
|
|
+ return m.Redirect(util.InterfaceToStr(config.Sysconfig["webdomain"]))
|
|
|
+ }
|
|
|
+ redis.Put("limitation", fmt.Sprintf("firstVisitTagByWX_%s", m.Session().Id()), fmt.Sprintf("materials_%s", personChannel), cacheTimeOut) //登录注册 用户标识
|
|
|
+ addLog(sess, m.Request, util.IntAll(mlid), types, personChannel, realUrl)
|
|
|
+ log.Println("重定向链接:", mlid, realUrl, imgWebpage)
|
|
|
+ if types == 1 {
|
|
|
+ return m.Redirect(imgWebpage)
|
|
|
+ } else {
|
|
|
+ return m.Redirect(realUrl)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func ImageToBase64(img image.Image, format string) (string, error) {
|
|
|
+ var buf bytes.Buffer
|
|
|
+ switch format {
|
|
|
+ case "jpeg", "jpg":
|
|
|
+ if err := jpeg.Encode(&buf, img, &jpeg.Options{Quality: 90}); err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+ case "png":
|
|
|
+ if err := png.Encode(&buf, img); err != nil { // 需导入 image/png
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ return "", fmt.Errorf("unsupported format: %s", format)
|
|
|
+ }
|
|
|
+ // Base64 编码
|
|
|
+ encoded := base64.StdEncoding.EncodeToString(buf.Bytes())
|
|
|
+ return encoded, nil
|
|
|
+}
|
|
|
+
|
|
|
+// 下载图片
|
|
|
+func downloadImage(url string) (image.Image, string, error) {
|
|
|
+ resp, err := http.Get(url)
|
|
|
+ if err != nil {
|
|
|
+ return nil, "", err
|
|
|
+ }
|
|
|
+ defer resp.Body.Close()
|
|
|
+
|
|
|
+ img, imgType, err := image.Decode(resp.Body)
|
|
|
+ if err != nil {
|
|
|
+ return nil, "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ return img, imgType, nil
|
|
|
+}
|
|
|
+
|
|
|
+// 内存缓存日志数量,超过此数量存库
|
|
|
+var nc = 100
|
|
|
+
|
|
|
+// 内存缓存日志map
|
|
|
+var arr = make([]map[string]interface{}, 0)
|
|
|
+
|
|
|
+// 对map的同步
|
|
|
+var lock sync.Mutex
|
|
|
+
|
|
|
+func addLog(sess map[string]interface{}, req *http.Request, mid, types int, parsonchannel, realUrl string) {
|
|
|
+ //log.Println("存储访问日志")
|
|
|
+ timeNow := time.Now()
|
|
|
+ agent := req.Header.Get("user-agent")
|
|
|
+ md, _ := json.Marshal(req.Form)
|
|
|
+ str := string(md)
|
|
|
+ logs := map[string]interface{}{
|
|
|
+ "types": types,
|
|
|
+ "materialid": mid,
|
|
|
+ "personchannel": parsonchannel,
|
|
|
+ "date": timeNow.Unix(),
|
|
|
+ "ip": req.Proto,
|
|
|
+ "refer": req.Referer(),
|
|
|
+ "year": timeNow.Year(),
|
|
|
+ "month": timeNow.Month(),
|
|
|
+ "day": timeNow.Day(),
|
|
|
+ "hour": timeNow.Hour(),
|
|
|
+ "minutes": timeNow.Minute(),
|
|
|
+ "mdescribe": str,
|
|
|
+ "client": agent,
|
|
|
+ "os": util.GetOS(agent),
|
|
|
+ "browse": util.GetBrowse(agent),
|
|
|
+ "method": req.Method,
|
|
|
+ "url": req.RequestURI,
|
|
|
+ "realUrl": realUrl,
|
|
|
+ }
|
|
|
+ if userId := util.InterfaceToStr(sess["mgoUserId"]); userId != "" {
|
|
|
+ logs["userid"] = userId
|
|
|
+ logs["nickname"] = util.InterfaceToStr(sess["s_nickname"])
|
|
|
+ logs["positionid"] = util.IntAll(sess["positionId"])
|
|
|
+ }
|
|
|
+
|
|
|
+ lock.Lock()
|
|
|
+ arr = append(arr, logs)
|
|
|
+ if len(arr) >= nc {
|
|
|
+ tmp := arr
|
|
|
+ arr = make([]map[string]interface{}, 0)
|
|
|
+ go func() {
|
|
|
+ log.Println("save..visit..log", len(tmp))
|
|
|
+ public.Mgo_Log.SaveBulk("material_logs", tmp...)
|
|
|
+ }()
|
|
|
+ }
|
|
|
+ lock.Unlock()
|
|
|
+}
|
|
|
+
|
|
|
+// 定时保存日志
|
|
|
+func SaveLogTask() {
|
|
|
+ lock.Lock()
|
|
|
+ if len(arr) >= 1 {
|
|
|
+ tmp := arr
|
|
|
+ arr = make([]map[string]interface{}, 0)
|
|
|
+ go func() {
|
|
|
+ log.Println("timer..save..visit..log", len(tmp))
|
|
|
+ public.Mgo_Log.SaveBulk("material_logs", tmp...)
|
|
|
+ }()
|
|
|
+ }
|
|
|
+
|
|
|
+ lock.Unlock()
|
|
|
+ time.AfterFunc(5*time.Minute, SaveLogTask)
|
|
|
+}
|