From 3a706d3378aa3626501370352963883fd2783558 Mon Sep 17 00:00:00 2001
From: zhangzengfei <zhangzengfei@smartai.com>
Date: 星期二, 28 十一月 2023 11:24:49 +0800
Subject: [PATCH] 添加appcenter,完善算法上传下载功能

---
 appcenter-service/models/dictionary.go   |   89 +
 appcenter-service/Makefile               |    7 
 appcenter-service/service/SysService.go  |  632 ++++++++
 appcenter-service/models/sdkChanSet.go   |   61 
 appcenter-service/service/AppService.go  |  317 ++++
 appcenter-service/service/SdkInstall.go  |  859 +++++++++++
 appcenter-service/controllers/app.go     |  218 ++
 appcenter-service/vo/sdk.go              |  102 +
 appcenter-service/controllers/sdkArg.go  |   30 
 appcenter-service/models/app.go          |  152 +
 appcenter-service/models/sdk.go          |  224 ++
 appcenter-service/service/Progress.go    |  222 ++
 appcenter-service/service/SdkDownLoad.go |  564 +++++++
 appcenter-service/controllers/sdk.go     |  501 ++++++
 appcenter-service/service/proc.go        |    6 
 appcenter-service/service/sdkService.go  |  170 ++
 appcenter-service/service/depend.go      |  189 ++
 appcenter-service/models/db.go           |   49 
 appcenter-service/main.go                |  132 +
 appcenter-service/models/sdkArg.go       |   52 
 20 files changed, 4,576 insertions(+), 0 deletions(-)

diff --git a/appcenter-service/Makefile b/appcenter-service/Makefile
new file mode 100644
index 0000000..9d3abe8
--- /dev/null
+++ b/appcenter-service/Makefile
@@ -0,0 +1,7 @@
+BUILD_VERSION := 1.1.1
+#APP_NAME      := myversion
+
+include ../module.dep
+
+
+
diff --git a/appcenter-service/controllers/app.go b/appcenter-service/controllers/app.go
new file mode 100644
index 0000000..67fad5c
--- /dev/null
+++ b/appcenter-service/controllers/app.go
@@ -0,0 +1,218 @@
+package controllers
+
+import (
+	"strconv"
+	"time"
+	"vamicro/appcenter-service/models"
+	"vamicro/appcenter-service/service"
+
+	"basic.com/valib/bhomeclient.git"
+	"basic.com/valib/logger.git"
+)
+
+type AppController struct {
+	bk bhomeclient.Broker
+}
+
+// @Security ApiKeyAuth
+// @Summary 鏌ユ壘宸插畨瑁呭拰鏈畨瑁呯殑搴旂敤鍒楄〃
+// @Description 鏌ユ壘宸插畨瑁呭拰鏈畨瑁呯殑搴旂敤鍒楄〃
+// @Produce json
+// @Tags 搴旂敤
+// @Param appName query string true "搴旂敤鍚嶇О"
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/app/findAllApp [get]
+func (ac AppController) FindAll(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	appName := c.Query("appName")
+	logger.Debug("FindAllApp appName:", appName)
+	list := service.GetAppList(appName)
+	if list == nil {
+		list = make([]service.AppWithShop, 0)
+	}
+	return &bhomeclient.Reply{Success: true, Data: list}
+}
+
+type DelApp struct {
+	AppId string `json:"appId" binding:"required"`
+}
+
+// @Security ApiKeyAuth
+// @Summary 鏍规嵁id鑾峰彇app淇℃伅
+// @Description 鏍规嵁id鑾峰彇app淇℃伅
+// @Produce json
+// @Tags 搴旂敤
+// @Param id query string true "搴旂敤id"
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/app/getAppInfo [get]
+func (ac AppController) GetAppInfo(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	id := c.Query("id")
+	logger.Debug("GetAppInfo id:", id)
+	if id == "" {
+		return &bhomeclient.Reply{Msg: "鍙傛暟鏈夎"}
+	}
+	var app models.App
+	rows, err := app.SelectById(id)
+	if err == nil && rows > 0 {
+		return &bhomeclient.Reply{Success: true, Data: app}
+	} else {
+		return &bhomeclient.Reply{Msg: "鑾峰彇澶辫触"}
+	}
+}
+
+// @Security ApiKeyAuth
+// @Summary 搴旂敤鍗歌浇
+// @Description 搴旂敤鍗歌浇
+// @Produce json
+// @Tags 搴旂敤
+// @Param arg body controllers.DelApp true "鍗歌浇鍙傛暟"
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/app/unInstall [post]
+func (ac AppController) UnInstall(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	var req DelApp
+	err := c.BindJSON(&req)
+	if err != nil {
+		return &bhomeclient.Reply{Msg: "鍙傛暟鏈夎"}
+	}
+
+	var sv service.SdkInstallService
+	if err := sv.PackUninstall(req.AppId); err != nil {
+		logger.Error("鎵цuninstall.sh 澶辫触", err.Error())
+		return &bhomeclient.Reply{Success: false, Msg: "鍗歌浇澶辫触"}
+	}
+
+	var appE models.App
+	if appE.DeleteById(req.AppId) {
+		return &bhomeclient.Reply{Success: true, Msg: "鍗歌浇鎴愬姛"}
+	} else {
+		return &bhomeclient.Reply{Success: false, Msg: "鍗歌浇澶辫触"}
+	}
+}
+
+// @Security ApiKeyAuth
+// @Summary 鑾峰彇鏈喘涔扮殑搴旂敤鍒楄〃
+// @Description 鑾峰彇鏈喘涔扮殑搴旂敤鍒楄〃
+// @Produce json
+// @Tags 搴旂敤
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/app/buyList [get]
+func (ac AppController) BuyList(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	appName := c.Query("appName")
+	logger.Debug("BuyList appName:", appName)
+	list := service.GetAppBuyList(appName)
+	if list == nil {
+		list = make([]models.App, 0)
+	}
+
+	return &bhomeclient.Reply{Success: true, Data: list}
+}
+
+// @Security ApiKeyAuth
+// @Summary 浣跨敤婵�娲荤爜婵�娲诲畨瑁呭簲鐢�
+// @Description 浣跨敤婵�娲荤爜婵�娲诲畨瑁呭簲鐢�
+// @Produce json
+// @Tags 搴旂敤
+// @Param code query string true "婵�娲荤爜"
+// @Param appId query string true "搴旂敤id"
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/app/active [get]
+func (ac AppController) Active(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	cod := c.Query("code")
+	appId := c.Query("appId")
+	if appId == "" { //code鍙互涓虹┖锛屼负0鍏冭喘
+		return &bhomeclient.Reply{Msg: "鍙傛暟鏈夎"}
+	}
+	d, err := service.ActiveApp(cod, appId)
+	if err == nil {
+		// 婵�娲绘垚鍔�
+		var app models.App
+		if err := app.UpdateCode(appId, cod); err != nil {
+			return &bhomeclient.Reply{Msg: err.Error()}
+		}
+		return &bhomeclient.Reply{Success: true, Data: d}
+	} else {
+		return &bhomeclient.Reply{Msg: err.Error()}
+	}
+}
+
+func (ac AppController) Save(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	var reqBody models.App
+	c.BindJSON(&reqBody)
+	if reqBody.Id == "" {
+		return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"}
+	}
+	reqBody.CreateTime = time.Now().Format("2006-01-02 15:04:05")
+	reqBody.CreateBy = "basic"
+	reqBody.UpdateBy = ""
+	reqBody.UpdateTime = ""
+	if err := reqBody.Save(); err == nil {
+		return &bhomeclient.Reply{Success: true, Msg: "淇濆瓨鎴愬姛"}
+	} else {
+		return &bhomeclient.Reply{Success: false, Msg: "淇濆瓨澶辫触"}
+	}
+}
+
+// @Security ApiKeyAuth
+// @Summary 鏄剧ず绠楁硶鎴栧簲鐢ㄧ殑浜у搧淇℃伅璇︽儏
+// @Description 鏄剧ず绠楁硶鎴栧簲鐢ㄧ殑浜у搧淇℃伅璇︽儏
+// @Produce json
+// @Tags 搴旂敤
+// @Param id query string true "绠楁硶鎴栧簲鐢ㄧ殑id"
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/app/detail [get]
+func (ac AppController) Detail(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	id := c.Query("id")
+	if id == "" {
+		return &bhomeclient.Reply{Msg: "鍙傛暟鏈夎"}
+	}
+	d, err := service.DetailByAppOrSdkId(id)
+	if err == nil {
+		return &bhomeclient.Reply{Success: true, Data: d}
+	} else {
+		return &bhomeclient.Reply{Msg: err.Error()}
+	}
+}
+
+// @Security ApiKeyAuth
+// @Summary 鑾峰彇鏇存柊鎻愰啋
+// @Description 鑾峰彇鏇存柊鎻愰啋
+// @Produce json
+// @Tags 搴旂敤
+// @Param id query string true "绠楁硶鎴栧簲鐢ㄧ殑id"
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/app/upgrade/notice [get]
+func (ac AppController) UpgradeNotice(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	userId := c.Header("Login_user_id")
+	notice := service.GetUpdateNotice()
+	LastNoticeTime, ok := notice.NoticeUser[userId]
+	if ok {
+		notice.LastNoticeTime = LastNoticeTime
+	}
+	return &bhomeclient.Reply{Success: true, Data: notice}
+}
+
+// @Security ApiKeyAuth
+// @Summary 寤惰繜鏇存柊鎻愰啋
+// @Description 寤惰繜鏇存柊鎻愰啋
+// @Produce json
+// @Tags 搴旂敤
+// @Param delay query string true "寤惰繜鎻愰啋鐨勭鏁�"
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/app/upgrade/notice [get]
+func (ac AppController) DelayNotice(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	userId := c.Header("Login_user_id")
+	delay := c.PostForm("delay")
+	delaySecond, err := strconv.Atoi(delay)
+	if nil != err {
+		return &bhomeclient.Reply{Msg: err.Error()}
+	}
+	service.DelayNotice(userId, delaySecond)
+	return &bhomeclient.Reply{Success: true, Msg: "鎿嶄綔鎴愬姛", Data: delaySecond}
+}
diff --git a/appcenter-service/controllers/sdk.go b/appcenter-service/controllers/sdk.go
new file mode 100644
index 0000000..0c66baf
--- /dev/null
+++ b/appcenter-service/controllers/sdk.go
@@ -0,0 +1,501 @@
+package controllers
+
+import (
+	"bytes"
+	"encoding/json"
+	"strconv"
+	"vamicro/appcenter-service/models"
+	"vamicro/appcenter-service/service"
+	"vamicro/appcenter-service/vo"
+
+	"basic.com/pubsub/protomsg.git"
+	"basic.com/valib/bhomeclient.git"
+	"basic.com/valib/logger.git"
+)
+
+type SdkController struct {
+}
+
+// @Summary 绠楁硶娉ㄥ唽
+// @Description 绠楁硶娉ㄥ唽
+// @Accept json
+// @Produce json
+// @Tags sdk
+// @Param reqMap body vo.SdkVo true "绠楁硶娉ㄥ唽鍙傛暟"
+// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"",success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"",success:false}"
+// @Router /data/api-v/sdk/register [POST]
+func (sc SdkController) Register(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	var reqBody vo.SdkRegisterVo
+
+	c.BindJSON(&reqBody)
+	if reqBody.Id == "" || reqBody.SdkType == "" || reqBody.SdkName == "" || reqBody.Icon == "" {
+		return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"}
+	}
+	logger.Debug("sdk register paramBody:", reqBody)
+	sv := service.NewSdkService(h.Bk)
+	if sv.Register(&reqBody) {
+		return &bhomeclient.Reply{Success: true, Msg: "绠楁硶娉ㄥ唽鎴愬姛"}
+	} else {
+		return &bhomeclient.Reply{Success: false, Msg: "娉ㄥ唽澶辫触"}
+	}
+}
+
+// @Summary 鏌ユ壘鎵�鏈夌畻娉�
+// @Description 鏌ユ壘鎵�鏈夌畻娉�
+// @Produce json
+// @Tags sdk
+// @Param sdkName query string false "鍙�夊弬鏁�"
+// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"绠楁硶鍒楄〃",success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"[]",success:false}"
+// @Router /data/api-v/sdk/findAllSdk [GET]
+func (sc SdkController) FindAllSdk(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	sdkName := c.Query("sdkName")
+	insStr := c.Query("installed") //濡傛灉鏈紶姝ゅ弬鏁帮紝鍒欒〃绀烘煡鎵�鏈�
+	userId := c.Header("Login_user_id")
+	ok := false
+	if insStr != "" {
+		ok = true
+	}
+	logger.Debugf("FindAllSdk sdkName=%v, insStr=%v, ok=%v, userId=%v", sdkName, insStr, ok, userId)
+	installed, _ := strconv.ParseBool(insStr)
+
+	sdks := service.GetSdkList(sdkName, insStr, userId) //鏈満宸插畨瑁呯殑绠楁硶
+	if ok && !installed {                               //浼犱簡installed鍙傛暟
+		nSdks := make([]service.SdkInsOrUpgrade, 0)
+		for _, s := range sdks {
+			if !s.Installed {
+				nSdks = append(nSdks, s)
+			}
+		}
+		return &bhomeclient.Reply{Success: true, Data: nSdks}
+	} else {
+		return &bhomeclient.Reply{Success: true, Data: sdks}
+	}
+}
+
+// @Summary 鏍规嵁id鑾峰彇绠楁硶淇℃伅
+// @Description 鏍规嵁id鑾峰彇绠楁硶淇℃伅
+// @Produce json
+// @Tags sdk
+// @Param id query string true "绠楁硶id锛屽繀濉�"
+// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"绠楁硶淇℃伅",success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"",success:false}"
+// @Router /data/api-v/sdk/getById [GET]
+func (sc SdkController) GetById(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	var sdk models.Sdk
+
+	id := c.Query("id")
+	if id == "" {
+		return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"}
+	}
+	rows, err := sdk.SelectById(id)
+	if err != nil || rows == 0 {
+		return &bhomeclient.Reply{Success: false, Msg: "璁板綍涓嶅瓨鍦�"}
+	}
+
+	var sdkVo = vo.SdkVo{}
+	sdkVo.Sdk = sdk
+	sdkVo.Args = sdk.GetSdkArgs(id, models.SCOPE_CAMERARULE)
+	return &bhomeclient.Reply{Success: true, Data: sdkVo}
+}
+
+// @Summary 鏍规嵁taskId鑾峰彇绠楁硶淇℃伅
+// @Description 鏍规嵁taskId鑾峰彇绠楁硶淇℃伅
+// @Produce json
+// @Tags sdk
+// @Param taskId query string true "taskId锛屽繀濉�"
+// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"绠楁硶淇℃伅",success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"",success:false}"
+// @Router /data/api-v/sdk/findByTaskId [GET]
+func (sc SdkController) FindByTaskId(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	taskId := c.Query("taskId")
+	if taskId == "" {
+		return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"}
+	}
+	var sdk models.Sdk
+	sdks, err := sdk.FindByTaskId(taskId)
+	if err != nil {
+		return &bhomeclient.Reply{Success: false, Msg: "鏌ヨ澶辫触"}
+	}
+	var sdkVoArr []vo.SdkVo
+	for _, sdk := range sdks {
+		sdkVo := vo.SdkVo{}
+		sdkVo.Sdk = sdk
+		sdkVo.Args = sdk.GetSdkArgs(sdk.Id, models.SCOPE_CAMERARULE)
+		sdkVoArr = append(sdkVoArr, sdkVo)
+	}
+
+	if err != nil {
+		return &bhomeclient.Reply{Success: false, Msg: "璁板綍涓嶅瓨鍦�"}
+	} else {
+		return &bhomeclient.Reply{Success: true, Data: sdkVoArr}
+	}
+}
+
+// @Summary 鑾峰彇鎵�鏈夌畻娉曢�氶亾鏁伴噺璁剧疆
+// @Description 鑾峰彇鎵�鏈夌畻娉曢�氶亾鏁伴噺璁剧疆
+// @Produce json
+// @Tags sdk
+// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"",success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"",success:false}"
+// @Router /data/api-v/sdk/getAllSdkChanSet [GET]
+func (sc SdkController) GetAllSdkChanSet(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	var scs models.SdkChanSet
+	list, err := scs.FindAll()
+	if err != nil {
+		return &bhomeclient.Reply{Success: false, Msg: "鍐呴儴閿欒"}
+	} else {
+		return &bhomeclient.Reply{Success: true, Data: list}
+	}
+}
+
+type SdkChanUpdateArg struct {
+	SdkType string `json:"sdk_type" binding:"required"`
+	ChanNum int    `json:"chan_num" binding:"required"`
+}
+
+// @Summary 鏇存柊绠楁硶閫氶亾鏁伴噺璁剧疆
+// @Description 鏇存柊绠楁硶閫氶亾鏁伴噺璁剧疆
+// @Produce json
+// @Tags sdk
+// @Param reqBody body controllers.SdkChanUpdateArg true "閫氶亾鏁伴噺璁剧疆鍙傛暟"
+// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"",success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"",success:false}"
+// @Router /data/api-v/sdk/updateSdkChanSet [POST]
+func (sc SdkController) UpdateSdkChanSet(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	var reqBody SdkChanUpdateArg
+	err := c.BindJSON(&reqBody)
+	if err != nil {
+		return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"}
+	}
+	var scs = models.SdkChanSet{
+		SdkType: reqBody.SdkType,
+		ChanNum: reqBody.ChanNum,
+	}
+	b, _ := scs.Update()
+	if b {
+		pMsg := protomsg.DbChangeMessage{
+			Table:  protomsg.TableChanged_T_SdkChanSet,
+			Action: protomsg.DbAction_Update,
+		}
+		pb, _ := json.Marshal(pMsg)
+		h.Bk.Publish("sdk-service", pb)
+		return &bhomeclient.Reply{Success: true, Msg: "鏇存柊鎴愬姛"}
+	} else {
+		return &bhomeclient.Reply{Success: false, Msg: "鏇存柊澶辫触"}
+	}
+}
+
+// @Summary 鏇存柊绠楁硶榛樿鍦烘櫙鍙傛暟
+// @Description 鏇存柊绠楁硶榛樿鍦烘櫙鍙傛暟
+// @Produce json
+// @Tags sdk
+// @Param reqBody body vo.SdkArgDefault true "閫氶亾鏁伴噺璁剧疆鍙傛暟"
+// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"",success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"",success:false}"
+// @Router /data/api-v/sdk/updateSdkArgConfig [POST]
+func (sc SdkController) UpdateSdkArgConfig(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	var reqBody vo.SdkArgDefault
+	err := c.BindJSON(&reqBody)
+	if err != nil {
+		return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"}
+	}
+	var sdk models.Sdk
+	rows, err := sdk.SelectById(reqBody.SdkId)
+	if err != nil || rows == 0 {
+		return &bhomeclient.Reply{Success: false, Msg: "绠楁硶id涓嶅瓨鍦�"}
+	}
+	bf := bytes.NewBuffer([]byte{})
+	jsonEncoder := json.NewEncoder(bf)
+	jsonEncoder.SetEscapeHTML(false)
+	jsonEncoder.Encode(reqBody.DefArgs)
+	sdk.ArgDef = bf.String()
+	b, err := sdk.Update()
+	if err != nil {
+		return &bhomeclient.Reply{Success: false, Msg: err.Error()}
+	}
+	if b {
+		pMsg := protomsg.DbChangeMessage{
+			Table:  protomsg.TableChanged_T_Sdk,
+			Action: protomsg.DbAction_Update,
+		}
+		pb, _ := json.Marshal(pMsg)
+		h.Bk.Publish("sdk-service", pb)
+		return &bhomeclient.Reply{Success: true, Msg: "鏇存柊鎴愬姛"}
+	} else {
+		return &bhomeclient.Reply{Success: false, Msg: "鏇存柊澶辫触"}
+	}
+}
+
+// @Summary 绠楁硶瀹夎鍖呬笂浼�(鍒嗗潡妫�鏌�)
+// @Description 绠楁硶瀹夎鍖呬笂浼�(鍒嗗潡妫�鏌�)
+// @Accept multipart/form-data
+// @Produce json
+// @Tags 绠楁硶
+// @Param chunkNumber formData int true "褰撳墠鏄鍑犱釜鍒嗗潡"
+// @Param chunkSize formData int true "姣忎竴鍧楃殑澶у皬"
+// @Param currentChunkSize formData int true "褰撳墠鍧楃殑澶у皬"
+// @Param identifier formData string true "鏁翠釜鏂囦欢鐨勫敮涓�鏍囪瘑锛岀洰鍓嶆槸md5"
+// @Param filename formData string true "鏂囦欢鍚嶇О"
+// @Param relativePath formData string true "鏂囦欢鍦ㄥ鎴风鐢佃剳鐨勮矾寰�"
+// @Param totalChunks formData int true "鏂囦欢鎬诲潡鏁�"
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/sdk/upload [get]
+func (sc SdkController) Upload(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	chunkNumber, e1 := strconv.Atoi(c.Query("chunkNumber"))
+	chunkSize, e2 := strconv.Atoi(c.Query("chunkSize"))
+	currentChunkSize, e3 := strconv.Atoi(c.Query("currentChunkSize"))
+	identifier := c.Query("identifier")
+	filename := c.Query("filename")
+	relativePath := c.Query("relativePath")
+	totalChunks, e5 := strconv.Atoi(c.Query("totalChunks"))
+	if identifier == "" || e1 != nil || e2 != nil || e3 != nil || e5 != nil {
+		return &bhomeclient.Reply{Msg: "鍙傛暟鏈夎"}
+	}
+	userId := c.Header("Login_user_id")
+	var arg = service.FileChunkCheckVo{
+		UserId:           userId,
+		FileName:         filename,
+		Identifier:       identifier,
+		RelativePath:     relativePath,
+		TotalChunks:      totalChunks,
+		ChunkNumber:      chunkNumber,
+		ChunkSize:        chunkSize,
+		CurrentChunkSize: currentChunkSize,
+	}
+	var sv service.SysService
+	if b := sv.CheckUpdateFile(&arg); b {
+		//c.String(http.StatusOK,"found")
+		return &bhomeclient.Reply{Success: true, Data: "found"}
+	} else {
+		//c.String(http.StatusNoContent,"")
+		return &bhomeclient.Reply{Success: true, Data: ""}
+	}
+}
+
+// @Security ApiKeyAuth
+// @Summary 绠楁硶瀹夎鍖呬笂浼�
+// @Description 绠楁硶瀹夎鍖呬笂浼�
+// @Accept multipart/form-data
+// @Produce json
+// @Tags 绠楁硶
+// @Param chunkNumber formData int true "褰撳墠鏄鍑犱釜鍒嗗潡"
+// @Param chunkSize formData int true "姣忎竴鍧楃殑澶у皬"
+// @Param currentChunkSize formData int true "褰撳墠鍧楃殑澶у皬"
+// @Param totalSize formData string true "鏂囦欢鎬诲ぇ灏�"
+// @Param identifier formData string true "鏁翠釜鏂囦欢鐨勫敮涓�鏍囪瘑锛岀洰鍓嶆槸md5"
+// @Param filename formData string true "鏂囦欢鍚嶇О"
+// @Param relativePath formData string true "鏂囦欢鍦ㄥ鎴风鐢佃剳鐨勮矾寰�"
+// @Param totalChunks formData int true "鏂囦欢鎬诲潡鏁�"
+// @Param file formData file true "鏂囦欢鍒嗙墖鍐呭"
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/sdk/upload [post]
+func (sc SdkController) UploadPack(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	chunkNumber, e1 := strconv.Atoi(c.PostForm("chunkNumber"))
+	chunkSize, e2 := strconv.Atoi(c.PostForm("chunkSize"))
+	currentChunkSize, e3 := strconv.Atoi(c.PostForm("currentChunkSize"))
+	totalSize, e4 := strconv.ParseInt(c.PostForm("totalSize"), 10, 64)
+	identifier := c.PostForm("identifier")
+	filename := c.PostForm("filename")
+	relativePath := c.PostForm("relativePath")
+	totalChunks, e5 := strconv.Atoi(c.PostForm("totalChunks"))
+	file, e6 := c.FormFile()
+	//file, header, e6 := c.Request.FormFile("file")
+	if identifier == "" || e1 != nil || e2 != nil || e3 != nil || e4 != nil || e5 != nil || e6 != nil {
+		return &bhomeclient.Reply{Msg: "鍙傛暟鏈夎"}
+	}
+	userId := c.Header("Login_user_id")
+	var arg = service.FileUploadVo{
+		UserId:           userId,
+		FileName:         filename,
+		Identifier:       identifier,
+		RelativePath:     relativePath,
+		TotalSize:        totalSize,
+		TotalChunks:      totalChunks,
+		ChunkNumber:      chunkNumber,
+		ChunkSize:        chunkSize,
+		CurrentChunkSize: currentChunkSize,
+		File:             file,
+		//Header:           header,
+	}
+	var sv service.SysService
+	if b, _, msg := sv.PatchUpload(&arg); b {
+		//if isComplete { //涓婁紶瀹屾瘯闇�瑕佽嚜鍔ㄨЕ鍙戝畨瑁�
+		//	var sv service.SdkInstallService
+		//	if b,err := sv.SdkInstall(identifier, filename);b {
+		//		util.ResponseFormat(c,&code.Code{http.StatusOK, true, "绠楁硶瀹夎鎴愬姛"},"绠楁硶瀹夎鎴愬姛")
+		//		return
+		//	} else {
+		//		util.ResponseFormat(c,&code.Code{http.StatusBadRequest, false, "绠楁硶瀹夎澶辫触"},err.Error())
+		//		return
+		//	}
+		//}
+		return &bhomeclient.Reply{Success: true, Msg: "涓婁紶瀹屾垚"}
+	} else {
+		return &bhomeclient.Reply{Msg: msg}
+	}
+}
+
+// @Security ApiKeyAuth
+// @Summary 涓婁紶瀹屾垚鑾峰彇瀹夎淇℃伅
+// @Description 涓婁紶瀹屾垚鑾峰彇瀹夎淇℃伅
+// @Produce json
+// @Tags 绠楁硶
+// @Param identifier formData string true "鏁翠釜鏂囦欢鐨勫敮涓�鏍囪瘑锛岀洰鍓嶆槸md5"
+// @Param filename formData string true "鏂囦欢鍚嶇О"
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/sdk/showInstallInfo [post]
+func (sc SdkController) ShowInstallInfo(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	identifier := c.Query("identifier")
+	filename := c.Query("filename")
+	logger.Debug("showInstallInfo identifier:", identifier, "filename:", filename)
+	if identifier == "" || filename == "" {
+		return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"}
+	}
+	var sv service.SdkInstallService
+	b, d, err := sv.ShowInstallInfo(identifier, filename)
+	if b {
+		return &bhomeclient.Reply{Success: true, Data: d}
+	} else {
+		return &bhomeclient.Reply{Msg: err.Error()}
+	}
+}
+
+// @Security ApiKeyAuth
+// @Summary 涓婁紶瀹屾垚寮�濮嬪畨瑁�
+// @Description 涓婁紶瀹屾垚寮�濮嬪畨瑁�
+// @Produce json
+// @Tags 绠楁硶
+// @Param identifier formData string true "鏁翠釜鏂囦欢鐨勫敮涓�鏍囪瘑锛岀洰鍓嶆槸md5"
+// @Param filename formData string true "鏂囦欢鍚嶇О"
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/sdk/install [post]
+func (sc SdkController) Install(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	identifier := c.Query("identifier")
+	filename := c.Query("filename")
+	logger.Debug("showInstallInfo identifier:", identifier, "filename:", filename)
+	if identifier == "" || filename == "" {
+		return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"}
+	}
+
+	var sv service.SdkInstallService
+	if b, err := sv.PackInstall(identifier, filename, h); b {
+		return &bhomeclient.Reply{Success: true, Msg: "瀹夎鎴愬姛"}
+	} else {
+		return &bhomeclient.Reply{Msg: err.Error()}
+	}
+}
+
+// @Security ApiKeyAuth
+// @Summary 鍗歌浇绠楁硶
+// @Description 鍗歌浇绠楁硶
+// @Produce json
+// @Tags 绠楁硶
+// @Param reqBody body controllers.DelSdk true "鍗歌浇鍙傛暟"
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/sdk/unInstall [post]
+func (sc SdkController) UnInstall(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	var reqBody DelSdk
+	err := c.BindJSON(&reqBody)
+	if err != nil {
+		return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"}
+	}
+	var sdkE models.Sdk
+	if sdkE.DeleteById(reqBody.SdkId) {
+		pMsg := protomsg.DbChangeMessage{
+			Table:  protomsg.TableChanged_T_Sdk,
+			Action: protomsg.DbAction_Delete,
+		}
+		pb, _ := json.Marshal(pMsg)
+		h.Bk.Publish(service.ProcName, pb)
+		return &bhomeclient.Reply{Success: true, Msg: "鍗歌浇鎴愬姛"}
+	} else {
+		return &bhomeclient.Reply{Success: false, Msg: "鍗歌浇澶辫触"}
+	}
+}
+
+// @Security ApiKeyAuth
+// @Summary 浠庡晢鍩庝笅杞芥垨鍗囩骇绠楁硶
+// @Description 浠庡晢鍩庝笅杞芥垨鍗囩骇绠楁硶
+// @Produce json
+// @Tags 绠楁硶
+// @Param path query string true "绠楁硶id"
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/sdk/sdkDownload [get]
+func (sc SdkController) SdkDownLoad(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	id := c.Query("path")
+	if id == "" {
+		return &bhomeclient.Reply{Msg: "涓嬭浇绠楁硶鍙傛暟鏈夎"}
+	}
+
+	if service.IsInstalling(id) {
+		return &bhomeclient.Reply{Success: true, Msg: "瀹夎涓紝璇风◢鍊�..."}
+	}
+
+	if b, err := service.DownloadOrUpgrade(id, h); b {
+		return &bhomeclient.Reply{Success: true, Msg: "绠楁硶瀹夎鎴愬姛"}
+	} else {
+		return &bhomeclient.Reply{Msg: err.Error()}
+	}
+}
+
+// @Security ApiKeyAuth
+// @Summary 搴旂敤涓績涓湭璐拱鐨勭畻娉曞垪琛�
+// @Description 搴旂敤涓績涓湭璐拱鐨勭畻娉曞垪琛�
+// @Produce json
+// @Tags 绠楁硶
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/sdk/buyList [get]
+func (sc SdkController) BuyList(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	sdkName := c.Query("sdkName")
+	logger.Debug("BuyList sdkName:", sdkName)
+	var sv service.SdkInstallService
+	list := sv.GetBuyList(sdkName)
+	if list == nil {
+		list = make([]service.SdkWithArg, 0)
+	}
+
+	return &bhomeclient.Reply{Success: true, Data: list}
+}
+
+// @Security ApiKeyAuth
+// @Summary 浣跨敤婵�娲荤爜婵�娲诲畨瑁呯畻娉�
+// @Description 浣跨敤婵�娲荤爜婵�娲诲畨瑁呯畻娉�
+// @Produce json
+// @Tags 绠楁硶
+// @Param code query string true "婵�娲荤爜"
+// @Param sdkId query string true "绠楁硶id"
+// @Success 200 {string} json "{"code":200, msg:"", success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"", success:false}"
+// @Router /data/api-v/sdk/active [get]
+func (sc SdkController) Active(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
+	cod := c.Query("code")
+	sdkId := c.Query("sdkId")
+	if sdkId == "" {
+		return &bhomeclient.Reply{Msg: "绠楁硶id涓嶈兘涓虹┖"}
+	}
+	var sv service.SdkInstallService
+	d, err := sv.Active(cod, sdkId)
+	if err == nil {
+		// 婵�娲绘垚鍔�
+		var sdk models.Sdk
+		if err := sdk.UpdateCode(sdkId, cod); err != nil {
+			return &bhomeclient.Reply{Msg: err.Error()}
+		}
+		return &bhomeclient.Reply{Success: true, Data: d}
+	} else {
+		return &bhomeclient.Reply{Msg: err.Error()}
+	}
+}
+
+type DelSdk struct {
+	SdkId string `json:"sdkId" binding:"required"`
+}
diff --git a/appcenter-service/controllers/sdkArg.go b/appcenter-service/controllers/sdkArg.go
new file mode 100644
index 0000000..fd99075
--- /dev/null
+++ b/appcenter-service/controllers/sdkArg.go
@@ -0,0 +1,30 @@
+package controllers
+
+import (
+	"basic.com/valib/bhomeclient.git"
+	"vamicro/appcenter-service/models"
+)
+
+type SdkArgController struct {
+
+}
+
+// @Summary 鑾峰彇绠楁硶鍙傛暟
+// @Description 鑾峰彇绠楁硶鍙傛暟
+// @Produce json
+// @Tags 绠楁硶鍙傛暟
+// @Param sdkId query string true "绠楁硶id"
+// @Param scope query string true "绠楁硶鍙傛暟鑼冨洿(TASKRULE銆丆AMERARULE)"
+// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"",success:true}"
+// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"",success:false}"
+// @Router /data/api-v/sdkArg/getSdkArgs [get]
+func (controller SdkArgController) GetSdkArgs(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply{
+	sdkId := c.Query("sdkId")
+	scope := c.Query("scope")
+	if sdkId== "" || scope == "" || (scope !=models.SCOPE_TASKRULE && scope !=models.SCOPE_CAMERARULE){
+		return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"}
+	}
+	var sdk models.Sdk
+	args := sdk.GetSdkArgs(sdkId, scope)
+	return &bhomeclient.Reply{Success: true, Data: args}
+}
\ No newline at end of file
diff --git a/appcenter-service/main.go b/appcenter-service/main.go
new file mode 100644
index 0000000..2cf2c2d
--- /dev/null
+++ b/appcenter-service/main.go
@@ -0,0 +1,132 @@
+package main
+
+import (
+	"basic.com/valib/bhomeclient.git"
+	"basic.com/valib/bhomedbapi.git"
+	"basic.com/valib/logger.git"
+	"basic.com/valib/version.git"
+	"context"
+	"flag"
+	"net/http"
+	_ "net/http/pprof"
+	"os"
+	"os/signal"
+	"syscall"
+	"vamicro/appcenter-service/controllers"
+	"vamicro/appcenter-service/models"
+	"vamicro/appcenter-service/service"
+	"vamicro/config"
+	versionControlS "vamicro/version-control/service"
+)
+
+var (
+	procName = service.ProcName
+	proc = &bhomeclient.ProcInfo{
+		Name: procName, //杩涚▼鍚嶇О
+		ID: procName, //杩涚▼id
+		Info: "", //杩涚▼鐨勬弿杩颁俊鎭紝鐢ㄤ簬鍖哄垎鍚屼竴杩涚▼鍚嶇О涓嬪涓繘绋�
+	}
+	env = flag.String("e", "pro", "")
+)
+
+func init() {
+	flag.Parse()
+	vaversion.Usage()
+
+	config.Init(*env)
+	// 鏃ュ織鍒濆鍖�
+	var logFile = config.LogConf.Path + "vamicro-"+procName+".log"
+	logger.InitLogger(logFile, config.LogConf.Level, config.LogConf.MaxSize, config.LogConf.MaxBackups, config.LogConf.MaxAge)
+	logger.Info("log init success !")
+}
+
+func main(){
+	models.Init()
+	defer models.CloseDB()
+
+	ctx, cancel := context.WithCancel(context.Background())
+	fm,pubTopics := initFuncMap()
+	var reg = &bhomeclient.RegisterInfo {
+		Proc: *proc,
+		Channel: nil,
+		PubTopic: pubTopics,
+		SubTopic:  []string{versionControlS.SysUpdateConfigTopic},
+	}
+
+	q := make(chan os.Signal, 1)
+	signal.Notify(q, os.Interrupt, os.Kill, syscall.SIGTERM)
+
+	ms, err := bhomeclient.NewMicroNode(ctx, q, config.Server.AnalyServerId, reg, logger.Debug)
+	if err !=nil {
+		return
+	}
+
+	bhomedbapi.InitLog(logger.Debug)
+	bhomedbapi.InitGetNetNode(ms.GetLocalNetNodeByTopic)
+	bhomedbapi.InitDoReq(ms.RequestOnly)
+	go ms.StartServer(fm)
+	go handleSubMsg(ctx, ms)
+	go service.SelfUpdateStart(ctx) //鑷姩鏇存柊
+	go service.NoticeTick(ctx)//鏇存柊鎻愰啋
+	// pprof 鐢ㄤ簬鍒嗘瀽鎬ц兘
+	go func() {
+		logger.Info(http.ListenAndServe("0.0.0.0:7073", nil))
+	}()
+
+	<-q
+	ms.DeRegister()
+	cancel()
+	ms.Free()
+}
+
+const urlPrefix = "/data/api-v"
+func initFuncMap() (map[string]bhomeclient.MicroFunc,[]string) {
+	funcMap := make(map[string]bhomeclient.MicroFunc)
+	sc := new(controllers.SdkController)
+	sa := new(controllers.SdkArgController)
+	ac := new(controllers.AppController)
+
+	funcMap[urlPrefix+"/sdk/register"] = sc.Register
+	funcMap[urlPrefix+"/sdk/getById"] = sc.GetById
+	funcMap[urlPrefix+"/sdk/findAllSdk"] = sc.FindAllSdk
+	funcMap[urlPrefix+"/sdk/getAllSdkChanSet"] = sc.GetAllSdkChanSet
+	funcMap[urlPrefix+"/sdk/findByTaskId"] = sc.FindByTaskId
+	funcMap[urlPrefix+"/sdk/updateSdkArgConfig"] = sc.UpdateSdkArgConfig
+	funcMap[urlPrefix+"/sdk/updateSdkChanSet"] = sc.UpdateSdkChanSet
+	funcMap[urlPrefix+"/sdkArg/getSdkArgs"] = sa.GetSdkArgs
+	funcMap[urlPrefix+"/sdk/upload"] = sc.Upload
+	funcMap[urlPrefix+"/sdk/uploadPack"] = sc.UploadPack
+	funcMap[urlPrefix+"/sdk/install"] = sc.Install
+	funcMap[urlPrefix+"/sdk/unInstall"] = sc.UnInstall
+	funcMap[urlPrefix+"/sdk/buyList"] = sc.BuyList
+	funcMap[urlPrefix+"/sdk/active"] = sc.Active
+	funcMap[urlPrefix+"/sdk/sdkDownload"] = sc.SdkDownLoad
+	funcMap[urlPrefix+"/sdk/showInstallInfo"] = sc.ShowInstallInfo
+
+	funcMap[urlPrefix+"/app/findAllApp"] = ac.FindAll
+	funcMap[urlPrefix+"/app/getAppInfo"] = ac.GetAppInfo
+	funcMap[urlPrefix+"/app/unInstall"] = ac.UnInstall
+	funcMap[urlPrefix+"/app/buyList"] = ac.BuyList
+	funcMap[urlPrefix+"/app/active"] = ac.Active
+	funcMap[urlPrefix+"/app/detail"] = ac.Detail
+	funcMap[urlPrefix+"/app/upgrade/notice"] = ac.UpgradeNotice
+	funcMap[urlPrefix+"/app/upgrade/notice/delay"] = ac.DelayNotice
+
+	var pubTopics []string
+	for key,_ := range funcMap {
+		pubTopics = append(pubTopics, key)
+	}
+	return funcMap, pubTopics
+}
+
+func handleSubMsg(ctx context.Context, ms *bhomeclient.MicroNode) {
+	for {
+		select {
+		case <-ctx.Done():
+			return
+		case msg := <-ms.SubCh:
+			logger.Debug("handleSubMsg recv sub msg:", msg)
+			service.PersistentWrapper(string(msg.Topic), msg.Data)
+		}
+	}
+}
\ No newline at end of file
diff --git a/appcenter-service/models/app.go b/appcenter-service/models/app.go
new file mode 100644
index 0000000..a877d69
--- /dev/null
+++ b/appcenter-service/models/app.go
@@ -0,0 +1,152 @@
+package models
+
+type App struct {
+	Id        string `gorm:"column:id;primary_key;type:varchar(50);unique;not null;" json:"id"`
+	Name      string `gorm:"column:name" json:"name"`                        //涓枃鍚嶇О,eg:绠楀姏绠$悊
+	Package   string `gorm:"column:package;unique;not null;" json:"package"` //鑻辨枃鍚嶅瓧
+	Type      string `gorm:"column:type" json:"type"`                        //鏂板紑椤甸潰:"1",寮规锛�"2"
+	Url       string `gorm:"column:url" json:"url"`                          //eg: /view/analysisPower/
+	Title     string `gorm:"column:title" json:"title"`                      //鎵撳紑寮规鎴栨柊寮�椤甸潰椤堕儴鏄剧ず
+	Width     int    `gorm:"column:width" json:"width"`                      //瀹氫箟寮规鐨勯粯璁ゅ搴�
+	Height    int    `gorm:"column:height" json:"height"`                    //瀹氫箟寮规鐨勯粯璁ら珮搴�
+	IconBlob  string `gorm:"column:iconBlob" json:"iconBlob"`                //鍥剧墖鐨刡ase64
+	IconBlob2 string `gorm:"column:iconBlob2" json:"iconBlob2"`              //绗簩濂楀浘鐗囩殑base64
+	Icon      string `gorm:"column:icon" json:"icon"`                        //鍥剧墖鐩稿璺緞鎴栬�呮槸iconfont
+	Version   string `gorm:"column:version;default:''" json:"version"`
+
+	CreateTime string `gorm:"column:create_time" json:"create_time"`
+	CreateBy   string `gorm:"column:create_by" json:"create_by"`
+	UpdateTime string `gorm:"column:update_time" json:"update_time"`
+	UpdateBy   string `gorm:"column:update_by" json:"update_by"`
+	IsDefault  bool   `gorm:"column:isDefault;default:0;" json:"isDefault"`
+
+	ProcName string `gorm:"column:procName" json:"procName"` //搴旂敤鐨勫悗绔湇鍔″悕锛岀郴缁熺洃鎺у櫒涓渶瑕佺敤,鐢卞晢鍩庣缁存姢
+
+	Price        float32 `json:"price"`                                   //鍟嗗煄绔环鏍�
+	CanUpOrIns   bool    `json:"canUpOrIns"`                              //鏄惁鍙畨瑁呮垨鍗囩骇
+	Platforms    []PtIns `json:"platforms"`                               //鍙�傞厤鐨勫钩鍙颁俊鎭�
+	ActivateCode string  `gorm:"column:activateCode" json:"activateCode"` // 婵�娲荤爜
+}
+
+type PtIns struct {
+	Platform string `json:"platform"`
+	Version  string `json:"version"`
+	VGpus    string `json:"vGpus"`
+}
+
+func (App) TableName() string {
+	return "t_app"
+}
+
+func (a *App) SelectById(id string) (rows int64, err error) {
+	dbSelect := db.Table(a.TableName()).Where("id=?", id).First(&a)
+	if dbSelect.Error != nil || dbSelect.RowsAffected == 0 {
+		return 0, dbSelect.Error
+	}
+	return dbSelect.RowsAffected, nil
+}
+
+func (a *App) Save() (err error) {
+	tx := db.Table(a.TableName()).Begin()
+	if tx.Error != nil {
+		return tx.Error
+	}
+
+	if err := tx.Save(&a).Error; err != nil {
+		tx.Rollback()
+		return err
+	}
+
+	err = tx.Commit().Error
+	if err == nil {
+		return nil
+	}
+	return err
+}
+
+func (a *App) Update() (result bool, err error) {
+	entity := App{}
+
+	rows, err := entity.SelectById(a.Id)
+	if err != nil {
+		return false, err
+	}
+	if rows == 0 {
+		return false, err
+	}
+	if err := db.Table("t_app").Where("id=?", a.Id).Update(&a).Error; err != nil {
+		return false, err
+	}
+	return true, nil
+}
+
+func (a *App) UpdateCode(appId, code string) (err error) {
+	if err := db.Table("t_app").Where("id=?", appId).Update("activateCode", code).Error; err != nil {
+		return err
+	}
+	return nil
+}
+
+func (a *App) DeleteById(id string) (result bool) {
+	updateResult := db.Exec("delete from "+a.TableName()+" where id=?", id)
+	if updateResult.Error != nil || updateResult.RowsAffected == 0 {
+		return false
+	}
+	return true
+}
+
+func (a *App) FindAll(name string) (rows []App, err error) {
+	mutex.Lock()
+	defer mutex.Unlock()
+
+	if name != "" {
+		if err := db.Table(a.TableName()).Where("name like ?", name).Order("create_time asc").Find(&rows).Error; err != nil {
+			return nil, err
+		}
+		return rows, nil
+	} else {
+		if err := db.Table(a.TableName()).Find(&rows).Error; err != nil {
+			return nil, err
+		}
+		return rows, nil
+	}
+}
+
+func (a *App) FindAllMap() map[string]App {
+	m := make(map[string]App)
+	list, _ := a.FindAll("")
+	if list != nil {
+		for _, s := range list {
+			m[s.Id] = s
+		}
+	}
+	return m
+}
+
+func (a *App) Total(inputText string) (int, error) {
+	var total int
+	sql := "select count(1) as total from " + a.TableName() + " where 1=1"
+	if inputText != "" {
+		sql += " and name like '%" + inputText + "%'"
+	}
+	err := db.Raw(sql).Count(&total).Error
+	if err != nil {
+		return 0, err
+	}
+	return total, nil
+}
+
+func (a *App) FindByPage(inputText string, page int, size int) (list []App, err error) {
+	offset := (page - 1) * size
+	sql := "select * from " + a.TableName() + " where 1=1"
+
+	if inputText != "" {
+		sql += " and name like '%" + inputText + "%'"
+	}
+	sql += " order by create_time desc"
+	err = db.Raw(sql).Offset(offset).Limit(size).Find(&list).Error
+	if err != nil {
+		return nil, err
+	}
+	return list, nil
+}
diff --git a/appcenter-service/models/db.go b/appcenter-service/models/db.go
new file mode 100644
index 0000000..bb96b0d
--- /dev/null
+++ b/appcenter-service/models/db.go
@@ -0,0 +1,49 @@
+package models
+
+import (
+	"basic.com/valib/logger.git"
+	"github.com/jinzhu/gorm"
+	_ "github.com/jinzhu/gorm/dialects/sqlite"
+	"strings"
+	"sync"
+	"vamicro/config"
+)
+
+var db *gorm.DB
+var err error
+var mutex sync.Mutex
+
+// Init creates a connection to mysql database and
+// migrates any new models
+func Init() {
+	db, err = gorm.Open(config.DBconf.Name, "../config/appcenter.db")
+	if err != nil {
+		logger.Debug("db open error ", err)
+	}
+	db.LogMode(true)
+	//db.SetLogger(&DbLogger{})
+	db.AutoMigrate(&Sdk{}, &SdkArgEntity{}, &SdkChanSet{}, &Dictionary{}, &App{})
+
+	//娣诲姞榛樿鐨勯�氶亾璁剧疆
+	addSdkChanSet()
+}
+
+func addSdkChanSet() {
+	var sqls []string
+	sqls = append(sqls, "INSERT INTO sdk_chan_set(`sdk_type`,`chan_num`) SELECT 'Yolo',3 where not exists (select 1 from sdk_chan_set where sdk_type='Yolo');")
+	sqls = append(sqls, "INSERT INTO sdk_chan_set(`sdk_type`,`chan_num`) SELECT 'FaceDetect',9 where not exists (select 1 from sdk_chan_set where sdk_type='FaceDetect');")
+	sqls = append(sqls, "INSERT INTO sdk_chan_set(`sdk_type`,`chan_num`) SELECT 'Plate',9 where not exists (select 1 from sdk_chan_set where sdk_type='Plate');")
+	sqls = append(sqls, "INSERT INTO sdk_chan_set(`sdk_type`,`chan_num`) SELECT 'HumanTrack',9 where not exists (select 1 from sdk_chan_set where sdk_type='HumanTrack');")
+	sqls = append(sqls, "INSERT INTO sdk_chan_set(`sdk_type`,`chan_num`) SELECT 'FaceExtract',200 where not exists (select 1 from sdk_chan_set where sdk_type='FaceExtract');")
+	sqls = append(sqls, "INSERT INTO sdk_chan_set(`sdk_type`,`chan_num`) SELECT 'FaceCompare',2000 where not exists (select 1 from sdk_chan_set where sdk_type='FaceCompare');")
+	db.Exec(strings.Join(sqls, ""))
+}
+
+// GetDB ...
+func GetDB() *gorm.DB {
+	return db
+}
+
+func CloseDB() {
+	db.Close()
+}
diff --git a/appcenter-service/models/dictionary.go b/appcenter-service/models/dictionary.go
new file mode 100644
index 0000000..c274702
--- /dev/null
+++ b/appcenter-service/models/dictionary.go
@@ -0,0 +1,89 @@
+package models
+
+type Dictionary struct {
+	Id          string `gorm:"primary_key" json:"id"`
+	Value       string `gorm:"column:value" json:"value"`       //鍊�
+	Name        string `gorm:"column:name" json:"name"`        //鍚嶇О
+	Type        string `gorm:"column:type" json:"type"`        //绫诲瀷
+	Description string `gorm:"column:description" json:"description"` //鎻忚堪
+	Sort 		int    `gorm:"column:sort;default:1" json:"sort"`
+	ParentId    string `gorm:"column:parent_id;default:0" json:"parent_id"`
+}
+
+const (
+	TYPE_RULECOMPUTEBETWEEN = "RULECOMPUTEBETWEEN"
+	TYPE_RULECOMPUTE        = "RULECOMPUTE"
+	TYPE_TYPECOMPUTE        = "TYPECOMPUTE"
+	TYPE_ALARMLEVEL         = "ALARMLEVEL"
+	TYPE_EVENTRULETOPIC     = "EVENTRULETOPIC" //浜嬩欢鎺ㄩ�佷竴绾т富棰�
+	TYPE_MONITORLEVEL       = "MONITORLEVEL"
+	TYPE_PERSONSEX          = "PERSONSEX"
+	TYPE_AGEDESC            = "AGEDESC"
+	TYPE_PERSONRACE         = "PERSONRACE"
+	TYPE_EVENTTYPECOMPUTE   = "EVENTTYPECOMPUTE"
+)
+
+const (
+	EVENTRULETOPIC_CAMERA      = "camera" //鎽勫儚鏈�
+	EVENTRULETOPIC_CAMERA_NAME = "name"
+	EVENTRULETOPIC_CAMERA_ADDR = "addr"
+
+	EVENTRULETOPIC_DBTABLE = "dbtable" //搴曞簱
+	EVENTRULETOPIC_TASK    = "task"    //浠诲姟
+
+	EVENTRULETOPIC_PERSON              = "person"       //浜哄憳
+	EVENTRULETOPIC_PERSON_MONITORLEVEL = "monitorLevel" //绛夌骇
+	EVENTRULETOPIC_PERSON_AGE          = "age"          //骞撮緞
+	EVENTRULETOPIC_PERSON_SEX          = "sex"          //鎬у埆
+	EVENTRULETOPIC_PERSON_RACE         = "race"         //绉嶆棌
+	EVENTRULETOPIC_PERSON_OTHREINFO    = "otherInfo"    //鍏朵粬淇℃伅
+
+	EVENTRULETOPIC_ALARMLEVEL = "alarmLevel" //鎶ヨ绛夌骇
+)
+
+func (Dictionary) TableName() string {
+	return "dictionary"
+}
+
+func (dic *Dictionary) FindAll() (dics []Dictionary, err error) {
+	if err := db.Table("dictionary").Find(&dics).Error; err != nil {
+		return nil, err
+	}
+	return dics, nil
+}
+
+func (dic *Dictionary) FindByType(dicType string) (dics []Dictionary, err error) {
+	if err := db.Table("dictionary").Where("type=?", dicType).Scan(&dics).Error; err != nil {
+		return nil, err
+	}
+	return dics, nil
+}
+
+func (dic *Dictionary) FindByParentId(parentId string) (dics []Dictionary, err error) {
+	if err := db.Table("dictionary").Where("parent_id=?", parentId).Scan(&dics).Error; err != nil {
+		return nil, err
+	}
+	return dics, nil
+}
+
+func (dic *Dictionary) Insert() (bool, error) {
+	if err := db.Table("dictionary").Create(&dic).Error; err != nil {
+		return false, err
+	}
+	return true, nil
+}
+
+func (dic *Dictionary) Update() (bool, error) {
+	if err := db.Table("dictionary").Update(&dic).Error; err != nil {
+		return false, err
+	}
+	return true, nil
+}
+
+func (dic *Dictionary) SelectById(id string) (bool, error) {
+	result := db.Table("dictionary").Where("id=?", id).First(&dic)
+	if result.Error != nil {
+		return false, err
+	}
+	return result.RecordNotFound(), nil
+}
diff --git a/appcenter-service/models/sdk.go b/appcenter-service/models/sdk.go
new file mode 100644
index 0000000..8e4e295
--- /dev/null
+++ b/appcenter-service/models/sdk.go
@@ -0,0 +1,224 @@
+package models
+
+import (
+	"strings"
+	"time"
+
+	"basic.com/pubsub/protomsg.git"
+	"basic.com/valib/logger.git"
+)
+
+const (
+	RecordNotFound = "record not found"
+)
+
+type Sdk struct {
+	Id         string `gorm:"column:id;primary_key" json:"id"`
+	IpcId      string `gorm:"column:ipc_id" json:"ipc_id"`                                  //鐪熸鐨勭畻娉昳d(瀵逛簬yolo鏉ヨ锛屽彧鍒涘缓涓�涓猧pc)
+	SdkType    string `gorm:"column:sdk_type" json:"sdk_type"`                              //浜鸿劯妫�娴嬶細FaceDetect,浜鸿劯鎻愬彇锛欶aceExtract,浜鸿劯姣斿锛欶aceCompare,琛屼负锛歒olo
+	SdkName    string `gorm:"column:sdk_name" json:"sdk_name" example:"浜鸿劯妫�娴�"`               //绠楁硶鍚嶇О
+	Icon       string `gorm:"column:icon" json:"icon"`                                      //绠楁硶鍥炬爣
+	Url        string `gorm:"column:url" json:"url" example:"http://ip:port/govideo/sdk/1"` //绠楁硶涓嬭浇鍦板潃
+	CreateTime string `gorm:"column:create_time" json:"create_time"`
+	CreateBy   string `gorm:"column:create_by" json:"create_by"`
+	UpdateTime string `gorm:"column:update_time" json:"update_time"`
+	Enable     bool   `gorm:"column:enable;default:1" json:"enable"`                           //鏄惁鍚敤
+	DelFlag    int    `gorm:"column:del_flag;default:0" json:"del_flag"`                       //閫昏緫鍒犻櫎
+	IconBlob   string `gorm:"column:iconBlob;type:text;" json:"iconBlob"`                      //鍥剧墖
+	IconBlob2  string `gorm:"column:iconBlob2;type:text;" json:"iconBlob2"`                    //绗簩濂楀浘鐗�
+	Version    string `gorm:"column:version;type:varchar(50);default:'1.0.0';" json:"version"` //鐗堟湰鍙�
+	EnTrack    bool   `gorm:"column:enTrack;default:1" json:"enTrack"`                         //鏄惁寮�鍚窡韪�
+	ArgDef     string `gorm:"column:argDef" json:"argDef"`                                     //绠楁硶鍙傛暟榛樿閰嶇疆
+	RuleSo     string `gorm:"column:rule_so" json:"rule_so"`                                   //瑙勫垯鐢ㄧ殑so鍚嶇О
+
+	AuthState3rd int    `gorm:"column:authState3rd;default:0" json:"authState3rd"` //绗笁鏂规巿鏉冪姸鎬� 0:鏈巿鏉冿紝1锛氬凡鎺堟潈锛�2锛氬凡杩囨湡
+	MacCode3rd   string `gorm:"column:macCode3rd" json:"macCode3rd"`               //绗笁鏂圭敓鎴愮殑鏈哄櫒鐮�
+	License3rd   string `gorm:"column:license3rd" json:"license3rd"`               //绗笁鏂规巿鏉冪爜
+	Expire3rd    string `gorm:"column:expire3rd" json:"expire3rd"`                 //杩囨湡鏃堕棿
+
+	BaseVersion  string  `gorm:"column:baseVersion" json:"baseVersion"`   //鍩虹绠楁硶鐗堟湰
+	Price        float32 `json:"price"`                                   //鍟嗗煄绔环鏍�
+	ActivateCode string  `gorm:"column:activateCode" json:"activateCode"` // 婵�娲荤爜
+}
+
+const (
+	AuthState3rd_UnAuth  = 0
+	AuthState3rd_Authed  = 1
+	AuthState3rd_expired = 2
+)
+
+func (sdk Sdk) Copy2ProtoSdk() protomsg.Sdk {
+	return protomsg.Sdk{
+		Id:         sdk.Id,
+		IpcId:      sdk.IpcId,
+		SdkType:    sdk.SdkType,
+		SdkName:    sdk.SdkName,
+		Icon:       sdk.Icon,
+		Url:        sdk.Url,
+		CreateTime: sdk.CreateTime,
+		UpdateTime: sdk.UpdateTime,
+		CreateBy:   sdk.CreateBy,
+		Enable:     sdk.Enable,
+		DelFlag:    int32(sdk.DelFlag),
+		IconBlob:   sdk.IconBlob,
+		IconBlob2:  sdk.IconBlob2,
+		Version:    sdk.Version,
+		EnTrack:    sdk.EnTrack,
+		ArgDef:     sdk.ArgDef,
+		RuleSo:     sdk.RuleSo,
+	}
+}
+
+func (Sdk) TableName() string {
+	return "sdks"
+}
+
+// 鏍规嵁绠楁硶id鏌ユ壘绠楁硶淇℃伅
+func (sdk *Sdk) SelectById(id string) (rows int64, err error) {
+	dbSelect := db.Table("sdks").Where("id=?", id).First(&sdk)
+	if dbSelect.Error != nil && dbSelect.Error.Error() != RecordNotFound {
+		return 0, dbSelect.Error
+	}
+	return dbSelect.RowsAffected, nil
+}
+
+func (sdk *Sdk) SelectBySdkType(sdkType string) (exist bool, model Sdk) {
+	dbSelect := db.Table("sdks").Where("sdk_type=?", sdkType).First(&model)
+	if dbSelect.Error != nil || dbSelect.RowsAffected == 0 {
+		return false, model
+	}
+	return dbSelect.RecordNotFound(), model
+}
+
+// 鏌ユ壘鎵�鏈夌畻娉�
+func (sdk *Sdk) FindAll(name string) (rows []Sdk, err error) {
+	mutex.Lock()
+	defer mutex.Unlock()
+
+	t := time.Now()
+	defer func() {
+		logger.Debugf("FindAll costTime=%v, name=%v", time.Since(t), name)
+	}()
+
+	if name != "" {
+		if err := db.Table("sdks").Where("sdk_name like ?", name).Order("sdk_name asc").Find(&rows).Error; err != nil {
+			logger.Debug("err: ", err)
+			return nil, err
+		}
+		return rows, nil
+	} else {
+		if err := db.Table("sdks").Order("sdk_name asc").Find(&rows).Error; err != nil {
+			logger.Debug("err: ", err)
+			return nil, err
+		}
+		return rows, nil
+	}
+}
+
+func (sdk *Sdk) FindAllMap() map[string]Sdk {
+	m := make(map[string]Sdk)
+	rows, e := sdk.FindAll("")
+	if e == nil && rows != nil {
+		for _, r := range rows {
+			m[r.Id] = r
+		}
+	}
+	return m
+}
+
+// 鏍规嵁浠诲姟id鏌ユ壘鎵�鏈夌殑绠楁硶
+func (sdk *Sdk) FindByTaskId(taskId string) (sdks []Sdk, err error) {
+	if err := db.Raw("select * from sdks where id in (select sdkid from task_sdks where taskid=? order by sort asc)", taskId).Scan(&sdks).Error; err != nil {
+		return sdks, err
+	}
+
+	return sdks, nil
+}
+
+// 绠楁硶鎻掑叆
+func (sdk *Sdk) Insert() (err error) {
+	tx := db.Table("sdks").Begin()
+	if tx.Error != nil {
+		return tx.Error
+	}
+
+	if err := tx.Create(&sdk).Error; err != nil {
+		tx.Rollback()
+		return err
+	}
+
+	err = tx.Commit().Error
+	if err == nil {
+		return nil
+	}
+	return err
+}
+
+// 绠楁硶鏇存柊
+func (sdk *Sdk) Update() (result bool, err error) {
+
+	dbSdk := Sdk{}
+
+	rows, err := dbSdk.SelectById(sdk.Id)
+	if err != nil {
+		return false, err
+	}
+	if rows == 0 {
+		return false, err //鏁版嵁搴撹繖鏉¤褰曚笉瀛樺湪
+	}
+	if err := db.Table(sdk.TableName()).Where("id=?", sdk.Id).Update(&sdk).Error; err != nil {
+		return false, err
+	}
+
+	return true, nil
+}
+
+func (sdk *Sdk) UpdateCode(sdkId, code string) (err error) {
+	if err := db.Table(sdk.TableName()).Where("id=?", sdkId).Update("activateCode", code).Error; err != nil {
+		return err
+	}
+	return nil
+}
+
+func (sdk *Sdk) DeleteById(id string) (result bool) {
+	//鍒犻櫎绠楁硶闇�瑕佸叧鑱斿垹闄ゆ墍鏈変笌绠楁硶鐩稿叧鐨勪换鍔′俊鎭�
+	updateResult := db.Exec("delete from sdks where id=?", id)
+	if updateResult.Error != nil || updateResult.RowsAffected == 0 {
+		return false
+	}
+
+	return true
+}
+
+// 鏍规嵁鍙傛暟鑼冨洿鑾峰彇绠楁硶鍙傛暟鍒楄〃
+func (sdk *Sdk) GetSdkArgs(sdkId string, scope string) []SdkArg {
+	var sdkArgEntity SdkArgEntity
+	argArr := make([]SdkArg, 0)
+	if sdkArgs, err := sdkArgEntity.FindBySdk(sdkId); err == nil {
+		for _, argEntity := range sdkArgs {
+			if strings.Contains(argEntity.Scope, scope) {
+				argArr = append(argArr, SdkArg{
+					Alias:           argEntity.Alias,
+					Name:            argEntity.Name,
+					Type:            argEntity.Type,
+					Must:            argEntity.Must,
+					Range:           argEntity.Range,
+					DefaultValue:    argEntity.DefaultValue,
+					DefaultOperator: argEntity.DefaultOperator,
+					Sort:            argEntity.Sort,
+					Unit:            argEntity.Unit,
+					ArgType:         argEntity.ArgType,
+				})
+			}
+		}
+	}
+	return argArr
+}
+
+func (sdk *Sdk) Update3rdLicense(sdkId string, lce3rd string, state3rd int) bool {
+	updateResult := db.Exec("update "+sdk.TableName()+" set license3rd=?,authState3rd=? where id=?", lce3rd, state3rd, sdkId)
+	if updateResult.Error != nil || updateResult.RowsAffected == 0 {
+		return false
+	}
+	return true
+}
diff --git a/appcenter-service/models/sdkArg.go b/appcenter-service/models/sdkArg.go
new file mode 100644
index 0000000..c16c00b
--- /dev/null
+++ b/appcenter-service/models/sdkArg.go
@@ -0,0 +1,52 @@
+package models
+
+type SdkArgEntity struct {
+	Id string `gorm:"primary_key;column:id" json:"id"`
+	SdkId string `gorm:"column:sdk_id" json:"sdk_id"`
+	Scope string `gorm:"column:scope" json:"scope"`
+	SdkArg
+}
+
+//绠楁硶鍙傛暟瀹氫箟
+type SdkArg struct {
+	Alias   string `gorm:"column:alias" json:"alias"`   //鍙傛暟鐨勫埆鍚�
+	Name  string `gorm:"column:name" json:"name"`  //鍙傛暟鍚嶇О
+	Type  string `gorm:"column:type" json:"type"`  //鍙傛暟绫诲瀷(鏁存暟锛屽瓧绗︿覆鎴栨暟缁�)
+	ArgType string `gorm:"column:arg_type" json:"arg_type"`
+	Must  bool   `gorm:"column:must" json:"must"`  //鏄惁蹇呭~
+	Unit string `gorm:"column:unit" json:"unit"` //鍗曚綅
+	Range string `gorm:"column:range" json:"range"` //鍊肩殑鑼冨洿锛宔g锛�0,100琛ㄧず浠�0鍒�100
+	DefaultValue string `gorm:"column:default_value" json:"default_value"`
+	DefaultOperator string `gorm:"column:default_operator" json:"default_operator"`
+	Sort  int    `gorm:"column:sort;default:1" json:"sort"`  //鍙傛暟椤哄簭
+}
+
+const (
+	SCOPE_CAMERARULE ="CAMERARULE"//鍦ㄦ憚鍍忔満瑙勫垯閰嶇疆椤甸潰鏄剧ず鐨勫弬鏁�
+	SCOPE_TASKRULE = "TASKRULE"//鍦ㄤ换鍔$畻娉曢厤缃〉闈㈡樉绀虹殑鍙傛暟
+)
+
+func (SdkArgEntity) TableName() string {
+	return "sdk_arg"
+}
+
+func (entity *SdkArgEntity) Insert() (bool,error){
+	if err :=db.Table("sdk_arg").Create(&entity).Error;err!=nil {
+		return false,err
+	}
+	return true,nil
+}
+func (entity *SdkArgEntity) Update() (bool,error) {
+	if err :=db.Table("sdk_arg").Update(&entity).Error;err!=nil {
+		return false,err
+	}
+	return true,nil
+}
+
+//鏍规嵁sdk鍜屽弬鏁拌寖鍥存煡鎵惧搴旂殑绠楁硶鍙傛暟
+func (entity *SdkArgEntity) FindBySdk(sdkId string) (arr []SdkArgEntity,err error) {
+	if err := db.Table("sdk_arg").Where("sdk_id=?",sdkId).Scan(&arr).Error;err !=nil {
+		return nil,err
+	}
+	return arr,nil
+}
diff --git a/appcenter-service/models/sdkChanSet.go b/appcenter-service/models/sdkChanSet.go
new file mode 100644
index 0000000..9394008
--- /dev/null
+++ b/appcenter-service/models/sdkChanSet.go
@@ -0,0 +1,61 @@
+package models
+
+type SdkChanSet struct {
+	SdkType 		string 		`gorm:"column:sdk_type;primary_key" json:"sdk_type"`
+	ChanNum 		int 		`gorm:"column:chan_num;default:16" json:"chan_num"`
+	ConfidenceInc 	int      	`gorm:"column:confidenceInc;default:5" json:"confidenceInc"`
+	MinMovePos 		int      	`gorm:"column:minMovePos;default:1" json:"minMovePos"`
+}
+
+func (SdkChanSet) TableName() string {
+	return "sdk_chan_set"
+}
+
+func (scs *SdkChanSet) FindAll() (list []SdkChanSet,err error) {
+	if err := db.Table(scs.TableName()).Find(&list).Error; err != nil {
+		return []SdkChanSet{}, err
+	}
+	return list, nil
+}
+
+func (scs *SdkChanSet) SelectBySdkType(sdkType string) (exist bool,model SdkChanSet){
+	dbSelect := db.Table(scs.TableName()).Where("sdk_type=?",sdkType).First(&model)
+	if dbSelect.Error != nil || dbSelect.RowsAffected == 0 {
+		return false, model
+	}
+	return dbSelect.RecordNotFound(), model
+}
+
+func (scs *SdkChanSet) Insert() (err error) {
+	tx := db.Table(scs.TableName()).Begin()
+	if tx.Error != nil {
+		return tx.Error
+	}
+
+	if err := tx.Create(&scs).Error; err != nil {
+		tx.Rollback()
+		return err
+	}
+
+	err =tx.Commit().Error
+	if err == nil{
+		return nil
+	}
+	return err
+}
+
+func (scs *SdkChanSet) Update() (b bool, err error) {
+	result :=db.Exec("update ? set chan_num=? where sdk_type=?",scs.TableName(), scs.ChanNum, scs.SdkType)
+	if result.Error != nil {
+		return false, err
+	}
+	return result.RowsAffected>0,nil
+}
+
+func (scs *SdkChanSet) Delete(sdkType string) bool {
+	updateResult := db.Exec("delete from ? where sdk_type=?", scs.TableName(),sdkType)
+	if updateResult.Error != nil || updateResult.RowsAffected == 0 {
+		return false
+	}
+	return true
+}
\ No newline at end of file
diff --git a/appcenter-service/service/AppService.go b/appcenter-service/service/AppService.go
new file mode 100644
index 0000000..849764c
--- /dev/null
+++ b/appcenter-service/service/AppService.go
@@ -0,0 +1,317 @@
+package service
+
+import (
+	"basic.com/valib/bhomedbapi.git"
+	"basic.com/valib/licence.git"
+	"basic.com/valib/logger.git"
+	"encoding/json"
+	"errors"
+	"strconv"
+	"time"
+	"vamicro/appcenter-service/models"
+	"vamicro/config"
+	"vamicro/extend/util"
+)
+
+type AppWithShop struct {
+	models.App
+	RemoteVersion string `json:"remoteVersion"` //鍟嗗煄浠撳簱鐗堟湰鍙�
+	Installed     bool   `json:"installed"`     //鏄惁宸插畨瑁�
+	IsUpgrade     bool   `json:"isUpgrade"`     //鏄惁闇�瑕佸崌绾�
+	ProgressMsg   string `json:"progressMsg"`   //瀹夎鎴栧崌绾ц繘搴�
+}
+
+type ProtoApps struct {
+	List []models.App `json:"list"`
+}
+
+func GetAppList(appName string) []AppWithShop {
+	var api models.App
+	insList, err := api.FindAll(appName) //鏈湴宸插畨瑁呮墍鏈夊簲鐢�,甯﹂『搴�
+	if err != nil {
+		logger.Debug("findall err:", err.Error())
+	}
+	installedApps := make([]AppWithShop, len(insList))
+	localAppIdArr := make([]string, 0)
+	iv := make(map[string]string)
+	localAppM := make(map[string]AppWithShop)
+	for idx, ls := range insList {
+		siou := AppWithShop{
+			Installed: true,
+		}
+
+		siou.App = ls
+		localAppM[siou.Package] = siou
+		installedApps[idx] = siou
+		iv[ls.Id] = ls.Version
+
+		localAppIdArr = append(localAppIdArr, siou.Id)
+	}
+
+	nInsApps := make([]AppWithShop, 0)
+
+	//杩滅鍙敤鐨勫簲鐢�
+	remoteApps := findAllMyApp(localAppIdArr, iv, appName)
+	if remoteApps != nil {
+		//logger.Debug("len(remoteApps):", len(remoteApps))
+
+		for _, ap := range remoteApps {
+			if v, ok := localAppM[ap.Package]; ok { //鏈湴宸插畨瑁�
+				ls := v
+				ls.Name = ap.Name //浠ュ晢鍩庝笂鐨勫悕绉颁负鍑�
+
+				ls.Installed = true
+
+				if ap.CanUpOrIns { //鍒ゆ柇鐗堟湰鍙锋槸鍚﹂渶瑕佸崌绾�
+					ls.ProgressMsg = ""
+					ls.IsUpgrade = shouldVersionBeUpgrade(ls.Version, ap.Version)
+					ls.RemoteVersion = ap.Version //杩滅鐨勭増鏈彿
+
+					if ip, insB := insIngMap.Load(ap.Id); insB {
+						iPgs := ip.(*InsProgress)
+						ls.ProgressMsg = iPgs.Status + strconv.Itoa(iPgs.Progress) + "%"
+					}
+				}
+				localAppM[ap.Package] = ls
+				for index, es := range installedApps {
+					if es.Package == ap.Package {
+						installedApps[index] = ls
+						break
+					}
+				}
+			} else { //鏈湴鏈畨瑁咃紝闇�瑕佸畨瑁�
+				if ap.CanUpOrIns {
+					bIns := AppWithShop{
+						RemoteVersion: ap.Version,
+						IsUpgrade:     false,
+						Installed:     false,
+						ProgressMsg:   "",
+					}
+					if ip, insB := insIngMap.Load(ap.Id); insB {
+						iPgs := ip.(*InsProgress)
+						bIns.ProgressMsg = iPgs.Status + strconv.Itoa(iPgs.Progress) + "%"
+					}
+					bIns.App = ap
+					nInsApps = append(nInsApps, bIns)
+				}
+			}
+		}
+	}
+
+	return append(installedApps, nInsApps...)
+}
+
+func findAllMyApp(localAppIdArr []string, iv map[string]string, inputTxt string) []models.App {
+	url := "http://" + util.GetShopUrl() + "/data/api-s/app/myApp"
+	machineCode := licence.GetMachineCode()
+	//logger.Debug("url:", url, "machineCode:", machineCode)
+	paramBody := map[string]interface{}{
+		"serverId":      config.Server.AnalyServerId,
+		"machineCode":   machineCode,
+		"localAppIdArr": localAppIdArr,
+		"iv":            iv,
+		"inputTxt":      inputTxt,
+	}
+	header := map[string]string{
+		"Authorization": token,
+	}
+	respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*20)
+	if err != nil {
+		logger.Debug("DoPostRequest err:", err)
+		return nil
+	}
+	var res bhomedbapi.Result
+	if err = json.Unmarshal(respBody, &res); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return nil
+	}
+	bytes, _ := json.Marshal(res.Data)
+	var pa ProtoApps
+	if err := json.Unmarshal(bytes, &pa); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return nil
+	}
+
+	return pa.List
+}
+
+// inputTxt杩囨护鏉′欢
+func GetAppBuyList(inputTxt string) []models.App {
+	url := "http://" + util.GetShopUrl() + "/data/api-s/app/buyList"
+	machineCode := licence.GetMachineCode()
+	logger.Debug("url:", url, "machineCode:", machineCode)
+
+	var api models.App
+	localApps, _ := api.FindAll("") //鏈湴宸插畨瑁呮墍鏈夊簲鐢�,甯﹂『搴�
+	if localApps == nil {
+		localApps = make([]models.App, 0)
+	}
+
+	localAppIdArr := make([]string, 0)
+	iv := make(map[string]string)
+	for _, ls := range localApps {
+		iv[ls.Id] = ls.Version
+
+		localAppIdArr = append(localAppIdArr, ls.Id)
+	}
+	paramBody := map[string]interface{}{
+		"serverId":      config.Server.AnalyServerId,
+		"machineCode":   machineCode,
+		"localAppIdArr": localAppIdArr,
+		"iv":            iv,
+		"inputTxt":      inputTxt,
+	}
+	header := map[string]string{
+		"Authorization": token,
+	}
+	respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*20)
+	if err != nil {
+		logger.Debug("DoPostRequest err:", err)
+		return nil
+	}
+	var res bhomedbapi.Result
+	if err = json.Unmarshal(respBody, &res); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return nil
+	}
+	bytes, _ := json.Marshal(res.Data)
+	var ss shopApps
+	if err := json.Unmarshal(bytes, &ss); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return nil
+	}
+
+	var resultArr []models.App
+	installAppM := make(map[string]models.App)
+
+	for _, ia := range localApps {
+		installAppM[ia.Package] = ia
+	}
+
+	if ss.Apps != nil {
+		for _, rs := range ss.Apps {
+			if _, ok := installAppM[rs.Package]; !ok {
+				resultArr = append(resultArr, rs)
+			}
+		}
+	}
+
+	return resultArr
+}
+
+type shopApps struct {
+	Apps []models.App `json:"apps"`
+}
+
+func ActiveApp(cod string, appId string) (interface{}, error) {
+	//浣跨敤婵�娲荤爜婵�娲诲簲鐢�
+	url := "http://" + util.GetShopUrl() + "/data/api-s/app/activeByAINode"
+	machineCode := licence.GetMachineCode()
+	if machineCode == "" {
+		logger.Debug("鑾峰彇鏈哄櫒鐮佸け璐�")
+		return nil, errors.New("鑾峰彇鏈哄櫒鐮佸け璐�")
+	}
+	paramBody := map[string]interface{}{
+		"code":        cod,
+		"appId":       appId,
+		"machineCode": machineCode,
+		"serverId":    config.Server.AnalyServerId,
+	}
+	header := map[string]string{
+		"Authorization": token,
+	}
+	respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*60)
+	if err != nil {
+		logger.Debug("DoPostRequest err:", err)
+		return nil, err
+	}
+	var res bhomedbapi.Result
+	if err = json.Unmarshal(respBody, &res); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return nil, err
+	}
+	if !res.Success {
+		logger.Debug("res.Data:", res.Data)
+		return nil, errors.New(res.Msg)
+	}
+
+	return res.Data, nil
+}
+
+func SaveApp(reqBody models.App) bool {
+	if reqBody.Id == "" {
+		return false
+	}
+	reqBody.CreateTime = time.Now().Format("2006-01-02 15:04:05")
+	reqBody.CreateBy = "basic"
+	reqBody.UpdateBy = ""
+	reqBody.UpdateTime = ""
+	if err := reqBody.Save(); err == nil {
+		return true
+	} else {
+		logger.Error("娉ㄥ唽搴旂敤澶辫触:", err.Error())
+	}
+
+	return false
+}
+
+func DetailByAppOrSdkId(id string) (interface{}, error) {
+	url := "http://" + util.GetShopUrl() + "/data/api-s/product/detailByAppOrSdkId"
+	machineCode := licence.GetMachineCode()
+	if machineCode == "" {
+		return nil, errors.New("鑾峰彇鏈哄櫒鐮佸け璐�")
+	}
+	paramBody := map[string]interface{}{
+		"id":          id,
+		"machineCode": machineCode,
+		"serverId":    config.Server.AnalyServerId,
+	}
+	header := map[string]string{
+		"Authorization": token,
+	}
+	respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*10)
+	if err != nil {
+		logger.Debug("DoPostRequest err:", err)
+		return nil, errors.New("璇锋眰鍟嗗煄澶辫触")
+	}
+	var res bhomedbapi.Result
+	if err = json.Unmarshal(respBody, &res); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return nil, err
+	}
+	if !res.Success {
+		logger.Debug("res.Data:", res.Data)
+		return nil, errors.New(res.Msg)
+	}
+	var app models.App
+	row, err := app.SelectById(id)
+	var mapData = res.Data.(map[string]interface{})
+	detail := mapData["detail"].(map[string]interface{})
+	detail["installed"] = false
+	detail["isUpgrade"] = false                                 //闇�瑕佸崌绾�
+	detail["remoteVersion"] = detail["productVersion"].(string) //闇�瑕佸崌绾�
+	detail["version"] = ""
+	if row > 0 {
+		detail["installed"] = true
+		if shouldVersionBeUpgrade(app.Version, detail["productVersion"].(string)) { //鍒ゆ柇鐗堟湰鍙锋槸鍚﹂渶瑕佸崌绾�
+			detail["isUpgrade"] = true                                  //闇�瑕佸崌绾�
+			detail["remoteVersion"] = detail["productVersion"].(string) //闇�瑕佸崌绾�
+		}
+		detail["version"] = app.Version
+	} else {
+		var sdk models.Sdk
+		row, err = sdk.SelectById(id)
+		if row > 0 {
+			var mapData = res.Data.(map[string]interface{})
+			detail["installed"] = true
+			detail := mapData["detail"].(map[string]interface{})
+			if shouldVersionBeUpgrade(sdk.Version, detail["productVersion"].(string)) { //鍒ゆ柇鐗堟湰鍙锋槸鍚﹂渶瑕佸崌绾�
+				detail["isUpgrade"] = true                                  //闇�瑕佸崌绾�
+				detail["remoteVersion"] = detail["productVersion"].(string) //闇�瑕佸崌绾�
+			}
+			detail["version"] = sdk.Version
+		}
+	}
+
+	return res.Data, nil
+}
diff --git a/appcenter-service/service/Progress.go b/appcenter-service/service/Progress.go
new file mode 100644
index 0000000..64eb033
--- /dev/null
+++ b/appcenter-service/service/Progress.go
@@ -0,0 +1,222 @@
+package service
+
+import (
+	"basic.com/valib/logger.git"
+	"errors"
+	"fmt"
+	"io"
+	"net/http"
+	"os"
+	"path"
+	"strconv"
+	"strings"
+	"sync"
+	"vamicro/extend/util"
+)
+
+//姝e湪瀹夎鍒楄〃
+var insIngMap sync.Map
+
+//鍒ゆ柇鏄惁鍦ㄥ畨瑁呬腑
+func IsInstalling(id string) bool {
+	_, ok := insIngMap.Load(id)
+	return ok
+}
+
+//瀹夎杩涘害
+type InsProgress struct {
+	Status   string `json:"status"`
+	Progress int    `json:"progress"`
+	Size     uint64 `json:"size"`
+	IsDone   bool   `json:"isDone"` //涓嶇鎴愬姛鎴栬�呭け璐ワ紝鏍囧織鏈瀹夎宸插畬鎴�
+}
+
+const (
+	InsStatus_Downloading     = "涓嬭浇涓�..."
+	InsStatus_Err             = "瀹夎鍖呬笅杞藉け璐�"
+	InsStatus_UnPackErr       = "瀹夎鍖呰В鍘嬪け璐�"
+	InsStatus_PackageChecking = "瀹夎鍖呮牎楠屼腑..."
+	InsStatus_CheckErr        = "瀹夎鍖呮牎楠屽け璐�"
+	InsStatus_Installing      = "瀹夎涓�..."
+	InsStatus_InstallErr      = "瀹夎澶辫触"
+	InsStatus_Done            = "宸插畨瑁�"
+)
+
+type WriteCounter struct {
+	Total uint64
+
+	iPgs *InsProgress
+}
+
+func (wc *WriteCounter) PrintProgress() {
+	logger.Info(strings.Repeat(" ", 35))
+	//logger.Info("Downloading... ",humanize.Bytes(wc.Total)," complete")
+
+	percent := (wc.Total * 100) / wc.iPgs.Size
+
+	wc.iPgs.Progress = int(percent)
+}
+
+func (wc *WriteCounter) Write(p []byte) (int, error) {
+	n := len(p)
+	wc.Total += uint64(n)
+	wc.PrintProgress()
+	return n, nil
+}
+
+//涓嬭浇鏂囦欢
+func DownloadFile(fPath string, url string, iProgress *InsProgress) error {
+	f, err := os.Create(fPath)
+	if err != nil {
+		return err
+	}
+	resp, err := http.Get(url)
+	if err != nil {
+		f.Close()
+		return err
+	}
+	defer resp.Body.Close()
+	counter := &WriteCounter{
+		iPgs: iProgress,
+	}
+	if _, err = io.Copy(f, io.TeeReader(resp.Body, counter)); err != nil {
+		f.Close()
+		return err
+	}
+	fmt.Printf("\n")
+	f.Close()
+	//if err = os.Rename(fPath, fPath);err != nil {
+	//	return err
+	//}
+	return nil
+}
+
+type downPara struct {
+	URL      string //寰呬笅杞芥枃浠剁殑url
+	FileName string //寰呬笅杞芥枃浠剁殑鍚嶇О
+}
+
+//procPath 涓嬭浇鍒扮洰鐨勬枃浠跺す
+func downloadExtraFile(downloadDir string, extra downPara, fb func(length, downLen int64)) error {
+	if extra.URL == "" {
+		return nil
+	}
+
+	var (
+		fsize   int64
+		buf     = make([]byte, 32*1024)
+		written int64
+	)
+
+	// 鍒涘缓搴旂敤涓嬭浇鐩綍, 鍚庣画浼氱洿鎺ュ壀鍒囧埌缂栬瘧鐜
+	//downloadDir := path.Join(procPath, "pre-install-sdks")
+	//err := dirPing(downloadDir)
+	//if err != nil {
+	//	logger.Warn("pack error: can not create dir.", err)
+	//	return errors.New("can not create dir")
+	//}
+
+	downloadPath := path.Join(downloadDir, extra.FileName)
+	tmpFilePath := downloadPath + ".download"
+	logger.Debug(tmpFilePath)
+	//鍒涘缓涓�涓猦ttp client
+	client := new(http.Client)
+	//client.Timeout = time.Second * 60 //璁剧疆瓒呮椂鏃堕棿
+	//get鏂规硶鑾峰彇璧勬簮
+	resp, err := client.Get(extra.URL)
+	if err != nil {
+		logger.Error("client.Get err:", err)
+		return err
+	}
+
+	//璇诲彇鏈嶅姟鍣ㄨ繑鍥炵殑鏂囦欢澶у皬
+	fsize, err = strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 32)
+	if err != nil {
+		logger.Error("璇诲彇鏈嶅姟鍣ㄨ繑鍥炴枃浠跺ぇ灏廵rr: ", err)
+	}
+
+	if isFileExist(downloadPath, fsize) {
+		return err
+	}
+
+	logger.Debug("fsize", fsize)
+	//鍒涘缓鏂囦欢
+	file, err := os.Create(tmpFilePath)
+	if err != nil {
+		logger.Error("os.Create err: ", err)
+		return err
+	}
+	defer file.Close()
+	if resp.Body == nil {
+		return errors.New("body is null")
+	}
+	defer resp.Body.Close()
+	//涓嬮潰鏄� io.copyBuffer() 鐨勭畝鍖栫増鏈�
+	for {
+		//璇诲彇bytes
+		nr, er := resp.Body.Read(buf)
+		if nr > 0 {
+			//鍐欏叆bytes
+			nw, ew := file.Write(buf[0:nr])
+			//鏁版嵁闀垮害澶т簬0
+			if nw > 0 {
+				written += int64(nw)
+			}
+			//鍐欏叆鍑洪敊
+			if ew != nil {
+				err = ew
+				break
+			}
+			//璇诲彇鏄暟鎹暱搴︿笉绛変簬鍐欏叆鐨勬暟鎹暱搴�
+			if nr != nw {
+				err = io.ErrShortWrite
+				break
+			}
+		}
+		if er != nil {
+			if er != io.EOF {
+				err = er
+			}
+			break
+		}
+		//娌℃湁閿欒浜嗗揩浣跨敤 callback
+		if fb != nil {
+			fb(fsize, written)
+		}
+	}
+	logger.Debug(err)
+	if err == nil {
+		file.Close()
+		err = os.Rename(tmpFilePath, downloadPath)
+		logger.Debug(err)
+	}
+	return err
+}
+
+// 濡傛灉鏂囦欢澶逛笉瀛樺湪灏变細鍒涘缓
+func dirPing(path string) error {
+	if !util.DirExists(path) {
+		e := os.MkdirAll(path, 00777)
+		if e != nil {
+			return e
+		}
+	}
+	return nil
+}
+
+func isFileExist(filename string, filesize int64) bool {
+	info, err := os.Stat(filename)
+	if os.IsNotExist(err) {
+		logger.Debug(info)
+		return false
+	}
+	if filesize == info.Size() {
+		logger.Debug("瀹夎鍖呭凡瀛樺湪锛�", info.Name(), info.Size(), info.ModTime())
+		return true
+	}
+	del := os.Remove(filename)
+	if del != nil {
+		logger.Error(del)
+	}
+	return false
+}
diff --git a/appcenter-service/service/SdkDownLoad.go b/appcenter-service/service/SdkDownLoad.go
new file mode 100644
index 0000000..5656cd7
--- /dev/null
+++ b/appcenter-service/service/SdkDownLoad.go
@@ -0,0 +1,564 @@
+package service
+
+import (
+	"bytes"
+	"crypto/md5"
+	"encoding/hex"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"path"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"time"
+	"vamicro/appcenter-service/models"
+	"vamicro/config"
+	"vamicro/extend/util"
+
+	"basic.com/valib/bhomeclient.git"
+	"basic.com/valib/bhomedbapi.git"
+	"basic.com/valib/licence.git"
+	"basic.com/valib/logger.git"
+	"github.com/mitchellh/mapstructure"
+)
+
+// 浠庢湇鍔″櫒涓婁笅杞芥枃浠跺埌涓存椂鐩綍锛屾牎楠屼箣鍚庡鏋滃畬鏁村皢鍏舵嫹璐濆埌鐩爣鐩綍涓�
+func DownSo(url string) (bool, error) {
+	resp, err := http.Get(url)
+	if err != nil {
+		logger.Error("鑾峰彇鏂囦欢澶辫触")
+		return false, err
+	}
+	// 浠巖esp涓鍑簔ip鏂囦欢瑙e帇缂╋紝瑙e嚭face.so,face.txt,鐒跺悗鎶婅В鍘嬪嚭鐨剆o鐢∕D5缂栫爜鍑轰竴涓猼emp.txt鏂囦欢锛屼笌瑙e帇鍑虹殑so.txt鏂囦欢姣斿锛�
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		logger.Error("璇诲彇resp.body澶辫触")
+		return false, err
+	}
+	CopyFile(body, "/opt/temp/temp.zip")
+	util.DeCompress("/opt/temp/temp.zip", "/opt/temp")
+	fileName := GetFileNameFromUrl(url, false)
+	md5str, err1 := File2md5("/opt/temp/" + fileName + ".so")
+	if err1 != nil {
+		logger.Error(err1)
+		return false, err1
+	}
+	md5str_origin, err2 := ioutil.ReadFile("/opt/temp/" + fileName + ".txt")
+	if err2 != nil {
+		logger.Error("璇诲彇瑙e帇鍚庣殑md5鏂囦欢澶辫触")
+		return false, err2
+	}
+	flag := CompareMd5([]byte(md5str), md5str_origin)
+	if flag {
+		logger.Info("涓ゆMD5缂栫爜涓�鑷达紒")
+	} else {
+		logger.Debug("涓ゆMD5缂栫爜涓嶄竴鑷达紝璇烽噸鏂颁笅杞�")
+		return false, nil
+	}
+	// 浠巙rl涓埅鍙杝oName
+	soName := GetFileNameFromUrl(url, true)
+	f, err := os.Create("/opt/workspace/ruleprocess/algorithm/" + soName)
+	if err != nil {
+		logger.Error("鍦ㄩ」鐩洰褰曚笅鍒涘缓so鏂囦欢澶辫触")
+		return false, err
+	}
+	data, _ := ioutil.ReadFile("/opt/temp/" + soName)
+	_, err4 := f.Write(data)
+	if err4 != nil {
+		logger.Error("澶嶅埗鏂囦欢鍑洪敊")
+		return false, err4
+	}
+	return true, nil
+}
+
+func CopyFile(byte []byte, dst string) (w int64, err error) {
+	dstFile, err := os.Create(dst)
+	if err != nil {
+		logger.Debug(err.Error())
+		return
+	}
+	defer dstFile.Close()
+	return io.Copy(dstFile, bytes.NewReader(byte))
+}
+
+// 鎸囧畾鐩綍鐨勬枃浠剁敓鎴愮浉搴旂殑MD5鐮佹枃浠�
+func File2md5(filename string) (string, error) {
+	// 鏂囦欢鐢熸垚MD5鍔犲瘑鍔犲瘑鏂囦欢
+	file, err := os.Open(filename)
+	if err != nil {
+		logger.Debug("os Open error")
+		return "", err
+	}
+	md5 := md5.New()
+	_, err = io.Copy(md5, file)
+	if err != nil {
+		logger.Debug("io copy error")
+		return "", err
+	}
+	md5Str := hex.EncodeToString(md5.Sum(nil))
+	return md5Str, nil
+}
+
+// 浠巙rl涓埅鍙栧嚭鏂囦欢鍚嶏紝鍙傛暟鏄槸鍚﹀甫鍚庣紑
+func GetFileNameFromUrl(url string, withSuffix bool) string {
+	fileName := strings.Split(url, "/")[len(strings.Split(url, "/"))-1]
+	if withSuffix {
+		return fileName
+	} else {
+		withoutSuffix := strings.Split(fileName, ".")[0]
+		return withoutSuffix
+	}
+}
+
+// 姣旇緝涓や釜MD5缂栫爜鏄惁涓�鑷�
+func CompareMd5(value1 []byte, value2 []byte) bool {
+	num := bytes.Compare(value1, value2)
+	if num == 0 {
+		return true
+	} else {
+		return false
+	}
+}
+
+//installedFlag 濡傛灉鏄痶rue,琛ㄧず鍙煡鏈湴鐨勶紝涓嶉渶瑕佹瘮瀵规煡鐪嬫湭瀹夎鐨勭畻娉�
+func GetSdkList(sdkName string, installedFlag, userId string) []SdkInsOrUpgrade {
+	//logger.Debug("installedFlag:", installedFlag)
+	t := time.Now()
+	var api bhomedbapi.UserApi
+	useIconTyp := 1
+	if userId != "" {
+		found, userInfo := api.GetUserProfile(userId)
+		logger.Debugf("GetSdkList GetUserProfile userInfo=%v, t=%v", userInfo, time.Since(t))
+		if found {
+			ub, e := json.Marshal(userInfo)
+			if e == nil {
+				type UIconDef struct {
+					UseIconType int `json:"useIconType"`
+				}
+				var ucd UIconDef
+				if e = json.Unmarshal(ub, &ucd); e == nil {
+					useIconTyp = ucd.UseIconType
+					logger.Debug("useIconTyp already 2", useIconTyp)
+
+				}
+			}
+		}
+	}
+	var sdkE models.Sdk
+	t = time.Now()
+	sdkAll, _ := sdkE.FindAll(sdkName) //鏈湴宸插畨瑁呮墍鏈夌畻娉�,甯﹂『搴�
+	logger.Debugf("GetSdkList FindAll sdkName=%v, len(sdkAll)=%v, t=%v", sdkName, len(sdkAll), time.Since(t))
+	if sdkAll == nil {
+		sdkAll = make([]models.Sdk, 0)
+	}
+	installedSdks := make([]SdkInsOrUpgrade, len(sdkAll))
+	iv := make(map[string]SdkVB)
+
+	localSdkIdArr := make([]string, 0)
+	localSdkM := make(map[string]SdkInsOrUpgrade)
+	t = time.Now()
+	for idx, ls := range sdkAll {
+		siou := SdkInsOrUpgrade{
+			Installed: true,
+		}
+
+		var sArg models.SdkArgEntity
+		args, e1 := sArg.FindBySdk(ls.Id)
+		if e1 == nil {
+			siou.Args = args
+		} else {
+			siou.Args = make([]models.SdkArgEntity, 0)
+		}
+
+		siou.Sdk = ls
+		siou.ProtoRuleSo = ls.RuleSo
+		if useIconTyp == 2 && siou.IconBlob2 != "" {
+			siou.IconBlob = siou.IconBlob2
+			siou.IconBlob2 = ""
+		}
+		localSdkM[siou.Id] = siou
+		iv[siou.Id] = SdkVB{
+			Version:     ls.Version,
+			BaseVersion: ls.BaseVersion,
+		}
+		installedSdks[idx] = siou
+
+		localSdkIdArr = append(localSdkIdArr, siou.Id)
+	}
+	logger.Debugf("GetSdkList FindBySdk len(sdkAll)=%v, t=%v", len(sdkAll), time.Since(t))
+	nInsSdks := make([]SdkInsOrUpgrade, 0)
+
+	installedFlagBool, _ := strconv.ParseBool(installedFlag)
+	if !installedFlagBool {
+		t = time.Now()
+		// ***杩欎釜鍦版柟闇�瑕佹湁鏁堢巼闂
+		upSdks, insSdks := findAllMySdk(localSdkIdArr, iv, sdkName)
+		logger.Debugf("GetSdkList findAllMySdk len(localSdkIdArr)=%v, len(iv)=%v, sdkName=%v, t=%v", len(localSdkIdArr), len(iv), sdkName, time.Since(t))
+
+		t = time.Now()
+		for _, sdk := range upSdks {
+			if v, ok := localSdkM[sdk.Id]; ok { //鏈湴宸插畨瑁�
+				ls := v
+				ls.SdkName = sdk.SdkName //浠ュ晢鍩庝笂鐨勪骇鍝佸悕绉颁负鍑�
+
+				ls.Installed = true
+				if sdk.CanUpOrIns {
+					ls.ProgressMsg = ""
+					ls.IsUpgrade = shouldVersionBeUpgrade(ls.Version, sdk.Version)
+					ls.RemoteVersion = sdk.Version //杩滅鐨勭増鏈彿
+
+					if ip, insB := insIngMap.Load(sdk.Id); insB {
+						iPgs := ip.(*InsProgress)
+						ls.ProgressMsg = iPgs.Status + strconv.Itoa(iPgs.Progress) + "%"
+					}
+				}
+
+				if useIconTyp == 2 && ls.IconBlob2 != "" {
+					ls.IconBlob = ls.IconBlob2
+					ls.IconBlob2 = ""
+				}
+				localSdkM[sdk.Id] = ls
+				for index, es := range installedSdks {
+					if es.Id == sdk.Id {
+						installedSdks[index] = ls
+						break
+					}
+				}
+			}
+		}
+		logger.Debugf("GetSdkList shouldVersionBeUpgrade len(upSdks)=%v, t=%v", len(upSdks), time.Since(t))
+
+		t = time.Now()
+		for _, sdk := range insSdks { //鏈湴鏈畨瑁咃紝浣嗗彲浠ュ畨瑁呭垪琛�
+			if sdk.CanUpOrIns {
+				bIns := SdkInsOrUpgrade{
+					RemoteVersion: sdk.Version,
+					IsUpgrade:     false,
+					Installed:     false,
+					ProgressMsg:   "",
+					ProtoRuleSo:   sdk.RuleSo,
+				}
+				if ip, insB := insIngMap.Load(sdk.Id); insB {
+					iPgs := ip.(*InsProgress)
+					bIns.ProgressMsg = iPgs.Status + strconv.Itoa(iPgs.Progress) + "%"
+				}
+				if useIconTyp == 2 && sdk.Sdk.IconBlob2 != "" {
+					sdk.Sdk.IconBlob = sdk.Sdk.IconBlob2
+					sdk.Sdk.IconBlob2 = ""
+				}
+				bIns.Sdk = sdk.Sdk
+				nInsSdks = append(nInsSdks, bIns)
+			}
+		}
+		logger.Debugf("GetSdkList Load len(insSdks)=%v, t=%v", len(insSdks), time.Since(t))
+	}
+
+	// 濡傛灉鍙傛暟涓虹┖, 杩斿洖鍏ㄩ儴
+	if installedFlag == "" {
+		return append(installedSdks, nInsSdks...)
+	}
+
+	// 杩斿洖鎵�鏈夋湭瀹夎
+	if !installedFlagBool {
+		return nInsSdks
+	}
+
+	// 杩斿洖鎵�鏈夊凡瀹夎
+	return installedSdks
+}
+
+func queryDatabase(sdkName string) ([]map[string]interface{}, map[string]bool) {
+	var api bhomedbapi.SdkApi
+	ids := make(map[string]bool)
+	sdks := []map[string]interface{}{}
+
+	// 鏌ヨ宸茬粡瀹夎鐨勭畻娉�
+	data := api.FindAll(sdkName)
+	for _, sdk := range data {
+		ids[sdk.Id] = true
+		sdks = append(sdks, map[string]interface{}{
+			"id":        sdk.Id,
+			"ipc_id":    sdk.IpcId,
+			"sdk_type":  sdk.SdkType,
+			"sdk_name":  sdk.SdkName,
+			"icon":      sdk.Icon,
+			"enable":    sdk.Enable,
+			"installed": true,
+		})
+	}
+
+	return sdks, ids
+}
+
+type shopSdks struct {
+	Sdks       []SdkWithArg `json:"sdks"`
+	CanInsList []SdkWithArg `json:"canInsList"`
+}
+
+type SdkVB struct {
+	Version     string `json:"version"`
+	BaseVersion string `json:"baseVersion"`
+}
+
+const (
+	token = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjQ3NDUwMjU5MjMsInVzZXIiOiJ7XCJpZFwiOlwiZTZjY2QzNmQtNGYxNi00NmZjLTg4ZDUtMDczNjU4NjZkMjA1XCIsXCJwZXJtaXNzaW9uc1wiOltcInByb2R1Y3RNYW5nZTpwdWJsaXNoXCIsXCJjb2RlTWFuZ2U6dmlld1wiLFwiZGV2aWNlTWFuYWdlOmFkZFwiLFwiYWRtaW5NYW5hZ2VcIixcIm9yZGVyTWFuZ2VcIixcImRldmljZU1hbmFnZTp2aWV3XCIsXCJwcm9kdWN0TWFuZ2U6YWRkXCIsXCJhZG1pbk1hbmFnZTp2aWV3XCIsXCJjb2RlTWFuZ2U6YWRkXCIsXCJwcm9kdWN0TWFuZ2U6b2ZmU2FsZVwiLFwib3JkZXJNYW5nZTpjYW5jZWxcIixcInByb2R1Y3RDZW50ZXI6ZG93bmxvYWRcIixcInByb2R1Y3RDZW50ZXI6YnV5XCIsXCJwcm9kdWN0TWFuZ2U6dmlld1wiLFwiYXBpXCIsXCJob21lXCIsXCJvcmRlck1hbmdlOnBheVwiLFwiYWRtaW5NYW5hZ2U6YWRkXCIsXCJvcmRlck1hbmdlOmRvd25sb2FkXCIsXCJwcm9kdWN0Q2VudGVyXCIsXCJkZXZpY2VNYW5hZ2U6dW5iaW5kXCIsXCJvcmRlck1hbmdlOnZpZXdcIixcImFkbWluTWFuYWdlOmVkaXRcIixcImRldmljZU1hbmFnZVwiLFwidmlwTWFuYWdlOmFkZFwiLFwidmlwTWFuYWdlOnZpZXdcIixcInByb2R1Y3RDZW50ZXI6dmlld1wiLFwidmlwTWFuYWdlOmVkaXRcIixcInZpcE1hbmFnZVwiLFwicHJvZHVjdE1hbmdlOmVkaXRcIixcImNvZGVNYW5nZVwiLFwicHJvZHVjdE1hbmdlXCJdLFwidXNlcm5hbWVcIjpcImJhc2ljXCJ9In0.vwjAFkWuEyadRLvIOGK8LFE3MjpY3SQ7j6AlTXnQDG8"
+)
+
+func findAllMySdk(localSdkIdArr []string, iv map[string]SdkVB, inputTxt string) ([]SdkWithArg, []SdkWithArg) {
+	t := time.Now()
+	url := "http://" + util.GetShopUrl() + "/data/api-s/sdk/findAllMySdk"
+	machineCode := licence.GetMachineCode()
+	defer func() {
+		logger.Debugf("findAllMySdk url=%v, costTime=%v", url, time.Since(t))
+	}()
+
+	//鑾峰彇骞冲彴绫诲瀷
+	paramBody := map[string]interface{}{
+		"serverId":      config.Server.AnalyServerId,
+		"machineCode":   machineCode,
+		"localSdkIdArr": localSdkIdArr,
+		"iv":            iv,
+		"inputTxt":      inputTxt,
+	}
+	header := map[string]string{
+		"Authorization": token,
+	}
+	respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*20)
+	if err != nil {
+		logger.Debug("DoPostRequest err:", err)
+		return nil, nil
+	}
+	var res bhomedbapi.Result
+	if err = json.Unmarshal(respBody, &res); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return nil, nil
+	}
+	bytes, _ := json.Marshal(res.Data)
+	var ss shopSdks
+	if err := json.Unmarshal(bytes, &ss); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return nil, nil
+	}
+
+	return ss.Sdks, ss.CanInsList
+}
+
+func GetLocalSdks() []map[string]interface{} {
+	var algos = []map[string]interface{}{}
+
+	AlgorithmFiles := "/opt/vasystem/bin/algorithm/*.json"
+
+	files, err := filepath.Glob(AlgorithmFiles)
+	if err != nil {
+		fmt.Println("Cannot access algorithm json files: No such file or directory")
+		return algos
+	}
+
+	for _, filename := range files {
+		algo := make(map[string]interface{})
+		f, err := ioutil.ReadFile(filename)
+		if err != nil {
+			return algos
+		}
+
+		if err := json.Unmarshal(f, &algo); err != nil {
+			return algos
+		}
+
+		algos = append(algos, map[string]interface{}{
+			"id":       algo["sdkId"],
+			"ipc_id":   algo["ipcId"],
+			"sdk_type": algo["sdkType"],
+			"sdk_name": algo["sdkName"],
+			"icon":     algo["icon"],
+			"args":     algo["sdkArgs"],
+		})
+	}
+
+	return algos
+}
+
+func FindLocalSdkSoById(id string) map[string]interface{} {
+	localAlgos := GetLocalSdks()
+	for _, sdk := range localAlgos {
+		if sdk["id"].(string) == id {
+			return sdk
+		}
+	}
+
+	return nil
+}
+
+type downOrUpResp struct {
+	Url  string `json:"url"`
+	Md5  string `json:"md5"`
+	Size uint64 `json:"size"`
+}
+
+//涓嬭浇鎴栬�呭崌绾х畻娉�
+func DownloadOrUpgrade(id string, h *bhomeclient.WrapperHandler) (bool, error) {
+	if _, ok := insIngMap.Load(id); ok {
+		insIngMap.Delete(id)
+	}
+	PreDownloading = true //闃叉娓呯悊绋嬪簭鎶婂崌绾у寘娓呯悊浜�
+	rb := false
+	ip := &InsProgress{
+		Status:   InsStatus_Downloading,
+		Progress: 0,
+	}
+	insIngMap.Store(id, ip) //鏀惧埌姝e湪瀹夎鍒楄〃涓�
+	defer func() {
+		if !rb {
+			insIngMap.Delete(id)
+		}
+		PreDownloading = false
+	}()
+
+	ver := ""
+	baseVer := ""
+	var apE models.App
+	r1, _ := apE.SelectById(id)
+	if r1 > 0 {
+		ver = apE.Version
+	} else {
+		var sdkE models.Sdk
+		if r2, _ := sdkE.SelectById(id); r2 > 0 {
+			ver = sdkE.Version
+			baseVer = sdkE.BaseVersion
+		}
+	}
+
+	url := "http://" + util.GetShopUrl() + "/data/api-s/sdk/downloadOrUpgrade"
+	machineCode := licence.GetMachineCode()
+	if machineCode == "" {
+		logger.Debug("鑾峰彇鏈哄櫒鐮佸け璐�")
+		return rb, errors.New("鑾峰彇鏈哄櫒鐮佸け璐�")
+	}
+	paramBody := map[string]interface{}{
+		"modId":       id,
+		"machineCode": machineCode,
+		"serverId":    config.Server.AnalyServerId,
+		"version":     ver,
+		"baseVersion": baseVer,
+	}
+	header := map[string]string{
+		"Authorization": token,
+	}
+	respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*60)
+	if err != nil {
+		logger.Debug("DoPostRequest err:", err)
+		return rb, err
+	}
+	var res bhomedbapi.Result
+	if err = json.Unmarshal(respBody, &res); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return rb, err
+	}
+	if !res.Success {
+		logger.Debug("res.Data:", res.Data)
+		return rb, errors.New("璇锋眰鍟嗗煄澶辫触")
+	}
+	logger.Debug("res.Data:", res.Data)
+	var resp downOrUpResp
+	if err := mapstructure.Decode(res.Data.(map[string]interface{}), &resp); err != nil {
+		logger.Debug("mapstructure.Decode err:", err)
+		return rb, err
+	}
+	logger.Debug("resp:", resp)
+	if resp.Url == "" || resp.Md5 == "" {
+		return rb, errors.New("鑾峰彇涓嬭浇瀹夎鍖呭け璐�")
+	}
+
+	ip.Size = resp.Size
+
+	//寮傛瀹夎
+	go startInstall(resp, id, ip, h)
+
+	rb = true
+	return rb, nil
+}
+
+//涓嬭浇瀹夎锛堝崌绾э級鍖咃紝楠岃瘉md5鍚庡畨瑁�
+func startInstall(dor downOrUpResp, id string, iProgress *InsProgress, h *bhomeclient.WrapperHandler) (bool, error) {
+	defer func() {
+		iProgress.IsDone = true
+
+		time.Sleep(10 * time.Second)
+		insIngMap.Delete(id)
+	}()
+
+	//1.绗竴姝ュ厛涓嬭浇瀹夎鍖�
+	configPatchPath := ""
+	if config.Server.PatchPath != "" {
+		configPatchPath = config.Server.PatchPath
+	} else {
+		configPatchPath = "/opt/vasystem/patch"
+	}
+	if !util.DirExists(configPatchPath) {
+		os.Mkdir(configPatchPath, 0777)
+	}
+	filenameWithSuffix := path.Base(dor.Url)
+	ext := path.Ext(filenameWithSuffix)
+	downUrl := "http://" + util.GetShopUrl() + "/files/" + dor.Url
+
+	iProgress.Status = InsStatus_Downloading
+	//濡傛灉妫�鏌ュ埌棰勪笅杞芥枃浠跺垯涓嶉噸澶嶄笅杞�
+	gzFilePath := configPatchPath + "/" + dor.Md5 + ext
+	_, err := os.Stat(gzFilePath)
+	if nil != err {
+		if os.IsNotExist(err) {
+			err := DownloadFile(gzFilePath, downUrl, iProgress)
+			if err != nil {
+				logger.Error("DownloadFile err:", err, " gzFilePath:", gzFilePath, " downUrl:", downUrl)
+				iProgress.Status = InsStatus_Err + " 鍘熷洜:" + err.Error()
+				return false, err
+			}
+		}
+	}
+
+	iProgress.Status = InsStatus_PackageChecking
+
+	//2.涓嬭浇瀹屾垚寮�濮嬪畨瑁�
+	if unPackB, unPackErr := unPackPatchPackage(dor.Md5, ext); !unPackB { //瑙e帇澶辫触
+		iProgress.Status = InsStatus_UnPackErr + " 鍘熷洜:" + unPackErr.Error()
+		return false, unPackErr
+	}
+	//3.鏍¢獙md5
+	fileMd5, err := util.FileMd5(gzFilePath)
+	if err != nil {
+		logger.Debug("FileMd5 err:", err)
+		iProgress.Status = InsStatus_CheckErr + " 鍘熷洜:" + err.Error()
+		return false, err
+	}
+	if fileMd5 != dor.Md5 {
+		logger.Debug("瀹夎鍖卪d5鏍¢獙澶辫触")
+		iProgress.Status = InsStatus_CheckErr + " 鍘熷洜:md5鏍¢獙澶辫触"
+		return false, errors.New("瀹夎鍖卪d5鏍¢獙澶辫触")
+	} else {
+		logger.Debug("瀹夎鍖卪d5鏍¢獙鎴愬姛")
+	}
+	iProgress.Status = InsStatus_Installing
+
+	_, err = installPack(dor.Md5, ext, h)
+	time.Sleep(2 * time.Second)
+	if err == nil {
+
+		iProgress.Status = InsStatus_Done
+
+		return true, nil
+	} else {
+		iProgress.Status = InsStatus_InstallErr + " 鍘熷洜:" + err.Error()
+		go func() {
+			time.Sleep(3 * time.Second)
+			iProgress.Status = ""
+			iProgress.Progress = 0
+			insIngMap.Delete(id) //瀹夎澶辫触涔熻〃绀哄畨瑁呯粨鏉熶簡  闇�瑕佹竻闄や俊鎭�
+		}()
+		return false, err
+	}
+}
diff --git a/appcenter-service/service/SdkInstall.go b/appcenter-service/service/SdkInstall.go
new file mode 100644
index 0000000..7f3b6a8
--- /dev/null
+++ b/appcenter-service/service/SdkInstall.go
@@ -0,0 +1,859 @@
+package service
+
+import (
+	"basic.com/valib/bhomeclient.git"
+	"basic.com/valib/bhomedbapi.git"
+	"basic.com/valib/licence.git"
+	"basic.com/valib/logger.git"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"path"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"time"
+	"vamicro/appcenter-service/models"
+	"vamicro/appcenter-service/vo"
+	"vamicro/config"
+	"vamicro/extend/util"
+)
+
+type SdkInstallService struct {
+}
+
+// inputTxt杩囨护鏉′欢
+func (sv SdkInstallService) GetBuyList(inputTxt string) []SdkWithArg {
+	url := "http://" + util.GetShopUrl() + "/data/api-s/sdk/buyList"
+	machineCode := licence.GetMachineCode()
+	logger.Debug("url:", url, "machineCode:", machineCode)
+	var sdkE models.Sdk
+	localSdks, _ := sdkE.FindAll("") //鏈湴宸插畨瑁呮墍鏈夌畻娉�,甯﹂『搴�
+	if localSdks == nil {
+		localSdks = make([]models.Sdk, 0)
+	}
+	iv := make(map[string]SdkVB)
+
+	localSdkIdArr := make([]string, 0)
+	for _, ls := range localSdks {
+		iv[ls.Id] = SdkVB{
+			Version:     ls.Version,
+			BaseVersion: ls.BaseVersion,
+		}
+
+		localSdkIdArr = append(localSdkIdArr, ls.Id)
+	}
+	paramBody := map[string]interface{}{
+		"serverId":      config.Server.AnalyServerId,
+		"machineCode":   machineCode,
+		"localSdkIdArr": localSdkIdArr,
+		"iv":            iv,
+		"inputTxt":      inputTxt,
+	}
+	header := map[string]string{
+		"Authorization": token,
+	}
+	respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*20)
+	if err != nil {
+		logger.Debug("DoPostRequest err:", err)
+		return nil
+	}
+	var res bhomedbapi.Result
+	if err = json.Unmarshal(respBody, &res); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return nil
+	}
+	bytes, _ := json.Marshal(res.Data)
+	var ss shopSdks
+	if err := json.Unmarshal(bytes, &ss); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return nil
+	}
+
+	var resultArr []SdkWithArg
+
+	installSdkM := make(map[string]models.Sdk)
+	if localSdks != nil {
+		for _, is := range localSdks {
+			installSdkM[is.Id] = is
+		}
+	}
+	if ss.Sdks != nil {
+		for _, rs := range ss.Sdks {
+			if _, ok := installSdkM[rs.Id]; !ok {
+				resultArr = append(resultArr, rs)
+			}
+		}
+	}
+	return resultArr
+}
+
+func (sv SdkInstallService) Active(cod string, sdkId string) (interface{}, error) {
+	//浣跨敤婵�娲荤爜婵�娲荤畻娉�
+	url := "http://" + util.GetShopUrl() + "/data/api-s/sdk/activeByAINode"
+	machineCode := licence.GetMachineCode()
+	if machineCode == "" {
+		logger.Debug("鑾峰彇鏈哄櫒鐮佸け璐�")
+		return nil, errors.New("鑾峰彇鏈哄櫒鐮佸け璐�")
+	}
+	paramBody := map[string]interface{}{
+		"code":        cod,
+		"sdkId":       sdkId,
+		"machineCode": machineCode,
+		"serverId":    config.Server.AnalyServerId,
+	}
+	header := map[string]string{
+		"Authorization": token,
+	}
+	respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*60)
+	if err != nil {
+		logger.Debug("DoPostRequest err:", err)
+		return nil, err
+	}
+	var res bhomedbapi.Result
+	if err = json.Unmarshal(respBody, &res); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return nil, err
+	}
+	if !res.Success {
+		logger.Debug("Active Sdk ret false, res: ", res)
+		return nil, errors.New(res.Msg)
+	}
+	// 婵�娲绘垚鍔�
+	return res.Data, nil
+}
+
+// 绠楁硶(搴旂敤)瀹夎鍖呭畨瑁�
+func (sv SdkInstallService) PackInstall(identifier string, filename string, h *bhomeclient.WrapperHandler) (bool, error) {
+	configPatchPath := ""
+	if config.Server.PatchPath != "" {
+		configPatchPath = config.Server.PatchPath
+	} else {
+		configPatchPath = "/opt/vasystem/patch"
+	}
+
+	filenameWithSuffix := path.Base(filename)
+	ext := path.Ext(filenameWithSuffix)
+
+	zipFilePath := configPatchPath + "/" + identifier + ext
+	unPackTargetPath := configPatchPath + "/" + identifier + "_basic/"
+	md5DirPath := configPatchPath + "/" + identifier
+	if util.Exists(zipFilePath) {
+		strMd5, e := util.FileMd5(zipFilePath)
+		if e != nil || strMd5 == "" {
+			go os.Remove(zipFilePath)
+			if util.DirExists(unPackTargetPath) {
+				go os.RemoveAll(unPackTargetPath)
+			}
+			if util.DirExists(md5DirPath) {
+				go os.RemoveAll(md5DirPath)
+			}
+			return false, errors.New("鑾峰彇瀹夎鍖卪d5澶辫触")
+		}
+		if strMd5 == identifier {
+			if _, insE := installPack(identifier, ext, h); insE != nil {
+				logger.Error("PackInstall insE:", insE)
+				return false, insE
+			}
+
+			return true, nil
+
+		} else {
+			go os.Remove(zipFilePath)
+			if util.DirExists(unPackTargetPath) {
+				go os.RemoveAll(unPackTargetPath)
+			}
+			if util.DirExists(md5DirPath) {
+				go os.RemoveAll(md5DirPath)
+			}
+			logger.Debug("strMd5 is", strMd5, "identifier is", identifier, "not equal")
+			return false, errors.New("鏍¢獙瀹夎鏂囦欢澶辫触")
+		}
+	} else {
+		return false, errors.New("瀹夎鍖呭凡涓㈠け锛岃閲嶆柊涓婁紶")
+	}
+}
+
+func (sv SdkInstallService) PackUninstall(appId string) error {
+	uninstallFile := "/opt/vasystem/package/" + appId + "/uninstall.sh"
+	if util.Exists(uninstallFile) {
+		_, err := ExecCmd(uninstallFile)
+		if err != nil {
+			logger.Error("瀹夎鑴氭湰鎵ц澶辫触:", err.Error())
+			return err
+		}
+	}
+
+	return nil
+}
+
+// 瑙e帇涓婁紶鐨勭畻娉曞畨瑁呭寘
+func unPackPatchPackage(identifier string, ext string) (bool, error) {
+	if ext != ".gz" {
+		return false, errors.New("闈炴硶鐨勫畨瑁呭寘鏂囦欢,瀹夎鍖呬负.tar.gz鏂囦欢")
+	}
+	configPatchPath := ""
+	if config.Server.PatchPath != "" {
+		configPatchPath = config.Server.PatchPath
+	} else {
+		configPatchPath = "/opt/vasystem/patch"
+	}
+	//1.瑙e帇缂╂洿鏂板寘
+	unPackTargetPath := configPatchPath + "/" + identifier + "_basic/"
+	unPackFilePath := configPatchPath + "/" + identifier + ext
+
+	if util.Exists(unPackTargetPath) {
+		//姝ょ増鏈凡缁忔洿鏂拌繃
+		rmErr := os.RemoveAll(unPackTargetPath)
+		if rmErr != nil {
+			return false, rmErr
+		}
+	}
+	if !util.CreateDirectory(unPackTargetPath) {
+		return false, errors.New("鍒涘缓鍘嬬缉鏂囦欢澶瑰け璐�")
+	}
+	logger.Debug("unPackFilePath:", unPackFilePath, "unPackPath:", unPackTargetPath)
+	_, err := util.UnTarGzByCmd(unPackFilePath, unPackTargetPath)
+	if err != nil {
+		logger.Debug("UnPack err:", err, "unPackFile:", unPackFilePath)
+		return false, err
+	}
+	return true, nil
+}
+
+func (sv SdkInstallService) ShowInstallInfo(identifier string, filename string) (bool, map[string]interface{}, error) {
+	configPatchPath := ""
+	if config.Server.PatchPath != "" {
+		configPatchPath = config.Server.PatchPath
+	} else {
+		configPatchPath = "/opt/vasystem/patch"
+	}
+	unPackTargetPath := configPatchPath + "/" + identifier + "_basic/"
+	isValid := false
+	defer func() {
+		if !isValid {
+			filenameWithSuffix := path.Base(filename)
+			ext := path.Ext(filenameWithSuffix)
+			unPackFilePath := configPatchPath + "/" + identifier + ext
+			md5DirPath := configPatchPath + "/" + identifier
+
+			if util.Exists(unPackTargetPath) {
+				os.RemoveAll(unPackTargetPath)
+			}
+			if util.Exists(unPackFilePath) {
+				os.RemoveAll(unPackFilePath)
+			}
+			if util.DirExists(md5DirPath) {
+				go os.RemoveAll(md5DirPath)
+			}
+
+		}
+	}()
+	if util.Exists(unPackTargetPath) {
+		targetFileName := ""
+		err := filepath.Walk(unPackTargetPath, func(path string, f os.FileInfo, err error) error {
+			if f == nil {
+				return err
+			}
+			if f.IsDir() {
+				targetFileName = f.Name()
+			}
+			return nil
+		})
+		if err != nil {
+			return isValid, nil, errors.New("闈炴硶鐨勫畨瑁呭寘")
+		} else {
+			unPackPath := unPackTargetPath + targetFileName + "/"
+			//瑙e帇瀹屾垚锛岃幏鍙栧畨瑁呭寘涓殑鏂囦欢锛屽紑濮嬪畨瑁�
+			//1.瑙f瀽瀹夎璇存槑ins.inc
+			incPath := unPackPath + "ins.inc"
+			if util.Exists(incPath) {
+				if incB, err := ioutil.ReadFile(incPath); err == nil {
+					var ins InsInc
+					if err = json.Unmarshal(incB, &ins); err == nil {
+						showInfo := map[string]interface{}{
+							"productName":    ins.ProductName,
+							"installContent": ins.InstallContent,
+						}
+						sdkInfo := make([]map[string]interface{}, 0)
+						appInfo := make([]map[string]interface{}, 0)
+						if ins.Sdks != nil {
+							for _, is := range ins.Sdks {
+								sdkInfo = append(sdkInfo, map[string]interface{}{
+									"sdkId":   is.SdkId,
+									"sdkName": is.SdkName,
+									"version": is.Version,
+								})
+							}
+						}
+						if ins.Modules != nil {
+							for _, ia := range ins.Modules {
+								appInfo = append(appInfo, map[string]interface{}{
+									"appId":   ia.AppId,
+									"appName": ia.AppName,
+									"version": ia.Version,
+								})
+							}
+						}
+						showInfo["sdks"] = sdkInfo
+						showInfo["apps"] = appInfo
+						isValid = true
+						return true, showInfo, nil
+					} else {
+						return false, nil, errors.New("闈炴硶鐨勫畨瑁呭寘")
+					}
+				} else {
+					return false, nil, errors.New("闈炴硶鐨勫畨瑁呭寘")
+				}
+			} else {
+				return false, nil, errors.New("闈炴硶鐨勫畨瑁呭寘")
+			}
+		}
+	} else {
+		return isValid, nil, errors.New("闈炴硶鐨勫畨瑁呭寘鏍煎紡锛屽畨瑁呭寘宸插垹闄�")
+	}
+}
+
+// 瀹夎sdk(app)
+func installPack(identifier string, ext string, h *bhomeclient.WrapperHandler) (bool, error) {
+	configPatchPath := ""
+	if config.Server.PatchPath != "" {
+		configPatchPath = config.Server.PatchPath
+	} else {
+		configPatchPath = "/opt/vasystem/patch"
+	}
+	//1.瑙e帇缂╂洿鏂板寘
+	unPackTargetPath := configPatchPath + "/" + identifier + "_basic/"
+	unPackFilePath := configPatchPath + "/" + identifier + ext
+	md5DirPath := configPatchPath + "/" + identifier
+	defer func() {
+		if util.Exists(unPackTargetPath) {
+			os.RemoveAll(unPackTargetPath)
+		}
+		if util.Exists(unPackFilePath) {
+			os.RemoveAll(unPackFilePath)
+		}
+		if util.DirExists(md5DirPath) {
+			go os.RemoveAll(md5DirPath)
+		}
+	}()
+
+	if !util.Exists(unPackTargetPath) { //瀹夎鍖呬笉瀛樺湪
+		return false, errors.New("瑙e帇鍚庣殑瀹夎鏂囦欢宸蹭笉瀛樺湪")
+	}
+
+	// 鏌ユ壘涓嬩竴绾х洰褰�
+	targetDir := ""
+	files, err := ioutil.ReadDir(unPackTargetPath)
+	if err != nil {
+		return false, err
+	}
+	for _, f := range files {
+		if f.IsDir() && f.Name() != "." && f.Name() != ".." {
+			targetDir = f.Name()
+		}
+	}
+
+	if targetDir == "" {
+		return false, errors.New("瀹夎鐩綍涓嶅瓨鍦�")
+	}
+
+	unPackPath := unPackTargetPath + targetDir + "/"
+	if !util.Exists(unPackPath) {
+		return false, errors.New("瀹夎鏂囦欢宸蹭笉瀛樺湪")
+	}
+
+	//瑙e帇瀹屾垚锛岃幏鍙栧畨瑁呭寘涓殑鏂囦欢锛屽紑濮嬪畨瑁�
+	//1.瑙f瀽瀹夎璇存槑ins.inc
+	incPath := unPackPath + "ins.inc"
+	if util.Exists(incPath) {
+		if incB, err := ioutil.ReadFile(incPath); err == nil {
+			var ins InsInc
+			if err = json.Unmarshal(incB, &ins); err == nil {
+
+				// 瀹氬埗鎵嬪姩瀹夎
+				if ins.ActivateCode != "*" {
+					//澶勭悊鎺堟潈淇℃伅,鐪嬪綋鍓嶅畨瑁呭寘鏄惁閫傜敤杩欏彴鏈哄櫒
+					curMc := licence.GetMachineCode()
+					curServerId := config.Server.AnalyServerId
+					devMatch := false
+					for _, mc := range ins.Devs {
+						if mc.DevId == curServerId || mc.MachineCode == curMc {
+							devMatch = true
+							break
+						}
+					}
+					if !devMatch {
+						logger.Debug("curServerId:", curServerId, "curMc:", curMc, "ins.Devs:", ins.Devs)
+						return false, errors.New("姝ゅ畨瑁呭寘涓庡綋鍓嶈澶囦笉鍖归厤锛岃妫�鏌�")
+					}
+				}
+
+				//瀹夎绠楁硶,濡傛灉鏈夌畻娉曞寘
+				if len(ins.Sdks) > 0 {
+					if ie := installSDKInPack(unPackPath, ins.Sdks, h); ie != nil {
+						return false, errors.New("绠楁硶瀹夎澶辫触,澶辫触鍘熷洜:" + ie.Error() + "")
+					}
+					//濡傛灉鏈変緷璧栨枃浠跺垯瀹夎渚濊禆
+					if depErr := installDepend(unPackPath); depErr != nil {
+						logger.Error("installDepend depErr:", depErr)
+
+						//濡傛灉瀹夎鍖呴噷娌℃湁甯︿緷璧栨垨渚濊禆瀹夎澶辫触锛屽垯灏濊瘯鍦ㄧ嚎涓嬭浇渚濊禆
+						depErr = downloadDepend(ins.Sdks)
+						if depErr != nil {
+							logger.Error("downloadDepend err:", depErr)
+						}
+					}
+				}
+
+				//瀹夎搴旂敤鍖咃紝濡傛灉鏈夊簲鐢�
+				if len(ins.Modules) > 0 {
+					if ie := installAppInPack(unPackPath, ins.Modules, h); ie != nil {
+						return false, errors.New("搴旂敤瀹夎澶辫触,澶辫触鍘熷洜:" + ie.Error() + "")
+					}
+				}
+			} else {
+				logger.Debug("鍙嶅簭鍒楀寲鎺堟潈淇℃伅澶辫触")
+				return false, errors.New("閿欒鐨勫畨瑁呭寘")
+			}
+		} else {
+			logger.Debug("璇诲彇鎺堟潈鏂囦欢澶辫触")
+			return false, errors.New("閿欒鐨勫畨瑁呭寘")
+		}
+	} else {
+		return false, errors.New("閿欒鐨勫畨瑁呭寘")
+	}
+
+	return true, nil
+}
+
+// 瀹夎瀹夎鍖呬腑鐨勭畻娉�
+func installSDKInPack(unPackPath string, sdkDefs []SdkIns, h *bhomeclient.WrapperHandler) error {
+	sv := NewSdkService(h.Bk)
+	var insErr error
+	var insSdkIds []string
+	defer func() {
+		if insErr != nil {
+			//todo 鍥炴粴
+			logger.Debug("installSDKInPack err:", insErr, "sdkIds:", insSdkIds)
+			if len(insSdkIds) > 0 {
+				//鍒犻櫎绠楁硶
+				//for _,id := range insSdkIds {
+				//
+				//}
+			}
+		}
+	}()
+
+	defSDKPath := unPackPath + "sdk.def"
+	if util.Exists(defSDKPath) {
+		if defB, err := ioutil.ReadFile(defSDKPath); err == nil {
+			//3.灏嗙畻娉晄o銆佷緷璧栨枃浠躲�亃conf銆�
+			var skDefArr []SdkDef
+			if err = json.Unmarshal(defB, &skDefArr); err == nil {
+				exedFiles := make(map[string]string)
+				for _, sd := range sdkDefs {
+					//鍏堟牎楠宲latform鏄惁鍖归厤
+					if sd.Platform == "" {
+						insErr = errors.New("闈炴硶鐨勫畨瑁呭寘锛屾棤platform淇℃伅锛岃涓嬭浇鏈�鏂板畨瑁呭寘")
+						return insErr
+					}
+					if !util.PlatformMatch(sd.Platform) {
+						insErr = errors.New("绠楁硶platform涓嶅尮閰嶏紝闈炴硶鐨勫畨瑁呭寘")
+						return insErr
+					}
+
+					if sd.SdkBaseComponentPath != "" {
+						bPath := path.Base(sd.SdkBaseComponentPath)
+						if util.Exists(unPackPath + bPath) {
+							if _, nIn := exedFiles[bPath]; !nIn { //鏈畨瑁呰繃锛屾墠瀹夎
+								//妫�鏌ョ畻娉曟敮鎸佺殑鏄惧崱鍨嬪彿鏄惁鍜屾湰鏈哄尮閰�
+								if !util.GpuMatch(sd.VGpus) {
+									insErr = errors.New("绠楁硶鏀寔鐨勬樉鍗″瀷鍙�(" + sd.VGpus + ")涓庡綋鍓嶈澶囦笉鍖归厤")
+									return insErr
+								}
+								if insErr = installComponent(unPackPath, bPath); insErr != nil {
+									return insErr
+								} else {
+									exedFiles[bPath] = bPath
+								}
+							}
+						} else {
+							insErr = errors.New("鍩虹绠楁硶鍖�" + bPath + "涓㈠け锛岃妫�鏌ュ畨瑁呭寘")
+							return insErr
+						}
+
+					}
+					if sd.ComponentPath != "" {
+						oPath := path.Base(sd.ComponentPath)
+						if util.Exists(unPackPath + oPath) {
+							if _, nIn := exedFiles[oPath]; !nIn { //鏈畨瑁呰繃锛屾墠瀹夎
+								if insErr = installComponent(unPackPath, oPath); insErr != nil {
+									return insErr
+								} else {
+									exedFiles[oPath] = oPath
+								}
+							}
+						} else {
+							insErr = errors.New("缁勪欢" + oPath + "涓㈠け锛岃妫�鏌�")
+							return insErr
+						}
+					}
+				}
+
+				for _, skd := range skDefArr {
+					srv := vo.SdkRegisterVo{}
+					srv.Id = skd.Def.Id
+					srv.SdkType = skd.Def.SdkType
+					srv.SdkName = skd.Def.SdkName
+					srv.Icon = skd.Def.Icon
+					srv.Url = skd.Def.Url
+					srv.IconBlob = skd.Def.IconBlob
+					srv.IconBlob2 = skd.Def.IconBlob2
+					srv.Version = skd.Def.Version
+					srv.EnTrack = skd.Def.EnTrack
+					srv.ArgDef = skd.Def.ArgDef
+					srv.RuleSo = skd.Def.RuleSo
+					srv.BaseVersion = skd.Def.BaseVersion
+
+					for _, ag := range skd.Args {
+						sra := vo.SdkRegisterArgVo{
+							Scope: ag.Scope,
+						}
+						sra.SdkArg = models.SdkArg{
+							Alias:           ag.Alias,
+							Name:            ag.Name,
+							Type:            ag.Type,
+							ArgType:         ag.ArgType,
+							Must:            ag.Must,
+							Unit:            ag.Unit,
+							Range:           ag.Range,
+							DefaultValue:    ag.DefaultValue,
+							DefaultOperator: ag.DefaultOperator,
+							Sort:            ag.Sort,
+						}
+						srv.Args = append(srv.Args, sra)
+					}
+					//灏嗙畻娉曟敞鍐屽埌鏁版嵁搴撲腑
+					if sv.Register(&srv) {
+						logger.Debug("娉ㄥ唽鎴愬姛锛宻dkId:", skd.Def.Id)
+						insSdkIds = append(insSdkIds, skd.Def.Id)
+					} else {
+						insErr = errors.New("sdk娉ㄥ唽澶辫触,绠楁硶id:" + skd.Def.Id + "")
+						logger.Debug(insErr.Error())
+						return insErr
+					}
+				}
+				//zconfPath := "./zconf/"
+				//libPath := "../libs/"
+				//if !util.DirExists(zconfPath) {
+				//	os.MkdirAll(zconfPath, 0777)
+				//}
+				//if !util.DirExists(libPath) {
+				//	os.MkdirAll(libPath, 0777)
+				//}
+				//for sdkType,_ := range soM {
+				//	if _,iOk := nInsM[sdkType];iOk {
+				//		//鍏堣В鍘婼dkType.tar.gz鏂囦欢
+				//		if unTarGzE := util.UnTarGz(unPackPath+sdkType+".tar.gz", unPackPath);unTarGzE == nil {
+				//			//澶嶅埗json鍚姩鏂囦欢
+				//			if util.Exists(unPackPath+sdkType+"/zconf/"+sdkType+".json") {
+				//				util.CopyFile(unPackPath+sdkType+"/zconf/"+sdkType+".json", zconfPath+sdkType+".json")
+				//			}
+				//			if util.DirExists(unPackPath+sdkType) {
+				//				if _,cE := util.CopyDirByCmd(unPackPath+sdkType, libPath);cE != nil {
+				//					insErr = cE
+				//					return insErr
+				//				}
+				//			}
+				//			if util.DirExists(unPackPath+sdkType+"/models") {
+				//				if _,cE := util.CopyDirByCmd(unPackPath+sdkType+"/models", "./"); cE != nil {
+				//					insErr = cE
+				//					return insErr
+				//				}
+				//				//鎷疯礉瀹屾垚鍚庡垹闄ibs涓媠dkType鏂囦欢澶逛笅models
+				//			}
+				//			if util.DirExists(libPath+sdkType+"/models") {
+				//				os.RemoveAll(libPath+sdkType+"/models")
+				//			}
+				//			if util.DirExists(libPath+sdkType+"/zconf") {
+				//				os.RemoveAll(libPath+sdkType+"/zconf")
+				//			}
+				//		} else {
+				//			logger.Debug("unTarGzE sdkType.tar.gz err:", unTarGzE)
+				//		}
+				//	} else {
+				//		logger.Debug("upper version has been installed")
+				//	}
+				//}
+			} else {
+				logger.Debug("鍙嶅簭鍒楀寲绠楁硶瀹氫箟淇℃伅澶辫触")
+				insErr = errors.New("閿欒鐨勫畨瑁呭寘")
+				return insErr
+			}
+		} else {
+			logger.Debug("璇诲彇绠楁硶瀹氫箟淇℃伅澶辫触,err:", err)
+			insErr = errors.New("閿欒鐨勫畨瑁呭寘")
+			return insErr
+		}
+	} else {
+		insErr = errors.New("閿欒鐨勫畨瑁呭寘锛岀畻娉曞畾涔夋枃浠朵笉瀛樺湪")
+		return insErr
+	}
+
+	return insErr
+}
+
+func installAppInPack(unPackPath string, appDefs []AppIns, h *bhomeclient.WrapperHandler) error {
+	//1.鍐欏叆鏁版嵁搴�
+	var appApi models.App
+
+	var insErr error
+	var insAppIds []string
+	defer func() {
+		if insErr != nil {
+			//todo 鍥炴粴
+			logger.Debug("installAppInPack err:", insErr, "appIds:", insAppIds)
+			if len(insAppIds) > 0 {
+				//鍒犻櫎搴旂敤
+				for _, id := range insAppIds {
+					appApi.DeleteById(id)
+				}
+			}
+		}
+	}()
+
+	defAppPath := unPackPath + "app.def"
+	if util.Exists(defAppPath) {
+		if defB, err := ioutil.ReadFile(defAppPath); err == nil {
+			//3.灏嗙畻娉晄o銆佷緷璧栨枃浠躲�亃conf銆�
+			var appDefArr []models.App
+			if err = json.Unmarshal(defB, &appDefArr); err == nil {
+				var appId = ""
+				for _, ap := range appDefArr {
+					appId = ap.Id
+					if !SaveApp(ap) {
+						insErr = errors.New("娉ㄥ唽搴旂敤澶辫触锛屽簲鐢╥d:" + ap.Id + "")
+						return insErr
+					} else {
+						insAppIds = append(insAppIds, ap.Id)
+					}
+				}
+
+				//2.澶勭悊app鏂囦欢鍐呭
+				exedFiles := make(map[string]string)
+				for _, sd := range appDefs {
+					if sd.ComponentPath != "" {
+						oPath := path.Base(sd.ComponentPath)
+						if util.Exists(unPackPath + oPath) {
+							if _, nIn := exedFiles[oPath]; !nIn { //鏈畨瑁呰繃锛屾墠瀹夎
+								insErr = installComponent(unPackPath, oPath)
+								if insErr != nil {
+									return insErr
+								} else {
+									exedFiles[oPath] = oPath
+								}
+							}
+						} else {
+							insErr = errors.New("缁勪欢" + oPath + "涓㈠け锛岃妫�鏌�")
+							return insErr
+						}
+					}
+				}
+
+				// 3 鎵嬪姩瀹夎
+				installFile := path.Join(unPackPath, "install.sh")
+				if util.Exists(installFile) {
+					// 鍒囨崲鍒板綋鍓嶈繍琛岀洰褰�
+					os.Chdir(unPackPath)
+					b, err := ExecCmd(installFile)
+					if err != nil {
+						logger.Error("瀹夎鑴氭湰鎵ц澶辫触:", err.Error())
+						return err
+					}
+					logger.Debug("install component result:", string(b))
+
+					// 澶嶅埗瀹夎鏂囦欢鍒皃ackage鐩綍, 鍗歌浇鏃惰皟鐢� uninstall
+					pkgDir := "/opt/vasystem/package/" + appId
+					ExecCmd(fmt.Sprintf("mkdir -p %s", pkgDir))
+					ExecCmd(fmt.Sprintf("cp -rf %s/* %s/", unPackPath, pkgDir))
+
+					return nil
+				}
+			} else {
+				logger.Debug("鍙嶅簭鍒楀寲搴旂敤瀹氫箟淇℃伅澶辫触")
+				insErr = errors.New("閿欒鐨勫畨瑁呭寘")
+				return insErr
+			}
+		} else {
+			insErr = errors.New("璇诲彇搴旂敤瀹氫箟鏂囦欢澶辫触")
+			return insErr
+		}
+	} else {
+		insErr = errors.New("閿欒鐨勫畨瑁呭寘锛屽簲鐢ㄥ畾涔夋枃浠朵笉瀛樺湪")
+		return insErr
+	}
+
+	return nil
+}
+
+func installComponent(unPackPath string, componentFileName string) error {
+	ext := path.Ext(componentFileName)
+	if ext == "" {
+		return errors.New("闈炴硶鐨勫畨瑁呭寘鍚庣紑")
+	}
+	cName := strings.ReplaceAll(componentFileName, ext, "")
+	targetPath := unPackPath + cName + "/"
+	logger.Debug("installComponent targetPath:", targetPath)
+	if util.Exists(targetPath) {
+		rmErr := os.RemoveAll(targetPath)
+		if rmErr != nil {
+			return rmErr
+		}
+	}
+	if !util.CreateDirectory(targetPath) {
+		return errors.New("鍒涘缓鍘嬬缉鏂囦欢澶瑰け璐�")
+	}
+	if utzOut, unTarGzE := util.UnTarGzByCmd(unPackPath+componentFileName, targetPath); unTarGzE == nil {
+		//浣跨敤瀹夎鑴氭湰鎵ц
+		//targetFileName := ""
+		//err := filepath.Walk(targetPath, func(path string, f os.FileInfo, err error) error {
+		//	if f == nil {
+		//		return err
+		//	}
+		//	if f.IsDir() {
+		//		targetFileName = f.Name()
+		//	}
+		//	return nil
+		//})
+		//if err != nil {
+		//	return errors.New("瀹夎鍖呬笉鍚堟硶锛岃妫�鏌ワ紝err:"+err.Error()+"")
+		//}
+		//logger.Debug("targetFileName:", targetFileName)
+		if util.Exists(targetPath + "install.sh") {
+			cmdPath := fmt.Sprintf("%sinstall.sh %s", targetPath, targetPath)
+			b, err := ExecCmd(cmdPath)
+			if err != nil {
+				return err
+			}
+			logger.Debug("install component ", componentFileName, " result:", string(b))
+			return nil
+		} else {
+			return errors.New("瀹夎鎵ц鏂囦欢涓嶅瓨鍦紝璇锋鏌�")
+		}
+	} else {
+		logger.Error("UnTarGzByCmd out:", utzOut)
+		return unTarGzE
+	}
+}
+
+func shouldVersionBeUpgrade(curVersion, dstVersion string) bool {
+	if curVersion == "" {
+		return true
+	}
+	if dstVersion == "" {
+		return false
+	}
+	curIVArr := strings.Split(curVersion, ".")
+	dstIVArr := strings.Split(dstVersion, ".")
+	if len(curIVArr) != 3 || len(dstIVArr) != 3 {
+		return false
+	}
+	cH, cEH := strconv.Atoi(curIVArr[0])
+	cM, cEM := strconv.Atoi(curIVArr[1])
+	cL, cEL := strconv.Atoi(curIVArr[2])
+
+	dH, dEH := strconv.Atoi(dstIVArr[0])
+	dM, dEM := strconv.Atoi(dstIVArr[1])
+	dL, dEL := strconv.Atoi(dstIVArr[2])
+	if cEH != nil || cEM != nil || cEL != nil || dEH != nil || dEM != nil || dEL != nil {
+		return false
+	}
+	if cH > dH {
+		return false
+	} else if cH == dH {
+		if cM > dM {
+			return false
+		} else if cM == dM {
+			if cL > dL {
+				return false
+			} else if cL == dL {
+				return false
+			} else {
+				return true
+			}
+		} else {
+			return true
+		}
+	} else {
+		return true
+	}
+}
+
+type InsInc struct {
+	OrderId      string   `json:"orderId"`      //璁㈠崟id
+	ProductId    string   `json:"productId"`    //浜у搧id
+	ActivateCode string   `json:"activateCode"` //婵�娲荤爜
+	Devs         []InsDev `json:"devs"`         //瀹夎鍖呯粰鍝簺璁惧浣跨敤
+	UserId       string   `json:"userId"`       //鐢ㄦ埛id
+	Sdks         []SdkIns `json:"sdks"`         //绠楁硶妯″潡
+	Modules      []AppIns `json:"modules"`      //搴旂敤妯″潡
+	ChCount      int      `json:"chCount"`      //閫氶亾鏁伴噺
+	AuthCount    int      `json:"authCount"`    //鎺堟潈鏁伴噺
+	ServeYear    int      `json:"serveYear"`    //鏈嶅姟鏃堕暱
+
+	ProductName    string `json:"productName"`
+	InstallContent string `json:"installContent"`
+}
+
+type InsDev struct {
+	DevId       string `json:"devId"`
+	MachineCode string `json:"machineCode"`
+}
+
+type SdkIns struct {
+	SdkId                string `json:"sdkId"`
+	SdkName              string `json:"sdkName"`
+	SdkType              string `json:"sdkType"`
+	Version              string `json:"version"`
+	BaseVersion          string `json:"baseVersion"`
+	SdkBaseComponentPath string `json:"sdkBase_component_path"`
+	SdkBaseComponentName string `json:"sdkBase_component_name"`
+	ComponentPath        string `json:"component_path"`
+	ComponentName        string `json:"component_name"`
+	VGpus                string `json:"vGpus"` //姝ょ畻娉曟敮鎸佺殑鏄惧崱鍨嬪彿
+	Platform             string `json:"platform"`
+}
+
+type AppIns struct {
+	AppId         string `json:"appId"`
+	AppName       string `json:"appName"`
+	Version       string `json:"version"`
+	ComponentPath string `json:"component_path"`
+	ComponentName string `json:"component_name"`
+}
+
+// 绠楁硶鍜屽弬鏁板畾涔�
+type SdkDef struct {
+	Def  models.Sdk            `json:"def"`
+	Args []models.SdkArgEntity `json:"args"`
+}
+
+type SdkWithArg struct {
+	models.Sdk
+	Args       []models.SdkArgEntity `json:"args"`
+	CanUpOrIns bool                  `json:"canUpOrIns"`
+	Platforms  []models.PtIns        `json:"platforms"` //鍙�傞厤鐨勫钩鍙颁俊鎭�
+}
+
+type SdkInsOrUpgrade struct {
+	SdkWithArg
+
+	RemoteVersion string `json:"remoteVersion"` //鍟嗗煄浠撳簱鐗堟湰鍙�
+	Installed     bool   `json:"installed"`     //鏄惁宸插畨瑁�
+	IsUpgrade     bool   `json:"isUpgrade"`     //鏄惁闇�瑕佸崌绾�
+	ProgressMsg   string `json:"progressMsg"`   //瀹夎鎴栧崌绾ц繘搴�
+	ProtoRuleSo   string `json:"ruleSo"`        //閫傞厤protomsg涓殑ruleSo
+}
diff --git a/appcenter-service/service/SysService.go b/appcenter-service/service/SysService.go
new file mode 100644
index 0000000..14d384b
--- /dev/null
+++ b/appcenter-service/service/SysService.go
@@ -0,0 +1,632 @@
+package service
+
+import (
+	"basic.com/valib/bhomeclient.git"
+	"basic.com/valib/bhomedbapi.git"
+	"basic.com/valib/licence.git"
+	"basic.com/valib/logger.git"
+	"bufio"
+	"context"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/mitchellh/mapstructure"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path"
+	"path/filepath"
+	"strings"
+	"sync"
+	"time"
+	"vamicro/config"
+	"vamicro/extend/util"
+	versionControlM "vamicro/version-control/models"
+)
+
+var (
+	/**
+	"app_auto_clean" : "0",
+	"app_update_notice": "0",
+	"app_auto_update": "0",
+	*/
+	VersionUpdateSetting = map[string]string{"app_auto_clean": "0", "app_update_notice": "0", "app_auto_update": "0"}
+
+	updateNoticeInfo UpdateNoticeInfo
+	NoticeLock       sync.Mutex
+	PreDownloading   bool
+)
+
+type SysService struct {
+}
+
+type FileChunkCheckVo struct {
+	UserId           string
+	ChunkNumber      int    //褰撳墠鍒嗙墖涓嬫爣,浠�1寮�濮�
+	ChunkSize        int    //姣忎竴鍧楃殑澶у皬
+	CurrentChunkSize int    //褰撳墠鍒嗗潡鐨勫ぇ灏�
+	FileName         string //鏂囦欢鍚嶇О
+	Identifier       string //鏁翠釜鏂囦欢鍞竴鏍囪瘑,md5
+	RelativePath     string //鏂囦欢瀹㈡埛绔矾寰�
+	TotalSize        int64  //鏂囦欢鎬诲ぇ灏�
+	TotalChunks      int    //鎬诲垎鐗囨暟閲�
+}
+
+type FileUploadVo struct {
+	Id               string
+	UserId           string
+	ChunkNumber      int                  //褰撳墠鍒嗙墖涓嬫爣,浠�1寮�濮�
+	ChunkSize        int                  //姣忎竴鍧楃殑澶у皬
+	CurrentChunkSize int                  //褰撳墠鍒嗗潡鐨勫ぇ灏�
+	FileName         string               //鏂囦欢鍚嶇О
+	Identifier       string               //鏁翠釜鏂囦欢鍞竴鏍囪瘑,md5
+	RelativePath     string               //鏂囦欢瀹㈡埛绔矾寰�
+	TotalSize        int64                //鏂囦欢鎬诲ぇ灏�
+	TotalChunks      int                  //鎬诲垎鐗囨暟閲�
+	File             *bhomeclient.FileArg //褰撳墠鍒嗙墖鐨勬枃浠跺唴瀹�
+}
+
+type UpdateNoticeInfo struct {
+	NoticeUser     map[string]int
+	NeedUpdate     bool
+	PreDownUpgrade bool
+	NoticeStatus   bool
+	AutoClean      bool
+	SdkNeedUpgrade []SdkInsOrUpgrade
+	AppNeedUpgrade []AppWithShop
+	LastNoticeTime int
+}
+
+func init() {
+	updateNoticeInfo.NoticeUser = make(map[string]int)
+}
+
+func (sv SysService) CheckUpdateFile(arg *FileChunkCheckVo) bool {
+	configPatchPath := ""
+	if config.Server.PatchPath != "" {
+		configPatchPath = config.Server.PatchPath
+	} else {
+		configPatchPath = "/opt/vasystem/patch"
+	}
+	fileTmpPath := configPatchPath + "/" + arg.Identifier
+	if !util.Exists(fileTmpPath) {
+		return false
+	}
+	//鍒ゆ柇鍚堟垚鐨勬枃浠舵槸鍚﹀瓨鍦�
+	index := strings.LastIndex(arg.FileName, ".")
+	subfix := ""
+	if index > -1 { //鏈夊悗缂�
+		subfix = arg.FileName[index:]
+	}
+	mergedFilePath := fileTmpPath + subfix
+	if util.Exists(mergedFilePath) {
+		return true
+	}
+	//鍒ゆ柇鍒嗗潡鏂囦欢鏄惁瀛樺湪
+	chunkAlignNum := util.FormatNum(arg.TotalChunks, arg.ChunkNumber)
+	chunkFilePath := fileTmpPath + "/" + arg.Identifier + "_" + chunkAlignNum
+	if !util.Exists(chunkFilePath) {
+		return false
+	}
+	if arg.ChunkNumber == arg.TotalChunks {
+		dirFiles, _ := ioutil.ReadDir(fileTmpPath)
+		if dirFiles != nil && len(dirFiles) == arg.TotalChunks {
+			//琛ㄧず鎵�鏈夊垎鍧楅兘涓婁紶浜嗭紝闇�瑕乵erge
+			if b, _ := MergeChunks(fileTmpPath, mergedFilePath); !b {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+func (sv SysService) PatchUpload(arg *FileUploadVo) (bool, bool, string) {
+	configPatchPath := ""
+	if config.Server.PatchPath != "" {
+		configPatchPath = config.Server.PatchPath
+	} else {
+		configPatchPath = "/opt/vasystem/patch"
+	}
+
+	if !util.CreateDirectory(configPatchPath) {
+		return false, false, "鍒涘缓鏂囦欢澶瑰け璐�"
+	}
+
+	filenameWithSuffix := path.Base(arg.FileName)
+	subfix := path.Ext(filenameWithSuffix)
+	MD5Str := arg.Identifier
+	logger.Debug("Identifier:", MD5Str)
+	fileTmpPath := configPatchPath + "/" + MD5Str
+	if !util.Exists(fileTmpPath) {
+		if !util.CreateDirectory(fileTmpPath) {
+			return false, false, "鍒涘缓琛ヤ竵鏂囦欢澶瑰け璐�"
+		}
+	}
+	chunkAlignNum := util.FormatNum(arg.TotalChunks, arg.ChunkNumber)
+	fileSavePath := fileTmpPath + "/" + MD5Str + "_" + chunkAlignNum
+	if util.Exists(fileSavePath) {
+		rmErr := os.Remove(fileSavePath)
+		if rmErr != nil {
+			logger.Debug("rmErr:", rmErr)
+			return false, false, rmErr.Error()
+		}
+	}
+	file, e := os.Create(fileSavePath)
+	if e != nil {
+		logger.Debug("os.Create err:", e, "fileSavePath:", fileSavePath)
+		return false, false, e.Error()
+	}
+	defer file.Close()
+	writer := bufio.NewWriter(file)
+
+	nn, err2 := writer.Write(arg.File.Bytes)
+	if nn == 0 || err2 != nil {
+		logger.Debug("write chunkData err:", err2, "nn:", nn)
+		return false, false, "鍐欏叆琛ヤ竵鍖呭け璐�"
+	}
+	if err2 = writer.Flush(); err2 != nil {
+		logger.Debug("write flush err:", err2)
+		return false, false, err2.Error()
+	}
+	isComplete := false
+	dirFiles, _ := ioutil.ReadDir(fileTmpPath)
+	if dirFiles != nil && len(dirFiles) == arg.TotalChunks {
+		isComplete = true
+	}
+	if isComplete {
+		if mergeB, mergeE := MergeChunks(fileTmpPath, fileTmpPath+subfix); mergeB {
+			logger.Debug("merge all chunks success,identifier:", MD5Str, "fileName:", arg.FileName)
+			unPackB, unPackErr := unPackPatchPackage(MD5Str, subfix)
+			logger.Debug("unPackB:", unPackB, "unPackErr:", unPackErr)
+			if unPackB {
+				return true, isComplete, "瑙e帇琛ヤ竵鍖呭け璐�,閿欒鐨勮ˉ涓佸寘鏍煎紡"
+			}
+		} else {
+			return false, isComplete, mergeE.Error()
+		}
+	}
+	return true, isComplete, ""
+}
+
+//upgrade
+//func (sv SysService) Upgrade(identifier string,filename string) (bool,error) {
+//	if !bakBeforeUpgrade() {
+//		return false,errors.New("鏇存柊鍓嶅浠藉け璐�")
+//	}
+//	configPatchPath := ""
+//	if config.Server.PatchPath != "" {
+//		configPatchPath = config.Server.PatchPath
+//	} else {
+//		configPatchPath = "/opt/vasystem/patch"
+//	}
+//
+//	filenameWithSuffix := path.Base(filename)
+//	ext := path.Ext(filenameWithSuffix)
+//
+//	zipFilePath := configPatchPath + "/"+identifier+ext
+//	if util.Exists(zipFilePath) {
+//		//鏍¢獙md5
+//		strMd5, e := util.FileMd5(zipFilePath)
+//		if e !=nil || strMd5 == "" {
+//			return false,errors.New("鑾峰彇鍗囩骇鍘嬬缉鍖卪d5澶辫触")
+//		}
+//		if strMd5 == identifier {
+//			if !updatePatch(identifier, ext) {
+//				return false,errors.New("鎵ц鍗囩骇杩囩▼寮傚父,璇风‘瀹氫笂浼犵殑琛ヤ竵鏄痶ar.gz鏍煎紡")
+//			}
+//			return true,nil
+//
+//		} else {
+//			logger.Debug("strMd5 is", strMd5,"identifier is",identifier,"not equal")
+//			return false,errors.New("鏍¢獙鍗囩骇鏂囦欢澶辫触")
+//		}
+//	} else {
+//		return false,errors.New("鍗囩骇鏂囦欢宸蹭涪澶憋紝璇烽噸鏂颁笂浼�")
+//	}
+//}
+//
+//func bakBeforeUpgrade() bool {
+//	configBakPath := ""
+//	if config.Server.BakPath != "" {
+//		configBakPath = config.Server.BakPath
+//	} else {
+//		configBakPath = "/opt/vasystem/bak"
+//	}
+//	if util.Exists(configBakPath) {
+//		//鍙繚鐣欐渶鏂扮殑鐗堟湰
+//		if err := os.RemoveAll(configBakPath);err != nil {
+//			return false
+//		}
+//	}
+//	if !util.CreateDirectory(configBakPath) {
+//		return false
+//	}
+//	b, err := ExecCmd("cp -r /opt/vasystem/bin /opt/vasystem/bak")
+//	if err != nil {
+//		logger.Debug("bakBeforeUpgrade result:",string(b),"err:",err)
+//		return false
+//	}
+//	return true
+//}
+
+//鏇存柊绯荤粺绋嬪簭
+//func updatePatch(identifier string, ext string) bool {
+//	configPatchPath := ""
+//	if config.Server.PatchPath != "" {
+//		configPatchPath = config.Server.PatchPath
+//	} else {
+//		configPatchPath = "/opt/vasystem/patch"
+//	}
+//	//1.瑙e帇缂╂洿鏂板寘
+//	unPackPath := configPatchPath+"/"+identifier+"_basic/"
+//	if util.Exists(unPackPath) {
+//		//姝ょ増鏈凡缁忔洿鏂拌繃
+//		rmErr := os.RemoveAll(unPackPath)
+//		if rmErr !=nil {
+//			return false
+//		}
+//	}
+//	if !util.CreateDirectory(unPackPath) {
+//		return false
+//	}
+//
+//	unPackFilePath := configPatchPath+"/"+identifier+ext
+//	err := util.UnTarGz(unPackFilePath, unPackPath)
+//	if err !=nil {
+//		logger.Debug("UnPack err:",err,"unPackFile:",unPackFilePath)
+//		return false
+//	}
+//
+//	//濡傛灉閫氱敤鑴氭湰鏈夋洿鏂帮紝鍒欐洿鏂伴�氱敤鑴氭湰
+//	if util.Exists(unPackPath+"updatePatch.sh") {
+//		cpStr := fmt.Sprintf("cp %s /opt/vasystem/bin",unPackPath+"updatePatch.sh")
+//		b, err := ExecCmd(cpStr)
+//		if err != nil {
+//			logger.Debug("cp updatePatch.sh to bin err:",err,"result:",string(b))
+//			return false
+//		}
+//	}
+//
+//	//鍒ゆ柇鏇存柊鍖呴噷鏄惁鏈夎ˉ涓佽剼鏈紝濡傛灉鏈夊垯鎵ц锛屽惁鍒欐墽琛寀pdatePatch.sh
+//	updateCmd := fmt.Sprintf("./updatePatch.sh %s %s %s &",unPackPath,unPackFilePath,configPatchPath+"/"+identifier)
+//	if util.Exists(unPackPath+"upgrade.sh") {
+//		updateCmd = fmt.Sprintf("%supgrade.sh %s %s %s &",unPackPath,unPackPath,unPackFilePath,configPatchPath+"/"+identifier)
+//	}
+//	//2.鏇存柊绯荤粺
+//	b,err := ExecCmd(updateCmd)
+//	if err != nil {
+//		logger.Debug("upgrade err:",err,"result:",string(b),"cmd:",updateCmd)
+//		return false
+//	} else {
+//		logger.Debug("upgrade result:",string(b),"cmd:",updateCmd)
+//	}
+//	return true
+//}
+
+func MergeChunks(chunkPath string, storePath string) (bool, error) {
+	var cmd *exec.Cmd
+	cmd = exec.Command("/bin/sh", "-c", fmt.Sprintf(`
+		filepath=%s
+		filestore=%s
+		echo "filepath: " $filepath
+		echo "filestorepath: "  $filestore
+		if [ ! -f $filestore ]; then
+			echo "$filestore not exist"
+		else
+			rm -f $filestore
+		fi
+		
+		for item in $(ls $filepath | sort -n)
+		do
+			$(cat ${filepath}/${item} >> ${filestore})
+			echo "merge ${filepath}/${item}  to $filestore ok"
+		done
+
+		echo "file store ok"`, chunkPath, storePath))
+
+	if b, err := cmd.Output(); err != nil {
+		logger.Debug("mergeChunks err:", err, "result:", string(b))
+		return false, errors.New("鍚堟垚鍘嬬缉鍖呭け璐�")
+	} else {
+		logger.Debug("mergeChunks result:", string(b))
+		return true, nil
+	}
+
+}
+
+func ExecCmd(cmdStr string) ([]byte, error) {
+	var cmd *exec.Cmd
+	cmd = exec.Command("/bin/sh", "-c", cmdStr)
+	return cmd.Output()
+}
+
+func NoticeTick(c context.Context) {
+	tick := time.Tick(1 * time.Second)
+	for {
+		select {
+		case <-c.Done():
+			logger.Info("proc close, self update exit")
+			return
+		case <-tick:
+			NoticeLock.Lock()
+			for uid, _ := range updateNoticeInfo.NoticeUser {
+				if updateNoticeInfo.NoticeUser[uid] > 0 {
+					updateNoticeInfo.NoticeUser[uid]--
+				}
+			}
+			NoticeLock.Unlock()
+		}
+	}
+}
+
+//鏇存柊妫�鏌�
+func SelfUpdateStart(c context.Context) {
+	tick := time.Tick(30 * time.Second)
+	for {
+		select {
+		case <-c.Done():
+			logger.Info("proc close, self update exit")
+			return
+		case <-tick:
+			NoticeLock.Lock()
+			//娓呯悊鍗囩骇鏂囦欢
+			appAutoClean, ok := VersionUpdateSetting["app_auto_clean"]
+			if ok && appAutoClean == "1" {
+				updateNoticeInfo.AutoClean = true
+				//configPatchPath := ""
+				//if config.Server.PatchPath != "" {
+				//	configPatchPath = config.Server.PatchPath
+				//} else {
+				//	configPatchPath = "/opt/vasystem/patch"
+				//}
+				//err := os.RemoveAll(configPatchPath)
+				//if nil != err {
+				//	logger.Error("clean update package failed:", err.Error())
+				//}
+				//_ = os.MkdirAll(configPatchPath, 0777)
+			} else {
+				updateNoticeInfo.AutoClean = false
+			}
+			//鏇存柊鍗囩骇鎻愰啋
+			appUpdateNotice, ok := VersionUpdateSetting["app_update_notice"]
+			var sdkNeedUp []SdkInsOrUpgrade
+			var appNeedUp []AppWithShop
+			if ok && appUpdateNotice == "1" {
+				sdkNeedUp, appNeedUp = CheckNeedUpgrade()
+				updateNoticeInfo.NeedUpdate = len(sdkNeedUp) > 0 || len(appNeedUp) > 0
+				updateNoticeInfo.NoticeStatus = true
+				SdkHasModify := SdkNewModify(updateNoticeInfo.SdkNeedUpgrade, sdkNeedUp)
+				AppHasModify := AppNewModify(updateNoticeInfo.AppNeedUpgrade, appNeedUp)
+				if SdkHasModify || AppHasModify {
+					for uid, _ := range updateNoticeInfo.NoticeUser {
+						if updateNoticeInfo.NoticeUser[uid] <= 0 {
+							updateNoticeInfo.NoticeUser[uid] = 0
+						}
+					}
+				}
+				updateNoticeInfo.SdkNeedUpgrade = sdkNeedUp
+				updateNoticeInfo.AppNeedUpgrade = appNeedUp
+			} else {
+				updateNoticeInfo.NeedUpdate = false
+				updateNoticeInfo.NoticeStatus = false
+			}
+			//棰勪笅杞�
+			appAutoUpdate, ok := VersionUpdateSetting["app_auto_update"]
+			if ok && appAutoUpdate == "1" {
+				updateNoticeInfo.PreDownUpgrade = true
+				if appUpdateNotice == "0" {
+					sdkNeedUp, appNeedUp = CheckNeedUpgrade()
+				}
+
+				if len(sdkNeedUp) > 0 {
+					for _, item := range sdkNeedUp {
+						haveDown := CheckPreDown(item.RemoteVersion, item.SdkType)
+						if !haveDown {
+							PreDownSdkAndAppUpgradeFile(item.Id)
+						}
+					}
+				}
+				if len(appNeedUp) > 0 {
+					for _, item := range appNeedUp {
+						haveDown := CheckPreDown(item.RemoteVersion, item.Package)
+						if !haveDown {
+							PreDownSdkAndAppUpgradeFile(item.Id)
+						}
+					}
+				}
+
+			} else {
+				updateNoticeInfo.PreDownUpgrade = false
+			}
+			NoticeLock.Unlock()
+		default:
+			time.Sleep(time.Second)
+		}
+	}
+}
+
+//鏄惁鍜屼笂娆℃瘮杈冩湁鏂扮殑鏇存柊
+func SdkNewModify(SdkNeedUpgrade []SdkInsOrUpgrade, sdkNeedUp []SdkInsOrUpgrade) bool {
+	for _, item := range SdkNeedUpgrade {
+		for _, item2 := range sdkNeedUp {
+			if item.Id == item2.Id {
+				if strings.Compare(item.RemoteVersion, item2.RemoteVersion) == 1 {
+					return true
+				}
+			}
+		}
+	}
+	return false
+}
+
+//鏄惁鍜屼笂娆℃瘮杈冩湁鏂扮殑鏇存柊
+func AppNewModify(AppNeedUpgrade []AppWithShop, appNeedUp []AppWithShop) bool {
+	for _, item := range AppNeedUpgrade {
+		for _, item2 := range appNeedUp {
+			if item.Id == item2.Id {
+				if strings.Compare(item.RemoteVersion, item2.RemoteVersion) == 1 {
+					return true
+				}
+			}
+		}
+	}
+	return false
+}
+
+/**
+棰勪笅杞絊DK鍗囩骇鍖�
+*/
+func PreDownSdkAndAppUpgradeFile(id string) {
+	if IsInstalling(id) {
+		logger.Debug("绯荤粺姝e湪鍗囩骇")
+		return
+	}
+	PreDownloading = true
+	ip := &InsProgress{
+		Status:   InsStatus_Downloading,
+		Progress: 0,
+	}
+	insIngMap.Store(id, ip) //鏀惧埌姝e湪瀹夎鍒楄〃涓�
+	defer func() {
+		insIngMap.Delete(id)
+		PreDownloading = false
+	}()
+	url := "http://" + util.GetShopUrl() + "/data/api-s/sdk/downloadOrUpgrade"
+	machineCode := licence.GetMachineCode()
+	if machineCode == "" {
+		logger.Debug("鑾峰彇鏈哄櫒鐮佸け璐�")
+		return
+	}
+	paramBody := map[string]interface{}{
+		"modId":       id,
+		"machineCode": machineCode,
+		"serverId":    config.Server.AnalyServerId,
+	}
+	header := map[string]string{
+		"Authorization": token,
+	}
+	respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*60)
+	if err != nil {
+		logger.Debug("DoPostRequest err:", err)
+		return
+	}
+	var res bhomedbapi.Result
+	if err = json.Unmarshal(respBody, &res); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return
+	}
+	if !res.Success {
+		logger.Debug("res.Data:", res.Data)
+		return
+	}
+	logger.Debug("res.Data:", res.Data)
+	var resp downOrUpResp
+	if err := mapstructure.Decode(res.Data.(map[string]interface{}), &resp); err != nil {
+		logger.Debug("mapstructure.Decode err:", err)
+		return
+	}
+	logger.Debug("resp:", resp)
+	if resp.Url == "" || resp.Md5 == "" {
+		return
+	}
+
+	ip.Size = resp.Size
+	//涓嬭浇瀹夎鍖�
+	configPatchPath := ""
+	if config.Server.PatchPath != "" {
+		configPatchPath = config.Server.PatchPath
+	} else {
+		configPatchPath = "../patch"
+	}
+	if !util.DirExists(configPatchPath) {
+		os.Mkdir(configPatchPath, 0777)
+	}
+	filenameWithSuffix := path.Base(resp.Url)
+	//ext := path.Ext(filenameWithSuffix)
+	downUrl := "http://" + util.GetShopUrl() + "/files/" + resp.Url
+
+	gzFilePath := configPatchPath + "/" + filenameWithSuffix
+	_, err = os.Stat(gzFilePath)
+	if nil != err {
+		if os.IsNotExist(err) {
+			err := DownloadFile(gzFilePath, downUrl, ip)
+			if err != nil {
+				logger.Debug("DownloadFile err:", err, " gzFilePath:", gzFilePath, " downUrl:", downUrl)
+				return
+			}
+		} else {
+			return
+		}
+	}
+}
+
+//妫�鏌ユ槸鍚﹂渶瑕佹洿鏂�
+func CheckNeedUpgrade() ([]SdkInsOrUpgrade, []AppWithShop) {
+	sdkNeedUp := make([]SdkInsOrUpgrade, 0)
+	// userId := c.Header("Login_user_id")
+	appNeedUp := make([]AppWithShop, 0)
+	sdks := GetSdkList("", "", "")
+	for _, item := range sdks {
+		if item.Installed && item.IsUpgrade {
+			sdkNeedUp = append(sdkNeedUp, item)
+		}
+	}
+	apps := GetAppList("")
+	for _, item := range apps {
+		if item.Installed && item.IsUpgrade {
+			appNeedUp = append(appNeedUp, item)
+		}
+	}
+
+	return sdkNeedUp, appNeedUp
+}
+
+//鍚屾鏇存柊璁剧疆
+func PersistentWrapper(topic string, payloads []byte) {
+	var sysSetting versionControlM.SysSetting
+	if err := json.Unmarshal(payloads, &sysSetting); nil != err {
+		logger.Error("handleSubMsg failed to persistent:", topic, string(payloads))
+	}
+	VersionUpdateSetting[sysSetting.Name] = sysSetting.Value
+}
+
+//鑾峰彇鏇存柊鎻愰啋
+func GetUpdateNotice() UpdateNoticeInfo {
+	return updateNoticeInfo
+}
+
+//寤惰繜鎻愰啋
+func DelayNotice(uid string, second int) UpdateNoticeInfo {
+	updateNoticeInfo.NoticeUser[uid] = second
+	return updateNoticeInfo
+}
+
+//鑾峰彇鏂囦欢鐩綍
+func GetDirFiles(path string) ([]string, error) {
+	files, err := filepath.Glob(filepath.Join(path, "*"))
+	return files, err
+}
+
+//鑾峰彇棰勪笅杞借矾寰�
+func GetPredownPath() string {
+	configPatchPath := ""
+	if config.Server.PatchPath != "" {
+		configPatchPath = config.Server.PatchPath
+	} else {
+		configPatchPath = "../patch"
+	}
+	return configPatchPath
+}
+
+//妫�鏌ユ槸鍚﹀凡缁忎笅杞�
+func CheckPreDown(version string, sdkName string) bool {
+	predowns, err := GetDirFiles(GetPredownPath())
+	if nil == err {
+		for _, item := range predowns {
+			if strings.Contains(item, sdkName+"-"+version) {
+				return true
+			}
+		}
+	}
+	return false
+}
diff --git a/appcenter-service/service/depend.go b/appcenter-service/service/depend.go
new file mode 100644
index 0000000..5981cc6
--- /dev/null
+++ b/appcenter-service/service/depend.go
@@ -0,0 +1,189 @@
+package service
+
+import (
+	"basic.com/valib/bhomedbapi.git"
+	"basic.com/valib/licence.git"
+	"basic.com/valib/logger.git"
+	"encoding/json"
+	"errors"
+	"github.com/mitchellh/mapstructure"
+	"io/ioutil"
+	"os"
+	"path"
+	"strings"
+	"sync"
+	"time"
+	"vamicro/config"
+	"vamicro/extend/util"
+)
+
+//瀹夎渚濊禆
+func installDepend(insDir string) error {
+	depDir := insDir + "/toolkits"
+	depDef := depDir + "/depend_enc.def"
+	if util.DirExists(depDir) && util.FileExists(depDef) {
+		depB, err := util.CallDecFileContent(depDef)
+		if err != nil {
+			logger.Error("CallDecFileContent depDef err:", err)
+			return err
+		}
+		depArr := strings.Split(string(depB), ":")
+		for _, depName := range depArr {
+			if util.DirExists(depDir+"/"+depName) && util.DirExists("/opt/toolkits") && !util.DirExists("/opt/toolkits/"+depName) {
+				_, err = util.CopyDirByCmd(depDir+"/"+depName, "/opt/toolkits/")
+				if err != nil {
+					logger.Error("copy dep ", depName, " err:", err)
+					continue
+				}
+			}
+		}
+	}
+	return nil
+}
+
+type sdkConfig struct {
+	RunTime string `json:"runtime"`
+}
+
+//鍔ㄦ�佺洃娴嬬畻娉曚緷璧栨枃浠舵槸鍚﹀瓨鍦紝涓嶅瓨鍦ㄥ垯灏濊瘯鍦ㄧ嚎涓嬭浇
+const binPath = "/opt/vasystem/bin"
+
+var depInstallingMap sync.Map
+
+func downloadDepend(sdks []SdkIns) error {
+	for _, s := range sdks {
+		sdkTyp := s.SdkType
+		jsf := binPath + "/zconf/" + sdkTyp + ".json"
+		if util.FileExists(jsf) {
+			fData, err := ioutil.ReadFile(jsf)
+			if err != nil {
+				logger.Error("open ", sdkTyp, " config err:", err)
+				continue
+			}
+			var sc sdkConfig
+			err = json.Unmarshal(fData, &sc)
+			if err != nil {
+				logger.Error("unmarshal sdkConfig err:", err)
+				continue
+			}
+			depArr := strings.Split(sc.RunTime, ":")
+			for _, dep := range depArr {
+				if dep == "/opt/vasystem/libs/"+sdkTyp {
+					continue
+				}
+				if strings.HasPrefix(dep, "/opt/toolkits/") {
+					tmp := strings.Replace(dep, "/opt/toolkits", "", -1)
+					idx := strings.Index(tmp, "/")
+					if idx > 0 {
+						depName := tmp[:idx]
+						if util.DirExists("/opt/toolkits") && !util.DirExists("/opt/toolkits/"+depName) {
+							_, ok := depInstallingMap.Load(depName)
+							if !ok {
+								go depOnline(depName)
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	return nil
+}
+
+//鍦ㄧ嚎涓嬭浇渚濊禆
+func depOnline(depName string) error {
+	depInstallingMap.Store(depName, depName)
+	defer depInstallingMap.Delete(depName)
+	url := "http://" + util.GetShopUrl() + "/data/api-s/sdk/depend"
+	machineCode := licence.GetMachineCode()
+	if machineCode == "" {
+		logger.Debug("depOnline 鑾峰彇鏈哄櫒鐮佸け璐�")
+		return errors.New("鑾峰彇鏈哄櫒鐮佸け璐�")
+	}
+	paramBody := map[string]interface{}{
+		"depName":     depName,
+		"machineCode": machineCode,
+		"serverId":    config.Server.AnalyServerId,
+	}
+	header := map[string]string{
+		"Authorization": token,
+	}
+	respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*60)
+	if err != nil {
+		logger.Debug("DoPostRequest err:", err)
+		return err
+	}
+	var res bhomedbapi.Result
+	if err = json.Unmarshal(respBody, &res); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return err
+	}
+	if !res.Success {
+		logger.Debug("res.Data:", res.Data)
+		return errors.New("璇锋眰鍟嗗煄澶辫触")
+	}
+	logger.Debug("res.Data:", res.Data)
+	var resp downOrUpResp
+	if err := mapstructure.Decode(res.Data.(map[string]interface{}), &resp); err != nil {
+		logger.Debug("mapstructure.Decode err:", err)
+		return err
+	}
+	logger.Debug("resp:", resp)
+	if resp.Url == "" || resp.Md5 == "" {
+		return errors.New("鑾峰彇渚濊禆鍖呬笅杞藉湴鍧�澶辫触")
+	}
+	logger.Info("渚濊禆椤�:", depName, " 鍦ㄧ嚎瀹夎鍖呭ぇ灏�:", resp.Size)
+	configPatchPath := ""
+	if config.Server.PatchPath != "" {
+		configPatchPath = config.Server.PatchPath
+	} else {
+		configPatchPath = "/opt/vasystem/patch"
+	}
+	if !util.DirExists(configPatchPath) {
+		os.Mkdir(configPatchPath, 0777)
+	}
+	filenameWithSuffix := path.Base(resp.Url)
+	ext := path.Ext(filenameWithSuffix)
+	gzFilePath := configPatchPath + "/" + resp.Md5 + ext
+
+	ip := &InsProgress{
+		Status:   InsStatus_Downloading,
+		Progress: 0,
+		Size:     resp.Size,
+	}
+	defer func() {
+		if util.FileExists(gzFilePath) {
+			os.Remove(gzFilePath)
+		}
+	}()
+	if !util.FileExists(gzFilePath) {
+		err := DownloadFile(gzFilePath, resp.Url, ip)
+		if err != nil {
+			logger.Debug("DownloadFile err:", err)
+			return err
+		}
+		rmd5, err := util.FileMd5(gzFilePath)
+		if err != nil {
+			logger.Error("FileMd5 err:", err)
+			return err
+		}
+		if rmd5 != resp.Md5 {
+			err = errors.New("涓嬭浇鐨勪緷璧栨枃浠舵牎楠宮d5澶辫触锛岃閲嶆柊涓嬭浇")
+			logger.Error(err)
+			return err
+		}
+	}
+	//瑙e帇瀹夎渚濊禆
+	depPath := "/opt/toolkits/" + depName
+	if !util.DirExists(depPath) {
+		os.Mkdir(configPatchPath, os.ModePerm)
+	}
+	out, err := util.UnTarGzByCmd(gzFilePath, depPath)
+	logger.Info("UnTarGzByCmd depName:", depName, " err:", err, " out:", out)
+	if err != nil {
+		os.RemoveAll(depPath)
+		return err
+	}
+
+	return nil
+}
diff --git a/appcenter-service/service/proc.go b/appcenter-service/service/proc.go
new file mode 100644
index 0000000..d69d506
--- /dev/null
+++ b/appcenter-service/service/proc.go
@@ -0,0 +1,6 @@
+package service
+
+
+const (
+	ProcName = "appcenter-service"
+)
diff --git a/appcenter-service/service/sdkService.go b/appcenter-service/service/sdkService.go
new file mode 100644
index 0000000..69825ec
--- /dev/null
+++ b/appcenter-service/service/sdkService.go
@@ -0,0 +1,170 @@
+package service
+
+import (
+	"basic.com/pubsub/protomsg.git"
+	"basic.com/valib/bhomeclient.git"
+	"basic.com/valib/licence.git"
+	"basic.com/valib/logger.git"
+	"encoding/json"
+	"errors"
+	"github.com/satori/go.uuid"
+	"time"
+	"vamicro/appcenter-service/models"
+	"vamicro/appcenter-service/vo"
+	"vamicro/config"
+	"vamicro/extend/util"
+)
+
+type SdkService struct {
+	bk bhomeclient.Broker
+}
+
+func NewSdkService(broker bhomeclient.Broker) *SdkService {
+	return &SdkService{
+		bk: broker,
+	}
+}
+
+type res struct {
+	Code    int         `json:"code"`
+	Success bool        `json:"success"`
+	Msg     string      `json:"msg"`
+	Data    interface{} `json:"data"`
+}
+
+func GetLicenseFromShopCenter(sdkId string) (string, error) {
+	url := "http://" + util.GetShopUrl() + "/data/api-s/sdk/dev/license"
+	machineCode := licence.GetMachineCode()
+	logger.Debug("url:", url, "machineCode:", machineCode)
+	paramBody := map[string]interface{}{
+		"devId": config.Server.AnalyServerId,
+		"sdkId": sdkId,
+	}
+	header := map[string]string{
+		"Authorization": token,
+	}
+	respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*2)
+	if err != nil {
+		logger.Debug("DoPostRequest err:", err)
+		return "", nil
+	}
+	var r res
+	if err = json.Unmarshal(respBody, &r); err != nil {
+		logger.Debug("unmarshal err:", err)
+		return "", nil
+	}
+	bts, _ := json.Marshal(r.Data)
+	var m map[string]interface{}
+	if err := json.Unmarshal(bts, &m); err != nil {
+		return "", err
+	}
+	if lce, ok := m["license"]; ok {
+		return lce.(string), nil
+	}
+	return "", errors.New("鏈幏鍙栧埌鎺堟潈淇℃伅")
+}
+
+//瀹炴椂鐩戣鏈満绠楁硶鏄惁宸叉巿鏉�
+func (sv SdkService) WatchLicense() {
+	for {
+		var sdkE models.Sdk
+		sdks, err := sdkE.FindAll("")
+		if err == nil && sdks != nil {
+			for _, s := range sdks {
+				if s.AuthState3rd == models.AuthState3rd_UnAuth || s.AuthState3rd == models.AuthState3rd_expired {
+					//鏌ョ湅鍟嗗煄涓绠楁硶鏄惁宸叉洿鏂版巿鏉冧俊鎭�
+					if lceStr, err := GetLicenseFromShopCenter(s.Id); err == nil {
+						sdkE.Update3rdLicense(s.Id, lceStr, models.AuthState3rd_Authed)
+					}
+				}
+			}
+		}
+		time.Sleep(10 * time.Second)
+	}
+}
+
+func (sv SdkService) Register(argBody *vo.SdkRegisterVo) bool {
+	var err error
+	tx := models.GetDB().Begin()
+	defer func() {
+		if err != nil && tx != nil {
+			tx.Rollback()
+		}
+	}()
+
+	var sdkE models.Sdk
+	rows, _ := sdkE.SelectById(argBody.Id)
+	registerSdk := argBody.Copy2Sdk()
+	if rows > 0 {
+		//update
+		if err = tx.Table(sdkE.TableName()).Save(&registerSdk).Error; err != nil {
+			return false
+		}
+	} else {
+		if err = tx.Table(sdkE.TableName()).Create(&registerSdk).Error; err != nil {
+			logger.Debug("register create sdk err:", err)
+			return false
+		}
+	}
+	//deal args
+	if err = tx.Exec("delete from sdk_arg where sdk_id=?", sdkE.Id).Error; err != nil {
+		logger.Debug("register del sdkarg err:", err)
+		return false
+	}
+	if argBody.Args != nil {
+		for _, argVo := range argBody.Args {
+			if argVo.Name == "" || argVo.Alias == "" || argVo.Type == "" {
+				err = errors.New("sdk arg error")
+				logger.Debug("register sdk err:", err)
+				return false
+			}
+			sdkArgE := models.SdkArgEntity{
+				Id:    uuid.NewV4().String(),
+				SdkId: argBody.Id,
+				Scope: argVo.Scope,
+			}
+			sdkArgE.SdkArg = argVo.Copy2SdkArg()
+			if sdkArgE.ArgType == "" {
+				sdkArgE.ArgType = "target" //濡傛灉涓虹┖锛岃涓烘槸鐩爣
+			}
+			if err = tx.Table(sdkArgE.TableName()).Create(&sdkArgE).Error; err != nil {
+				logger.Debug("register sdk err:", err)
+				return false
+			}
+
+			//澶勭悊绠楁硶鍙傛暟鏋氫妇鍊�
+			if err = tx.Exec("delete from dictionary where type=?", argVo.Alias).Error; err != nil {
+				logger.Debug("register sdk err:", err)
+				return false
+			}
+			if argVo.Dics != nil && len(argVo.Dics) > 0 {
+				for _, argValEle := range argVo.Dics {
+					argValDic := models.Dictionary{
+						Id:       uuid.NewV4().String(),
+						Value:    argValEle.Value,
+						Name:     argValEle.Name,
+						Type:     argVo.Alias,
+						Sort:     argValEle.Sort,
+						ParentId: argBody.Id, //灞炰簬鍝釜绠楁硶
+					}
+					if err = tx.Table(argValDic.TableName()).Create(&argValDic).Error; err != nil {
+						logger.Debug("register sdk err:", err)
+						return false
+					}
+				}
+			}
+		}
+	}
+	tx.Commit()
+	sv.AddDbChangeMsg(protomsg.DbAction_Insert)
+	return true
+}
+
+func (sv SdkService) AddDbChangeMsg(action protomsg.DbAction) {
+	pMsg := protomsg.DbChangeMessage{
+		Table:  protomsg.TableChanged_T_Sdk,
+		Action: action,
+	}
+	pb, _ := json.Marshal(pMsg)
+	sv.bk.Publish(ProcName, pb)
+}
diff --git a/appcenter-service/vo/sdk.go b/appcenter-service/vo/sdk.go
new file mode 100644
index 0000000..27442f0
--- /dev/null
+++ b/appcenter-service/vo/sdk.go
@@ -0,0 +1,102 @@
+package vo
+
+import (
+	"strings"
+	"time"
+	"vamicro/appcenter-service/models"
+)
+
+type SdkVo struct {
+	models.Sdk
+	Args    		[]models.SdkArg `json:"args"` //绠楁硶鍙傛暟
+}
+
+type SdkRegisterVo struct {
+	Id 				string 					`json:"id"`
+	SdkType 		string 					`json:"sdk_type"`//浜鸿劯妫�娴嬶細FaceDetect,浜鸿劯鎻愬彇锛欶aceExtract,浜鸿劯姣斿锛欶aceCompare,琛屼负锛歒olo
+	SdkName 		string 					`json:"sdk_name"`    //绠楁硶鍚嶇О
+	Args    		[]SdkRegisterArgVo 		`json:"args"` //绠楁硶鍙傛暟
+	Icon    		string 					`json:"icon"`       //绠楁硶鍥炬爣
+	Url     		string 					`json:"url"`                       //绠楁硶涓嬭浇鍦板潃
+	IconBlob 		string 					`json:"iconBlob"` //鍥剧墖
+	IconBlob2 		string 					`json:"iconBlob2"` //绗簩濂楀浘鐗�
+	Version 		string 					`json:"version"` //鐗堟湰鍙�
+	EnTrack 		bool 					`json:"enTrack"`
+	ArgDef 			string 					`json:"argDef"`
+	RuleSo 			string 					`json:"rule_so"`
+	BaseVersion 	string 					`json:"baseVersion"`
+}
+
+type SdkRegisterArgVo struct {
+	Scope string `json:"scope"`
+	models.SdkArg
+
+	Dics []SdkArgDic `json:"dics"` //濡傛灉姝ょ畻娉曞弬鏁版槸琚�夐」锛岄渶瑕佸皢鍙傛暟鏋氫妇鍊煎啓鍏ュ埌瀛楀吀琛ㄤ腑
+}
+
+type SdkArgDic struct {
+	Value string `json:"value"`
+	Name string `json:"name"`
+	Sort int `json:"sort"`
+}
+
+func (sra *SdkRegisterArgVo) Copy2SdkArg() models.SdkArg {
+	return sra.SdkArg
+}
+
+func (sv *SdkRegisterVo)Copy2Sdk() models.Sdk {
+	argDef := strings.Replace(sv.ArgDef, "\\u003c", "<", -1)
+	argDef = strings.Replace(argDef, "\\u003e", ">", -1)
+	argDef = strings.Replace(argDef, "\\u0026", "&", -1)
+	return models.Sdk{
+		Id         :sv.Id,
+		IpcId      :"",
+		SdkType    :sv.SdkType,
+		SdkName    :sv.SdkName,
+		Icon       :sv.Icon,
+		Url        :sv.Url,
+		CreateTime :time.Now().Format("2006-01-02 15:04:05"),
+		CreateBy   :"basic",
+		UpdateTime :time.Now().Format("2006-01-02 15:04:05"),
+		Enable     :true,
+		DelFlag    :0,
+		IconBlob: sv.IconBlob,
+		IconBlob2: sv.IconBlob2,
+		Version: sv.Version,
+		EnTrack: sv.EnTrack,
+		ArgDef: argDef,
+		RuleSo: sv.RuleSo,
+		BaseVersion: sv.BaseVersion,
+	}
+}
+
+type SdkArgDefault struct {
+	SdkId 					string 			`json:"sdkId" binding:"required"`
+	DefArgs 				[]ArgDefault 	`json:"defArgs" binding:"required"`
+}
+
+type ArgDefault struct {
+	ArgType 				string 			`json:"arg_type" example:"鏍囩:label,鐩爣:target"`
+	Alias 					string 			`json:"alias" example:"鍙傛暟鍒悕,渚嬪锛歝onfidence"`
+	Name 					string   		`json:"name" example:"鍙傛暟鍚�,渚嬪:缃俊搴�"`
+	Type 					string 			`json:"type" example:"绫诲瀷,鍊�:value,閫夐」:option"`
+	Operators 				[]OperatorKV 	`json:"operators"`
+	DefaultValue 			string 			`json:"default_value" example:"榛樿鍊�"`
+	Unit 					string  		`json:"unit" example:"鍗曚綅"`
+	Range 					string  		`json:"range" example:"鍙栧�艰寖鍥达紝渚嬪:[1,100]"`
+	Sort 					int 			`json:"sort"`
+
+	Config 					ArgConfig 		`json:"config"`
+}
+
+type OperatorKV struct {
+	Operator 				string 		`json:"operator"`
+	Name 					string 		`json:"name"`
+}
+
+type ArgConfig struct {
+	IsShow 					bool 		`json:"isShow"` //鏄惁鍙
+	IsConfigurable			bool 		`json:"isConfigurable"`  //鏄惁鍙厤
+	IsOptional 				bool 		`json:"isOptional"`   //鏄惁鍙��
+	IsMulti					bool 		`json:"isMulti"`  //鏄惁澶氶��
+}

--
Gitblit v1.8.0