maxiaoshan 1 жил өмнө
parent
commit
3e24f86df3

+ 2 - 0
src/config.json

@@ -30,6 +30,8 @@
         }
     },
 	"msgserveraddrfile": "spdata.jianyu360.com:802",
+    "msgserveraddrchromedp": "spdata.jianyu360.com:807",
+    "msgserveraddrchromedptest": "spdata.jianyu360.com:807",
     "msgname":"editor",
     "uploadevents": {
         "7100": "bid",

+ 1 - 0
src/front/front.go

@@ -124,6 +124,7 @@ func (f *Front) Login() error {
 		f.SetSession("email", (*user)["s_email"])
 		f.SetSession("auth", (*user)["i_auth"])
 		f.SetSession("platform", (*user)["s_platform"])
+		f.SetSession("identity", (*user)["i_identity"])
 		comeintime := time.Unix((*user)["l_comeintime"].(int64), 0).Format("2006-01-02")
 		f.SetSession("comeintime", comeintime)
 		if qu.IntAll((*user)["i_auth"]) > u.Role_Admin {

+ 220 - 86
src/front/spider.go

@@ -13,7 +13,7 @@ import (
 
 	mu "mfw/util"
 	qu "qfw/util"
-	util "spiderutil"
+	sp "spiderutil"
 	"strings"
 	"time"
 	u "util"
@@ -56,6 +56,7 @@ type Step2 struct {
 	DateFormat     string
 	Expert         string
 	Types          int
+	Chrome         string
 }
 
 type Step3 struct {
@@ -66,6 +67,7 @@ type Step3 struct {
 	T_date         string
 	Expert         string
 	Types          int
+	Chrome         string
 }
 
 type StepRe3 struct {
@@ -101,7 +103,7 @@ func (f *Front) LoadSpider(codeTaskIdReState string) error {
 	}
 	copy := f.GetString("copy")
 	if f.Method() == "GET" {
-		code := util.Se.Decode4Hex(code)
+		code := sp.Se.Decode4Hex(code)
 		f.T["actiontext"] = "编辑"
 		//lua, _ := u.MgoE.FindOne("luaconfig", map[string]interface{}{"code": code})
 		lua, _ := u.MgoEB.FindOne("luaconfig", map[string]interface{}{"code": code})
@@ -169,7 +171,7 @@ func (f *Front) LoadSpider(codeTaskIdReState string) error {
 				f.T["spidermovevent"] = (*lua)["spidermovevent"]
 				f.T["spiderhistorymaxpage"] = (*lua)["spiderhistorymaxpage"]
 				events := []string{}
-				for k, _ := range util.Config.Uploadevents {
+				for k, _ := range sp.Config.Uploadevents {
 					events = append(events, k)
 				}
 				sort.Strings(events)
@@ -191,7 +193,7 @@ func (f *Front) ViewSpider(id string) error {
 	auth := qu.IntAll(f.GetSession("auth"))
 	if auth >= 1 {
 		if f.Method() == "GET" {
-			code := util.Se.Decode4Hex(id)
+			code := sp.Se.Decode4Hex(id)
 			f.T["actiontext"] = "编辑"
 			//lua, _ := u.MgoE.FindOne("luaconfig", map[string]interface{}{"code": code})
 			lua, _ := u.MgoEB.FindOne("luaconfig", map[string]interface{}{"code": code})
@@ -216,7 +218,7 @@ func (f *Front) ViewSpider(id string) error {
 				f.T["spidermovevent"] = (*lua)["spidermovevent"]
 				f.T["spiderhistorymaxpage"] = (*lua)["spiderhistorymaxpage"]
 				events := []string{}
-				for k, _ := range util.Config.Uploadevents {
+				for k, _ := range sp.Config.Uploadevents {
 					events = append(events, k)
 				}
 				sort.Strings(events)
@@ -249,9 +251,14 @@ func (f *Front) LoadModel(id string) error {
 }
 
 func (f *Front) SaveStep() {
+	rep := map[string]interface{}{}
+	if f.Step2.Types == 2 || f.Step3.Types == 2 { //chrome模式只支持转成专家模式保存
+		rep["msg"] = "爬虫不支持chrome模式保存"
+		f.ServeJson(rep)
+		return
+	}
 	userid, _ := f.GetSession("userid").(string)
 	auth := qu.IntAll(f.GetSession("auth"))
-	rep := map[string]interface{}{}
 	if f.GetString("oldlua") != "" {
 		id := f.GetString("code")
 		//one, _ := u.MgoE.FindOne("luaconfig", map[string]interface{}{"code": id})
@@ -269,7 +276,7 @@ func (f *Front) SaveStep() {
 			b := u.MgoEB.Update("luaconfig", map[string]interface{}{"code": id}, map[string]interface{}{"$set": upset}, true, false)
 			if b {
 				rep["msg"] = "保存成功"
-				rep["code"] = util.Se.Encode2Hex(id)
+				rep["code"] = sp.Se.Encode2Hex(id)
 				f.ServeJson(rep)
 				return
 			}
@@ -343,6 +350,9 @@ func (f *Front) SaveStep() {
 				f.Step3.ContentChooser,
 				f.Step3.ElementChooser,
 			}
+			param_list_chrome, param_content_chrome := []sp.ChromeActions{}, []sp.ChromeActions{}
+			json.Unmarshal([]byte(f.Step2.Chrome), &param_list_chrome)
+			json.Unmarshal([]byte(f.Step3.Chrome), &param_content_chrome)
 			param := map[string]interface{}{}
 			common[4] = 1
 			param["param_common"] = common
@@ -351,13 +361,18 @@ func (f *Front) SaveStep() {
 			//向导模式
 			param["param_time"] = ptime
 			param["param_list"] = list
+			param["param_list_chrome"] = param_list_chrome
+			param["param_content_chrome"] = param_content_chrome
 			param["param_content"] = content
 			param["type_time"] = f.Step1.Types
 			param["type_list"] = f.Step2.Types
 			param["type_content"] = f.Step3.Types
+
 			//专家模式
 			param["str_time"] = f.Step1.Expert
 			param["str_list"] = f.Step2.Expert
+			param["str_list_chrome"] = f.Step2.Chrome
+			param["str_content_chrome"] = f.Step3.Chrome
 			param["str_content"] = f.Step3.Expert
 			param["comeintime"] = comeintime
 			listcheck = strings.Replace(listcheck, "\n", "\\\\n", -1)
@@ -366,7 +381,7 @@ func (f *Front) SaveStep() {
 			param["contentcheck"] = strings.Replace(contentcheck, "\"", "\\\\\"", -1)
 			//补充模型
 			s_model := f.GetString("model")
-			configModel := util.Config.Model[s_model]
+			configModel := sp.Config.Model[s_model]
 			model := map[string]interface{}{}
 			for k, _ := range configModel {
 				model[k] = f.GetString(k)
@@ -421,7 +436,7 @@ func (f *Front) SaveStep() {
 			} else if f.OtherBase.SpiderType == "increment" && err == nil { //增量
 				param["event"] = tmpEvent //开发人员切换增量节点
 			}
-			if movevent, ok := util.Config.Uploadevents[f.OtherBase.SpiderMoveEvent].(string); ok && movevent != "" {
+			if movevent, ok := sp.Config.Uploadevents[f.OtherBase.SpiderMoveEvent].(string); ok && movevent != "" {
 				param["spidermovevent"] = movevent
 			}
 			//开发人员修改爬虫节点后,在审核人员上架时,要在原来的节点下架,临时记录要下架的节点downevent
@@ -433,7 +448,8 @@ func (f *Front) SaveStep() {
 			param["iscopycontent"] = f.StepRe3.Checked
 			//
 			param["listisfilter"] = ListFilterReg.MatchString(f.Step2.Expert) //列表页校验是否含“--关键词过滤”
-			checkLua := LuaTextCheck(f.Base.SpiderCode, f.Step2.Expert, f.Step3.Expert, f.Step2.Types, infoformat, model, msgResult)
+			checkLua := LuaTextCheck(infoformat, param, param_list_chrome, param_content_chrome, msgResult)
+			//checkLua := LuaTextCheck(f.Base.SpiderCode, f.Step2.Expert, f.Step3.Expert, f.Step2.Types, infoformat, model, msgResult)
 			if !checkLua {
 				issave := spider.SaveSpider(code, param) //保存脚本
 				if issave {
@@ -455,7 +471,7 @@ func (f *Front) SaveStep() {
 				rep["msg"] = "保存失败," + msgResult["err"]
 				rep["ok"] = false
 			}
-			rep["code"] = util.Se.Encode2Hex(code)
+			rep["code"] = sp.Se.Encode2Hex(code)
 			f.ServeJson(rep)
 		}
 	}
@@ -549,7 +565,7 @@ func LuaSaveLog(code, user string, data *map[string]interface{}, stype int) {
 	}
 }
 
-//爬虫保存时,检查列表页和三级页代码中是否含lua原生方法
+/*爬虫保存时,检查列表页和三级页代码中是否含lua原生方法
 func LuaTextCheck(code, list, detail string, type_list, infoformat int, model map[string]interface{}, msgResult map[string]string) bool {
 	defer qu.Catch()
 	//1、异常校验
@@ -616,6 +632,94 @@ func LuaTextCheck(code, list, detail string, type_list, infoformat int, model ma
 	msgResult["warn"] += warnmsg
 	msgResult["err"] = errmsg
 	return errmsg != ""
+}*/
+func LuaTextCheck(infoformat int, param map[string]interface{}, param_list_chrome, param_content_chrome []sp.ChromeActions, msgResult map[string]string) bool {
+	code := qu.ObjToString(param["code"])
+	list := qu.ObjToString(param["str_list"])
+	detail := qu.ObjToString(param["str_content"])
+	type_list := qu.IntAll(param["type_list"])
+	type_content := qu.IntAll(param["type_content"])
+	model, _ := param["model"].(map[string]interface{})
+	defer qu.Catch()
+	//1、异常校验
+	var errmsg, warnmsg string
+	if LuaReg.MatchString(list) || LuaReg.MatchString(detail) {
+		errmsg += "代码中含有lua原生方法;"
+	}
+	if ListFilterReg.MatchString(detail) && !strings.Contains(detail, "delete") { //三级页含过滤但是没有data["delete"]="true"
+		errmsg += `三级页缺少data["delete"]="true";`
+	}
+	sln_reg := regexp.MustCompile(`sendListNum\(pageno,list\)`)
+	slnIndexArr := sln_reg.FindAllStringIndex(list, -1)
+	if type_list == 1 {
+		if strings.Contains(list, "downloadByChrome") { //chrome下载方法动作参数判断
+			for _, act := range param_list_chrome {
+				if act.Action != "changeip" && act.Param == "" {
+					errmsg += "列表页chrome模式'" + act.Action + "'动作未填写参数,填写后注意Ctrl+F10重新插入代码;"
+				}
+			}
+		}
+		if len(slnIndexArr) == 0 { //列表页专家模式且不含sendListNum
+			errmsg += "代码中缺少sendListNum(pageno,list)方法;"
+		} else if len(slnIndexArr) > 0 { //判断sendListNum方法的位置
+			trim_reg := regexp.MustCompile("trim")
+			insert_reg := regexp.MustCompile("insert")
+			trIndexArr := trim_reg.FindAllStringIndex(list, -1)
+			irIndexArr := insert_reg.FindAllStringIndex(list, -1)
+			slIndex := slnIndexArr[len(slnIndexArr)-1] //sendListNum位置
+			trIndex := trIndexArr[len(trIndexArr)-1]   //com.trim位置
+			irIndex := irIndexArr[len(irIndexArr)-1]   //insert位置
+			qu.Debug("sendListNum位置:", trIndex, slIndex, irIndex)
+			if slIndex[1] < trIndex[0] || slIndex[0] > irIndex[1] { //sendListNum方法必须在com.trim方法后,table.insert方法前
+				errmsg += "sendListNum方法位置错误;"
+			}
+		}
+		//校验列表页area、city、distric
+		if !strings.Contains(list, "area") {
+			errmsg += `模板item["area"]不存在;`
+		}
+		if !strings.Contains(list, "city") {
+			errmsg += `模板item["city"]不存在;`
+		}
+		if !strings.Contains(list, "district") {
+			errmsg += `模板item["district"]不存在;`
+		}
+		area := qu.ObjToString(model["area"])
+		city := qu.ObjToString(model["city"])
+		district := qu.ObjToString(model["district"])
+		if area != "" && !strings.Contains(list, area) {
+			errmsg += "省份信息与模板不一致;"
+		}
+		if city != "" && !strings.Contains(list, city) {
+			errmsg += "城市信息与模板不一致;"
+		}
+		if district != "" && !strings.Contains(list, district) {
+			errmsg += "区/县信息与模板不一致;"
+		}
+		if infoformat == 2 && !strings.Contains(detail, "projectname") {
+			errmsg += "拟建/审批数据缺少projectname字段;"
+		}
+		//校验爬虫代码的一致性
+		if !strings.Contains(list, code) {
+			errmsg += `模板item["spidercode"]值错误;`
+		}
+	}
+	if type_content == 1 {
+		if strings.Contains(detail, "downloadByChrome") { //chrome下载方法动作参数判断
+			for _, act := range param_content_chrome {
+				if act.Action != "changeip" && act.Param == "" {
+					errmsg += "详情页chrome模式'" + act.Action + "'动作未填写参数,填写后注意Ctrl+F10重新插入代码;"
+				}
+			}
+		}
+	}
+	//2、提醒校验
+	if !strings.Contains(detail, "downloadFile") && !strings.Contains(detail, "getFileAttachmentsArrayWithTag") {
+		warnmsg += "三级页缺少下载附件方法;"
+	}
+	msgResult["warn"] += warnmsg
+	msgResult["err"] = errmsg
+	return errmsg != ""
 }
 
 //方法测试
@@ -647,7 +751,7 @@ func (f *Front) RunStep() {
 	}
 	if f.Method() == "POST" {
 		switch f.GetString("step") {
-		case "step1": //publishtime
+		case "Step1": //publishtime
 			ptime := []interface{}{
 				f.Step1.DateFormat,
 				f.Step1.Address,
@@ -662,78 +766,108 @@ func (f *Front) RunStep() {
 			if err == nil {
 				f.ServeJson(rs)
 			}
-		case "step2": //list
-			addrs := strings.Split(f.Step2.Listadds, "\n")
-			if len(addrs) > 0 {
-				for k, v := range addrs {
-					addrs[k] = "'" + v + "'"
+		case "Step2": //list
+			if imodal == 2 { //chromedp测试
+				chromeActions := []sp.ChromeActions{}
+				var result []interface{}
+				if json.Unmarshal([]byte(f.Step2.Chrome), &chromeActions) == nil {
+					chromeTask := sp.ChromeTask{
+						TimeOut: 120, //测试默认两分钟
+						Actions: chromeActions,
+					}
+					result = spider.DownloadByChrome(downloadnode, "", chromeTask, 150)
+				} else {
+					result = append(result, "chrome task json 格式化错误")
 				}
-				f.Step2.Listadds = strings.Join(addrs, ",")
-			} else if len(f.Step2.Listadds) > 5 {
-				f.Step2.Listadds = "'" + f.Step2.Listadds + "'"
+				f.ServeJson(result)
 			} else {
-				f.Step2.Listadds = ""
-			}
-			list := []interface{}{
-				f.Step2.Listadd,
-				f.Step2.Listadds,
-				f.Step2.BlockChooser,
-				f.Step2.AddressChooser,
-				f.Step2.TitleChooser,
-				f.Step2.DateChooser,
-				f.Step2.DateFormat,
-			}
-			listcheck = strings.Replace(listcheck, "\n", "\\n", -1)
-			listcheck = strings.Replace(listcheck, "\"", "\\\"", -1)
-			s_model := f.GetString("model")
-			configModel := util.Config.Model[s_model]
-			model := map[string]interface{}{}
-			for k, _ := range configModel {
-				model[k] = f.GetString(k)
-			}
-			if script {
-				_, script := spider.GetPageList(common, list, model, listcheck, f.Step2.Expert, downloadnode, imodal, 1)
-				f.ServeJson(script)
-				return
-			}
-			rs, err := spider.GetPageList(common, list, model, listcheck, f.Step2.Expert, downloadnode, imodal)
-			if err == nil {
-				f.ServeJson(rs)
-			} else if err.(error).Error() == "no" {
-				f.ServeJson(rs[0])
-			}
-		case "step3": //detail
-			content := []interface{}{
-				f.Step3.ContentChooser,
-				f.Step3.ElementChooser,
+				addrs := strings.Split(f.Step2.Listadds, "\n")
+				if len(addrs) > 0 {
+					for k, v := range addrs {
+						addrs[k] = "'" + v + "'"
+					}
+					f.Step2.Listadds = strings.Join(addrs, ",")
+				} else if len(f.Step2.Listadds) > 5 {
+					f.Step2.Listadds = "'" + f.Step2.Listadds + "'"
+				} else {
+					f.Step2.Listadds = ""
+				}
+				list := []interface{}{
+					f.Step2.Listadd,
+					f.Step2.Listadds,
+					f.Step2.BlockChooser,
+					f.Step2.AddressChooser,
+					f.Step2.TitleChooser,
+					f.Step2.DateChooser,
+					f.Step2.DateFormat,
+				}
+				listcheck = strings.Replace(listcheck, "\n", "\\n", -1)
+				listcheck = strings.Replace(listcheck, "\"", "\\\"", -1)
+				s_model := f.GetString("model")
+				configModel := sp.Config.Model[s_model]
+				model := map[string]interface{}{}
+				for k, _ := range configModel {
+					model[k] = f.GetString(k)
+				}
+				if script {
+					_, script := spider.GetPageList(common, list, model, listcheck, f.Step2.Expert, downloadnode, imodal, 1)
+					f.ServeJson(script)
+					return
+				}
+				rs, err := spider.GetPageList(common, list, model, listcheck, f.Step2.Expert, downloadnode, imodal)
+				if err == nil {
+					f.ServeJson(rs)
+				} else if err.(error).Error() == "no" {
+					f.ServeJson(rs[0])
+				}
 			}
+		case "Step3": //detail
+			if imodal == 2 { //chromedp测试
+				chromeActions := []sp.ChromeActions{}
+				var result []interface{}
+				if json.Unmarshal([]byte(f.Step3.Chrome), &chromeActions) == nil {
+					chromeTask := sp.ChromeTask{
+						TimeOut: 120, //测试默认两分钟
+						Actions: chromeActions,
+					}
+					result = spider.DownloadByChrome(downloadnode, "", chromeTask, 150)
+				} else {
+					result = append(result, "chrome task json 格式化错误")
+				}
+				f.ServeJson(result)
+			} else {
+				content := []interface{}{
+					f.Step3.ContentChooser,
+					f.Step3.ElementChooser,
+				}
 
-			contentcheck = strings.Replace(contentcheck, "\n", "\\n", -1)
-			contentcheck = strings.Replace(contentcheck, "\"", "\\\"", -1)
-			data := map[string]interface{}{}
-			data["title"] = f.Step3.T_title
-			data["href"] = f.Step3.T_href
-			data["publishtime"] = f.Step3.T_date
-			if script {
-				_, script := spider.GetContentInfo(common, content, data, contentcheck, f.Step3.Expert, downloadnode, imodal, 1)
-				f.ServeJson(script)
-				return
-			}
-			rs, err := spider.GetContentInfo(common, content, data, contentcheck, f.Step3.Expert, downloadnode, imodal)
-			if projectinfo, ok := rs["projectinfo"].(map[string]interface{}); ok && projectinfo != nil {
-				if attachments, ok := projectinfo["attachments"].(map[string]interface{}); ok && attachments != nil {
-					for _, tmp := range attachments {
-						tmpMap := tmp.(map[string]interface{})
-						if qu.ObjToString(tmpMap["filename"]) == "附件中含有乱码" {
-							rs["msg"] = "附件中含有乱码"
+				contentcheck = strings.Replace(contentcheck, "\n", "\\n", -1)
+				contentcheck = strings.Replace(contentcheck, "\"", "\\\"", -1)
+				data := map[string]interface{}{}
+				data["title"] = f.Step3.T_title
+				data["href"] = f.Step3.T_href
+				data["publishtime"] = f.Step3.T_date
+				if script {
+					_, script := spider.GetContentInfo(common, content, data, contentcheck, f.Step3.Expert, downloadnode, imodal, 1)
+					f.ServeJson(script)
+					return
+				}
+				rs, err := spider.GetContentInfo(common, content, data, contentcheck, f.Step3.Expert, downloadnode, imodal)
+				if projectinfo, ok := rs["projectinfo"].(map[string]interface{}); ok && projectinfo != nil {
+					if attachments, ok := projectinfo["attachments"].(map[string]interface{}); ok && attachments != nil {
+						for _, tmp := range attachments {
+							tmpMap := tmp.(map[string]interface{})
+							if qu.ObjToString(tmpMap["filename"]) == "附件中含有乱码" {
+								rs["msg"] = "附件中含有乱码"
+							}
 						}
 					}
 				}
-			}
-			if err == nil {
-				f.ServeJson(rs)
-			} else {
-				f.ServeJson(rs["no"])
+				if err == nil {
+					f.ServeJson(rs)
+				} else {
+					f.ServeJson(rs["no"])
+				}
 			}
 		}
 	}
@@ -1122,7 +1256,7 @@ func (f *Front) UpState() error {
 	res := map[string]interface{}{
 		"istotask": istotask,
 		"err":      "没有权限",
-		"code":     util.Se.Encode2Hex(code),
+		"code":     sp.Se.Encode2Hex(code),
 		"taskid":   taskid,
 	}
 	var xgTime int64
@@ -1247,12 +1381,12 @@ func UpStateAndUpSpider(code, id, reason, username string, state int) (bool, err
 		if (*one)["event"] != nil {
 			event = qu.IntAll((*one)["event"])
 		} else {
-			for k, _ := range util.Config.Uploadevents { //
+			for k, _ := range sp.Config.Uploadevents { //
 				event = qu.IntAll(k)
 				break
 			}
 			//r := rand.New(rand.NewSource(time.Now().UnixNano()))
-			//event = util.Config.Uploadevents[r.Intn(len(util.Config.Uploadevents))]
+			//event = sp.Config.Uploadevents[r.Intn(len(sp.Config.Uploadevents))]
 		}
 		//oldstate := qu.IntAll(one["state"])
 		switch state {
@@ -1481,7 +1615,7 @@ func (f *Front) ChangeEvent() {
 	code := f.GetString("code")
 	event, _ := f.GetInt("event")
 	eventok := false
-	for k, _ := range util.Config.Uploadevents {
+	for k, _ := range sp.Config.Uploadevents {
 		if event == qu.Int64All(k) {
 			eventok = true
 			break
@@ -1643,7 +1777,7 @@ func (f *Front) LuaList() {
 		f.ServeJson(map[string]interface{}{"draw": draw, "data": luas, "recordsFiltered": count, "recordsTotal": count})
 	} else {
 		events := []string{}
-		for k, _ := range util.Config.Uploadevents {
+		for k, _ := range sp.Config.Uploadevents {
 			events = append(events, k)
 		}
 		sort.Strings(events)
@@ -1728,7 +1862,7 @@ func (f *Front) Heart() {
 		f.ServeJson(map[string]interface{}{"draw": draw, "data": list, "recordsFiltered": count, "recordsTotal": count})
 	} else {
 		events := []string{}
-		for k, _ := range util.Config.Uploadevents {
+		for k, _ := range sp.Config.Uploadevents {
 			events = append(events, k)
 		}
 		sort.Strings(events)
@@ -1751,7 +1885,7 @@ type spinfo struct {
 
 //爬虫信息
 func SpiderInfo(data string) {
-	data = util.Se.DecodeString(data)
+	data = sp.Se.DecodeString(data)
 	infos := []map[string]interface{}{}
 	err := json.Unmarshal([]byte(data), &infos)
 	if err != nil {
@@ -1781,7 +1915,7 @@ func SpiderInfo(data string) {
 
 //接受维护任务信息
 func SpiderModifyTask(data string) {
-	data = util.Se.DecodeString(data)
+	data = sp.Se.DecodeString(data)
 	mtasks := []map[string]interface{}{}
 	err := json.Unmarshal([]byte(data), &mtasks)
 	if err != nil {

+ 2 - 2
src/main.go

@@ -81,8 +81,8 @@ func init() {
 		qu.ObjToString(util.Config.Msgservers["bid"]["name"]),
 		qu.ObjToString(util.Config.Msgservers["test"]["name"]),
 	)
-	spider.InitMsgClientFile(util.Config.MsgserveraddrFile, util.Config.Msgname+"file")
-
+	spider.InitMsgClientFile(util.Config.MsgserveraddrFile, util.Config.Msgname+"_file")
+	spider.InitChromeMsgClient(util.Config.MsgserveraddrChromedp, util.Config.MsgserveraddrChromedpTest, util.Config.Msgname+"_chromedp", util.Config.Msgname+"_chromedptest")
 	//初始化网络存储服务
 	//util.InitWeedcl()
 	util.OssInit(

+ 1 - 1
src/res/util/comm.lua

@@ -511,7 +511,7 @@ end
 --确定模块的附件下载方法(获取title与href)
 --tags:模块选择器
 --withend:是否以文件类型为后缀,比如 .doc,true为后缀,false不为后缀
-filetype={"jpg","JPG","bid","pdf","png","PDF","docx","doc","xlsx","xls","zip","rar","swf","DOCX","DOC","PDF","XLSX","XLS","ZIP","RAR","SWF"}	 
+filetype={"jpeg","JPEG","jpg","JPG","bid","pdf","png","PDF","docx","doc","xlsx","xls","zip","rar","swf","DOCX","DOC","PDF","XLSX","XLS","ZIP","RAR","SWF"}
 function common.getFilesLinkByTag(href,tags,content,withend)
 	local dhtml = findOneHtml(tags, content)
 	--dhtml=dhtml.."<a href='/123.doc'>123.doc</a>"

+ 30 - 0
src/spider/download.go

@@ -384,6 +384,36 @@ func DownloadFile_back(downloaderid, url, method string, reqparam, head map[stri
 	}
 }
 
+func DownloadByChrome(downloadnode, downloaderid string, chrometask util.ChromeTask, timeout int64) (result []interface{}) {
+	defer mu.Catch()
+	ResultMsclient := MsclientChromedpTest
+	if downloadnode == "test" { //806
+		ResultMsclient = MsclientChromedpTest
+	} else {
+		ResultMsclient = MsclientChromedp
+	}
+	msgid := mu.UUID(8)
+	var ret []byte
+	var err error
+
+	ret = []byte{}
+	if downloaderid == "" {
+		ret, err = ResultMsclient.Call("", msgid, mu.SERVICE_DOWNLOAD, mu.SENDTO_TYPE_RAND_RECIVER, chrometask, timeout)
+	} else {
+		if isAvailable(downloaderid) {
+			ret, err = ResultMsclient.Call(downloaderid, msgid, mu.SERVICE_DOWNLOAD, mu.SENDTO_TYPE_P2P, chrometask, timeout)
+		} else {
+			return
+		}
+	}
+	if err != nil {
+		str := "方法DownloadByChrome err:" + err.Error()
+		log.Println(str)
+	}
+	json.Unmarshal(ret, &result)
+	return
+}
+
 //下载点是否可用
 func isAvailable(code string) bool {
 	b := false

+ 95 - 0
src/spider/msclient.go

@@ -17,10 +17,14 @@ var Msclient *mu.Client
 var MsclientFile *mu.Client
 var MsclientBid *mu.Client
 var MsclientTest *mu.Client
+var MsclientChromedp *mu.Client
+var MsclientChromedpTest *mu.Client
 var Alldownloader map[string]DynamicIPMap = make(map[string]DynamicIPMap)
 var AlldownloaderBid map[string]DynamicIPMap = make(map[string]DynamicIPMap)
 var AlldownloaderFile map[string]DynamicIPMap = make(map[string]DynamicIPMap)
 var AlldownloaderTest map[string]DynamicIPMap = make(map[string]DynamicIPMap)
+var AlldownloaderChromedp map[string]DynamicIPMap = make(map[string]DynamicIPMap)
+var AlldownloaderChromedpTest map[string]DynamicIPMap = make(map[string]DynamicIPMap)
 
 //
 func processevent(p *mu.Packet) {
@@ -115,6 +119,52 @@ func processeventTest(p *mu.Packet) {
 		}
 	}
 }
+func processeventChromedp(p *mu.Packet) {
+	defer mu.Catch()
+	var data []byte
+	switch p.Event {
+	case mu.SERVICE_DOWNLOAD_APPEND_NODE:
+		data = p.GetBusinessData()
+		//log.Println("获取动态地址:", len(data), string(data))
+		for i := 0; i < len(data)/8; i++ {
+			code := string(data[i*8 : (i+1)*8])
+			AlldownloaderChromedp[code] = DynamicIPMap{
+				Code:        code,
+				InvalidTime: time.Now().Unix() + 60*10,
+			}
+		}
+	case mu.SERVICE_DOWNLOAD_DELETE_NODE:
+		data = p.GetBusinessData()
+		//log.Println("删除动态地址:", len(data), string(data))
+		for i := 0; i < len(data)/8; i++ {
+			code := string(data[i*8 : (i+1)*8])
+			delete(AlldownloaderChromedp, code)
+		}
+	}
+}
+func processeventChromedpTest(p *mu.Packet) {
+	defer mu.Catch()
+	var data []byte
+	switch p.Event {
+	case mu.SERVICE_DOWNLOAD_APPEND_NODE:
+		data = p.GetBusinessData()
+		//log.Println("获取动态地址:", len(data), string(data))
+		for i := 0; i < len(data)/8; i++ {
+			code := string(data[i*8 : (i+1)*8])
+			AlldownloaderChromedp[code] = DynamicIPMap{
+				Code:        code,
+				InvalidTime: time.Now().Unix() + 60*10,
+			}
+		}
+	case mu.SERVICE_DOWNLOAD_DELETE_NODE:
+		data = p.GetBusinessData()
+		//log.Println("删除动态地址:", len(data), string(data))
+		for i := 0; i < len(data)/8; i++ {
+			code := string(data[i*8 : (i+1)*8])
+			delete(AlldownloaderChromedp, code)
+		}
+	}
+}
 
 //
 func gc4Alldownloader() {
@@ -153,6 +203,24 @@ func gc4AlldownloaderTest() {
 	}
 	time.AfterFunc(1*time.Minute, gc4AlldownloaderTest)
 }
+func gc4AlldownloaderChromedp() {
+	n := time.Now().Unix()
+	for _, v := range AlldownloaderChromedp {
+		if v.InvalidTime < n {
+			delete(AlldownloaderChromedp, v.Code)
+		}
+	}
+	time.AfterFunc(1*time.Minute, gc4AlldownloaderChromedp)
+}
+func gc4AlldownloaderChromedpTest() {
+	n := time.Now().Unix()
+	for _, v := range AlldownloaderChromedp {
+		if v.InvalidTime < n {
+			delete(AlldownloaderChromedp, v.Code)
+		}
+	}
+	time.AfterFunc(1*time.Minute, gc4AlldownloaderChromedpTest)
+}
 
 //
 func GetOneDownloader() string {
@@ -203,6 +271,12 @@ func InitMsgClient(serveraddr, serveraddrbid, serveraddrtest, name, namebid, nam
 	go gc4AlldownloaderTest()
 }
 
+//初始chrome启动消息客户端
+func InitChromeMsgClient(chromeaddr, chrometestaddr, name, nametest string) {
+	InitMsgClientChromedp(chromeaddr, name)
+	InitMsgClientChromedpTest(chrometestaddr, nametest)
+}
+
 func InitMsgClientFile(serveraddr, name string) {
 	MsclientFile, _ = mu.NewClient(&mu.ClientConfig{ClientName: name,
 		MsgServerAddr:   serveraddr,
@@ -213,3 +287,24 @@ func InitMsgClientFile(serveraddr, name string) {
 	})
 	go gc4AlldownloaderFile()
 }
+
+func InitMsgClientChromedp(serveraddr, name string) {
+	MsclientChromedp, _ = mu.NewClient(&mu.ClientConfig{ClientName: name,
+		MsgServerAddr:   serveraddr,
+		EventHandler:    processeventChromedp,
+		CanHandleEvents: []int{mu.SERVICE_DOWNLOAD_APPEND_NODE, mu.SERVICE_DOWNLOAD_DELETE_NODE},
+		ReadBufferSize:  200,
+		WriteBufferSize: 200,
+	})
+	go gc4AlldownloaderChromedp()
+}
+func InitMsgClientChromedpTest(serveraddr, name string) {
+	MsclientChromedpTest, _ = mu.NewClient(&mu.ClientConfig{ClientName: name,
+		MsgServerAddr:   serveraddr,
+		EventHandler:    processeventChromedpTest,
+		CanHandleEvents: []int{mu.SERVICE_DOWNLOAD_APPEND_NODE, mu.SERVICE_DOWNLOAD_DELETE_NODE},
+		ReadBufferSize:  200,
+		WriteBufferSize: 200,
+	})
+	go gc4AlldownloaderChromedpTest()
+}

+ 9 - 13
src/spider/script.go

@@ -831,22 +831,18 @@ func (s *Script) LoadScript(site *string, downloadnode, script string, isfile ..
 	}))
 	//chromedp下载
 	s.L.SetGlobal("downloadByChrome", s.L.NewFunction(func(S *lua.LState) int {
-		//blink := S.ToString(-4)
-		timeout := S.ToInt64(-3)
-		isProxy := S.ToBool(-2)
+		timeout := S.ToInt64(-2)
 		taskStr := S.ToString(-1)
-		task := []map[string]interface{}{}
-		tabResult := S.NewTable()
-		if json.Unmarshal([]byte(taskStr), &task) == nil {
-			chromeCase := sp.GetChromedpCase(timeout, isProxy, task)
-			qu.Debug(timeout, isProxy, *chromeCase)
-			result := sp.DownloadByChromedp(chromeCase)
-			for i, v := range result {
-				tabResult.Insert(i+1, lua.LString(v))
+		chromeActions := []sp.ChromeActions{}
+		if json.Unmarshal([]byte(taskStr), &chromeActions) == nil {
+			chromeTask := sp.ChromeTask{
+				TimeOut: timeout,
+				Actions: chromeActions,
 			}
-			S.Push(tabResult)
+			ret := DownloadByChrome(downloadnode, s.Downloader, chromeTask, s.Timeout)
+			S.Push(sp.MapToTable(S, ret))
 		} else {
-			S.Push(tabResult)
+			S.Push(lua.LString("chrome task json 格式化错误"))
 		}
 		return 1
 	}))

+ 99 - 26
src/web/staticres/js/common.js

@@ -53,25 +53,41 @@ common.form.isCheck=function(id,func){
 }
 common.form.serializeArray=function(id){
 	var serializeArray={};
+	var chromeArr = [];
 	$("#"+id+" [name]").each(function(){
 		var name=$(this).prop("name");
 		var value=$(this).prop("value");
 		if($(this).get(0).tagName=="TEXTAREA" && $(this).attr("id")){
-			if($(this).attr("id").indexOf("step1")>-1){
+			if($(this).attr("id").indexOf("Step1")>-1){
 				value=editor_1.getValue()
-			}else if($(this).attr("id").indexOf("step2")>-1){
+			}else if($(this).attr("id").indexOf("Step2")>-1){
 				value=editor_2.getValue()
-			}else if($(this).attr("id").indexOf("step3")>-1){
+			}else if($(this).attr("id").indexOf("Step3")>-1){
 				value=editor_3.getValue()
-			}else if($(this).attr("id").indexOf("stepre3")>-1){
+			}else if($(this).attr("id").indexOf("Stepre3")>-1){
 				value=editor_re3.getValue()
 			}
 		}else{
 			value=$(this).prop("value");
 			value=value?value:"";
 		}
-		serializeArray[name]=value.trim();
+		//组合有序的chrome
+		if(name.includes("Chrome")){
+			var chromeMap = {};
+			chromeMap["action"] = name.replace("Chrome.","");
+			chromeMap["param"] = value
+			var selector_val = $(this).parents(".chrome-actions").find("[sel='"+name+".selector']").val();
+			if (selector_val) {
+				chromeMap["selector"]= selector_val
+			}
+			chromeArr.push(chromeMap);
+		}else{
+			serializeArray[name]=value.trim();
+		}
 	});
+	if (chromeArr.length > 0){
+		serializeArray[id+".Chrome"] = JSON.stringify(chromeArr);
+	}
 	return serializeArray
 }
 common.form.submit=function(){}
@@ -85,8 +101,8 @@ common.spider.editjs=function (step) {
 	}, 500)
 }
 
-common.spider.initMirror=function(){
-	editor_1 = CodeMirror.fromTextArea($("#step1_mirror")[0], {
+common.spider.initMirror=function()	{
+	editor_1 = CodeMirror.fromTextArea($("#Step1_mirror")[0], {
 		theme:"solarized light",
 		lineNumbers: true,
 		indentUnit:4,
@@ -99,7 +115,7 @@ common.spider.initMirror=function(){
 			"F10": function(cm) {
 		      var r=window.confirm("生成代码后原先的将会被覆盖,是否生成?")
 			  if(r){
-				$("a[for=step1]").eq(0).trigger("click",["editor_1"])
+				$("a[for=Step1]").eq(0).trigger("click",["editor_1"])
 			  }
 		    },
 			"F9":function(cm) {
@@ -116,7 +132,7 @@ common.spider.initMirror=function(){
 		    }
 		}
 	});
-	editor_2 = CodeMirror.fromTextArea($("#step2_mirror")[0], {
+	editor_2 = CodeMirror.fromTextArea($("#Step2_mirror")[0], {
 		theme:"solarized light",
 		lineNumbers: true,
 		indentUnit:4,
@@ -127,9 +143,9 @@ common.spider.initMirror=function(){
 		        cm.setOption("fullScreen", !cm.getOption("fullScreen"));
 		    },
 			"F10": function(cm) {
-		     var r=window.confirm("生成代码后原先的将会被覆盖,是否生成?")
+		      var r=window.confirm("生成代码后原先的将会被覆盖,是否生成?")
 			  if(r){
-				$("a[for=step2]").eq(0).trigger("click",["editor_2"])
+				$("a[for=Step2]").eq(0).trigger("click",["editor_2"])
 			  }
 		    },
 			"F9":function(cm) {
@@ -141,12 +157,34 @@ common.spider.initMirror=function(){
 				var str_tab = "\t".repeat(cm.getCursor().ch);
 				cm.replaceSelection(`local attachments = com.getFileAttachmentsArrayWithTag(data["href"],"dl","<dl>"..data["contenthtml"].."</dl>",false)\n${str_tab}if table.getn(attachments)>0 then\n\t\t${str_tab}data["projectinfo"]={\n\t\t${str_tab}["attachments"]=attachments\n\t${str_tab}}\n${str_tab}end`);
 			},
+			"Ctrl-F10":function (cm){
+				if (!luaIsChrome){
+					window.alert("非chrome爬虫,禁止使用chrome下载方法");
+					return
+				}
+				var str_tab = "\t".repeat(cm.getCursor().ch);
+				var data = common.form.serializeArray("Step2");
+				var chromeActionsStr = data["Step2.Chrome"];
+				var chromeActionMapStr = chromeActionsStr.substring(1,chromeActionsStr.length - 1);
+				var regex = /{([^}]*)}/g;
+				var chromeActionsStrArr = chromeActionMapStr.match(regex);
+				var luaText = `local timeout = 60\n${str_tab}local chromeTask = [[\n${str_tab}\t[\n${str_tab}\t\t`;
+				for (var i in chromeActionsStrArr){
+					if (i == chromeActionsStrArr.length -1){
+						luaText += chromeActionsStrArr[i]+`\n${str_tab}\t`;
+					}else{
+						luaText += chromeActionsStrArr[i]+`,\n${str_tab}\t\t`;
+					}
+				}
+				luaText += `]\n${str_tab}]]\n${str_tab}local contenthtml = downloadByChrome(timeout,chromeTask)`
+				cm.replaceSelection(luaText);
+			},
 		    "Esc": function(cm) {
 		        if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
 		    }
 		}
 	});
-	editor_3 = CodeMirror.fromTextArea($("#step3_mirror")[0], {
+	editor_3 = CodeMirror.fromTextArea($("#Step3_mirror")[0], {
 		theme:"solarized light",
 		lineNumbers: true,
 		indentUnit:4,
@@ -159,7 +197,7 @@ common.spider.initMirror=function(){
 			"F10": function(cm) {
 		      var r=window.confirm("生成代码后原先的将会被覆盖,是否生成?")
 			  if(r){
-				$("a[for=step3]").eq(0).trigger("click",["editor_3"])
+				$("a[for=Step3]").eq(0).trigger("click",["editor_3"])
 			  }
 		    },
 			"F9":function(cm) {
@@ -171,6 +209,28 @@ common.spider.initMirror=function(){
 				var str_tab = "\t".repeat(cm.getCursor().ch);
 				cm.replaceSelection(`local attachments = com.getFileAttachmentsArrayWithTag(data["href"],"dl","<dl>"..data["contenthtml"].."</dl>",false)\n${str_tab}if table.getn(attachments)>0 then\n\t\t${str_tab}data["projectinfo"]={\n\t\t${str_tab}["attachments"]=attachments\n\t${str_tab}}\n${str_tab}end`);
 			},
+			"Ctrl-F10":function (cm){
+				if (!luaIsChrome){
+					window.alert("非chrome爬虫,禁止使用chrome下载方法");
+					return
+				}
+				var str_tab = "\t".repeat(cm.getCursor().ch);
+				var data = common.form.serializeArray("Step3");
+				var chromeActionsStr = data["Step3.Chrome"];
+				var chromeActionMapStr = chromeActionsStr.substring(1,chromeActionsStr.length - 1);
+				var regex = /{([^}]*)}/g;
+				var chromeActionsStrArr = chromeActionMapStr.match(regex);
+				var luaText = `local timeout = 60\n${str_tab}local chromeTask = [[\n${str_tab}\t[\n${str_tab}\t\t`;
+				for (var i in chromeActionsStrArr){
+					if (i == chromeActionsStrArr.length -1){
+						luaText += chromeActionsStrArr[i]+`\n${str_tab}\t`;
+					}else{
+						luaText += chromeActionsStrArr[i]+`,\n${str_tab}\t\t`;
+					}
+				}
+				luaText += `]\n${str_tab}]]\n${str_tab}local contenthtml = downloadByChrome(timeout,chromeTask)`
+				cm.replaceSelection(luaText);
+			},
 		    "Esc": function(cm) {
 		        if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
 		    }
@@ -401,19 +461,32 @@ common.spider.upload=function(code){
 	});
 }
 common.spider.save_unnew=function(){
-	var base=common.form.serializeArray("baseinfo");
-	var step1=common.form.serializeArray("step1");
-	var step2=common.form.serializeArray("step2");
-	var step3=common.form.serializeArray("step3");
-	var stepre3=common.form.serializeArray("stepre3");
-	step1["Step1.types"]=$("[href='#tab_1']").parent().attr("data-mode");
-	step1["Step1.types"]=step1["Step1.types"]=="guide"?"0":"1"
-	step1["Step2.types"]=$("[href='#tab_2']").parent().attr("data-mode");
-	step1["Step2.types"]=step1["Step2.types"]=="guide"?"0":"1"
-	step1["Step3.types"]=$("[href='#tab_3']").parent().attr("data-mode");
-	step1["Step3.types"]=step1["Step3.types"]=="guide"?"0":"1"
-	stepre3["StepRe3.Checked"] = $("#copyTab").prop('checked');//是否复制三级页
-	var all=$.extend({},base,step1,step2,step3,stepre3);
+	var base=common.form.serializeArray("baseinfo");//基本参数
+	var Step1=common.form.serializeArray("Step1");//发布时间
+	var Step2=common.form.serializeArray("Step2");//列表页
+	var Step3=common.form.serializeArray("Step3");//详情页
+	var Stepre3=common.form.serializeArray("Stepre3");
+	//设置types
+	Step1["Step1.types"]=$("[href='#tab_1']").parent().attr("data-mode");
+	Step1["Step1.types"]=Step1["Step1.types"]=="guide"?"0":"1"
+	var Step2_type = $("[href='#tab_2']").parent().attr("data-mode");
+	if (Step2_type === "chrome"){
+		Step1["Step2.types"]="2"
+	}else if (Step2_type === "expert"){
+		Step1["Step2.types"]="1"
+	}else if (Step2_type === "guide"){
+		Step1["Step2.types"]="0"
+	}
+	var Step3_type = $("[href='#tab_3']").parent().attr("data-mode");
+	if (Step3_type === "chrome"){
+		Step1["Step3.types"]="2"
+	}else if (Step3_type === "expert"){
+		Step1["Step3.types"]="1"
+	}else if (Step3_type === "guide"){
+		Step1["Step3.types"]="0"
+	}
+	Stepre3["StepRe3.Checked"] = $("#copyTab").prop('checked');//是否复制三级页
+	var all=$.extend({},base,Step1,Step2,Step3,Stepre3);
 	$.ajax({
 		url:"/center/save",
 		method:"post",

+ 4 - 4
src/web/templates/bottom.html

@@ -14,11 +14,11 @@
 <script src="/codemirror/fullscreen.js"></script>
 <script>
 	$(function(){
-		if($("#step1_mirror").length>0){
+		if($("#Step1_mirror").length>0){
 			common.spider.initMirror();
-			$("#step1_mirror").parent().addClass("hide");
-			$("#step2_mirror").parent().addClass("hide");
-			$("#step3_mirror").parent().addClass("hide");
+			$("#Step1_mirror").parent().addClass("hide");
+			$("#Step2_mirror").parent().addClass("hide");
+			$("#Step3_mirror").parent().addClass("hide");
 		}
 		$(".edit-step>li").each(function(){
 		    common.spider.guideActive($(this).attr("data-mode"),this)

+ 0 - 1
src/web/templates/errlualist.html

@@ -99,7 +99,6 @@
           return div.html()
 				}},
         {"data": "encode",render:function(val,a,row){
-          console.log(row.modifytime)
           var button
            var div=$("<div><div class=\"btn-group\"></div></div>")
           if(row.modifytime==null){

+ 10 - 6
src/web/templates/head.html

@@ -27,7 +27,7 @@
   <link rel="stylesheet" href="/time/css/wui.min.css">
   <link rel="stylesheet" href="/time/css/style.css">
 	<link rel="stylesheet"  href="/css/otherStyle.css">
-	
+
 	<script src="/plugins/jQuery/jquery-2.2.3.min.js"></script>
 	<script src="/js/common.js"></script>
 	<script src="/js/bootstrap.min.js"></script>
@@ -35,6 +35,7 @@
 	<script src="/js/bootstrap-datetimepicker.fr.js"></script>
 	<script src="/js/model.js"></script>
 	<script src="/js/head.js"></script>
+	<script src="/js/xm-select.js"></script>
 	<style>
 		#myModal-feedback .close{
 			margin-top:-19px;
@@ -583,7 +584,7 @@
 				  <li><a href="/admin/task/export"><i class="fa fa-link"></i>监控信息</a></li>
 			  </ul>
 		  </li>
-		  {{else if eq (session "auth") 3}}
+		{{else if eq (session "auth") 3}}
 			<li data="index"><a href="/center"><i class="glyphicon glyphicon-eye-open"></i> <span>脚本列表</span></a></li>
 			<li data="index_rwgl"><a href="/center/managerTask"><i class="glyphicon glyphicon glyphicon-tasks"></i> <span>任务管理</span></a></li>
 			<li data="index_fbgl"><a href="/center/lualist.html"><i class="glyphicon glyphicon-credit-card"></i> <span>运行监控中心</span></a></li>
@@ -597,13 +598,18 @@
 			<li data="index"><a href="/center"><i class="glyphicon glyphicon-eye-open"></i> <span>爬虫列表</span></a></li>
 			<li data="index_rwlb"><a href="/center/mytask"><i class="glyphicon glyphicon-tasks"></i> <span>任务列表</span></a></li>
 		{{end}}
+
 		{{if eq (session "platform") "golua平台"}}
-     	<li data="index_heart"><a href="/center/heart"><i class="fa fa-heartbeat"></i> <span>心跳监控</span></a></li>
-    	<li data="index_errlua"><a href="/center/errorLua"><i class="fa fa-warning"></i> <span>错误爬虫管理</span></a></li>
+		  {{if eq (session "identity") 1}}
+		  <li data="index_heart"><a href="/center/heart"><i class="fa fa-heartbeat"></i> <span>心跳监控</span></a></li>
+		  {{end}}
+		  <li data="index_errlua"><a href="/center/errorLua"><i class="fa fa-warning"></i> <span>错误爬虫管理</span></a></li>
 <!--    	<li data="index_errdata"><a href="/center/errorData"><i class="glyphicon glyphicon-exclamation-sign"></i> <span>错误信息管理</span></a></li>-->
 <!--		<li data="index_wtgl"><a href="/center/managerQues"><i class="glyphicon glyphicon-question-sign"></i> <span>问题管理</span></a></li>-->
 		{{end}}
+		{{if eq (session "identity") 1}}
 		<li data="index_site"><a href="/center/site/sitelist"><i class="glyphicon glyphicon-home"></i> <span>站点列表</span></a></li>
+		{{end}}
 		<li ><a href="/center/logout" target="_self"><i class="fa fa-sign-out"></i> <span>退出</span></a></li>
 		<li style="color:#fff;padding:35px 20px;" class="hide">
 			<div class="form-group">
@@ -618,7 +624,6 @@
     <!-- /.sidebar -->
   </aside>
 <script>
-	
 	var $site = "";
 	var $channel = "";
 	var $code = "";
@@ -641,7 +646,6 @@
     var href = $("#datahref").val();
 	var stype = {{.T.task.s_type}};
 	var event = {{.T.task.i_event}};
-	console.log(href,stype,event)
     if(href==""){
       return
     }

+ 3 - 1
src/web/templates/index.html

@@ -631,6 +631,7 @@ $(function(){
 			"<select id='platform' onchange='checkclick(this.value)' class='form-control input-sm'>"+
 			"<option value='-1'>全部</option>"+
 			"<option value='golua平台'>golua平台</option>"+
+				"<option value='chrome'>chrome</option>"+
 			"<option value='python'>python</option>"+
 				"<option value='通用爬虫'>通用爬虫</option>"+
 			"</select></div>"
@@ -955,7 +956,8 @@ $(function(){
     function createComboxPlatform(code,id){
     	return "<select onchange='updateesp(this.value,\"platform\",\"\",\""+code+"\",\""+id+"\")' class='form-control input-sm'>"+
     			  "<option value='golua平台'>golua平台</option>"+
-    			  "<option value='python'>python</option>"+
+				"<option value='chrome'>chrome</option>"+
+				"<option value='python'>python</option>"+
     				"<option value='通用爬虫'>通用爬虫</option>"+
           "</select>"
   };

+ 1 - 0
src/web/templates/lualist.html

@@ -248,6 +248,7 @@
                     "<select id='platform' onchange='checkclick(this.value)' class='form-control input-sm'>"+
                     "<option value='-1'>全部</option>"+
                     "<option value='golua平台'>golua平台</option>"+
+                    "<option value='chrome'>chrome</option>"+
                     "<option value='python'>python</option>"+
                     "<option value='通用爬虫'>通用爬虫</option>"+
                     "</select></div>"

+ 1 - 0
src/web/templates/sitelist.html

@@ -553,6 +553,7 @@ $(function(){
             "<select id='platform' onchange='checkclick(this.value,\"platform\")' class='form-control input-sm'>"+
             "<option value='-1'>全部</option>"+
             "<option value='golua平台'>golua平台</option>"+
+            "<option value='chrome'>chrome</option>"+
             "<option value='python'>python</option>"+
             "<option value='golua平台,python'>golua平台,python</option>"+
             "<option value='通用爬虫'>通用爬虫</option>"+

+ 171 - 5
src/web/templates/spiderbase.html

@@ -1,3 +1,20 @@
+<style>
+	.chrome-actions{
+		display: flex;
+		align-items: center;
+		box-sizing: border-box;
+		padding-left: 20px;
+	}
+	.chrome-actions .fa-plus-square{
+		margin-top: 7px;
+		cursor: pointer;
+		color: green;
+	}
+	.chrome-actions .fa-minus-square{
+		margin-top: 7px;
+		color: red;
+	}
+</style>
 <div class="modal fade" id="modal-js">
 	<div class="modal-dialog">
 		<form class="form-horizontal" role="form">
@@ -8,11 +25,11 @@
 					<h4 class="modal-title">JS</h4>
 				</div>
 				<div class="modal-body">
-					<div class="form-group" id="step2_js_pre">
-						<textarea id="step2_js" name="">{{.T.lua.js_list.js_text}}</textarea>
+					<div class="form-group" id="Step2_js_pre">
+						<textarea id="Step2_js" name="">{{.T.lua.js_list.js_text}}</textarea>
 					</div>
-					<div class="form-group" id="step3_js_pre">
-						<textarea id="step3_js" name="">{{.T.lua.js_detail.js_text}}</textarea>
+					<div class="form-group" id="Step3_js_pre">
+						<textarea id="Step3_js" name="">{{.T.lua.js_detail.js_text}}</textarea>
 					</div>
 					<div class="form-group">
 						<label for="js_name" class="col-sm-2 control-label">js文件名:</label>
@@ -76,6 +93,34 @@
 	</div>
 	<!-- /.modal-dialog -->
 </div>
+<div class="modal fade" id="chrome-task">
+	<div class="modal-dialog">
+		<form class="form-horizontal" role="form">
+			<div class="modal-content">
+				<div class="modal-header">
+					<button type="button" class="close" data-dismiss="modal" aria-label="Close">
+						<span aria-hidden="true">&times;</span></button>
+					<h4 class="modal-title">编辑动作</h4>
+				</div>
+				<div class="modal-body">
+					<div class="form-group">
+						<label for="selectList" class="col-sm-2 control-label">动作集:</label>
+						<div class="col-sm-10">
+							<div id="selectList" class="xm-select-demo" style="width: 400px;"></div>
+						</div>
+
+					</div>
+				</div>
+				<div class="modal-footer">
+					<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
+					<button type="button" class="btn btn-primary" onclick="saveActions()">保存</button>
+				</div>
+			</div>
+			<!-- /.modal-content -->
+		</form>
+	</div>
+	<!-- /.modal-dialog -->
+</div>
 <!-- /.modal -->
 <form class="form-horizontal" id="baseinfo">
 	<div class="col-md-4 max-base">
@@ -491,7 +536,128 @@
 	</div>
 </form>
 <script>
-
+	var actionHtmlMap ={
+		"navigate":`
+			<div class="form-group chrome-actions">
+				<label class="control-label col-md-2 ">列表页地址:</label>
+				<i class="fa fa-plus-square" onclick="addChromeAction(this)"></i>&nbsp;
+				<i class="fa fa-minus-square" style="cursor: pointer" onclick="removeChromeAction(this)"></i>
+<!--				<i class="fa fa-times-circle" style="color: red;margin-top: 7px;"></i>-->
+				<div class="col-md-5">
+					<input type="text" class="form-control" placeholder="请输入地址" name="Chrome.navigate" />
+				</div>
+			</div>`,
+		"changeip":`
+			<div class="form-group chrome-actions">
+				<label class="control-label col-md-2">切换IP:</label>
+				<i class="fa fa-plus-square" style="cursor: pointer" onclick="addChromeAction(this)"></i>&nbsp;
+				<i class="fa fa-minus-square" style="cursor: pointer" onclick="removeChromeAction(this)"></i>
+				<div class="col-md-5">
+					<input type="text" disabled class="form-control" name="Chrome.changeip"/>
+				</div>
+			</div>`,
+		"click":`
+			<div class="form-group chrome-actions">
+				<label class="control-label col-md-2">点击:</label>
+				<i class="fa fa-plus-square" style="cursor: pointer" onclick="addChromeAction(this)"></i>&nbsp;
+				<i class="fa fa-minus-square" style="cursor: pointer" onclick="removeChromeAction(this)"></i>
+				<div class="col-md-5">
+					<input type="text" class="form-control" placeholder="请输入selector" name="Chrome.click" />
+				</div>
+				<label class="control-label col-md-2">Selector:</label>
+				<div class="col-md-2">
+					<select sel="Chrome.click.selector">
+						<option>ByQuery</option>
+						<option>ByID</option>
+					</select>
+				</div>
+			</div>`,
+		"waitready":`
+			<div class="form-group chrome-actions">
+				<label class="control-label col-md-2">元素加载完毕:</label>
+				<i class="fa fa-plus-square" style="cursor: pointer" onclick="addChromeAction(this)"></i>&nbsp;
+				<i class="fa fa-minus-square" style="cursor: pointer" onclick="removeChromeAction(this)"></i>
+				<div class="col-md-5">
+					<input type="text" class="form-control" placeholder="请输入selector" name="Chrome.waitready" />
+				</div>
+				<label class="control-label col-md-2">Selector:</label>
+				<div class="col-md-2">
+					<select sel="Chrome.waitready.selector">
+						<option>ByQuery</option>
+						<option>ByID</option>
+					</select>
+				</div>
+			</div>`,
+		"waitvisible":`
+			<div class="form-group chrome-actions">
+				<label class="control-label col-md-2">元素可见:</label>
+				<i class="fa fa-plus-square" style="cursor: pointer" onclick="addChromeAction(this)"></i>&nbsp;
+				<i class="fa fa-minus-square" style="cursor: pointer" onclick="removeChromeAction(this)"></i>
+				<div class="col-md-5">
+					<input type="text" class="form-control" placeholder="请输入selector" name="Chrome.waitvisible" />
+				</div>
+				<label class="control-label col-md-2">Selector:</label>
+				<div class="col-md-2">
+					<select sel="Chrome.waitvisible.selector">
+						<option>ByQuery</option>
+						<option>ByID</option>
+					</select>
+				</div>
+			</div>`,
+		"wait":`
+			<div class="form-group chrome-actions">
+				<label class="control-label col-md-2">等待休息:</label>
+				<i class="fa fa-plus-square" style="cursor: pointer" onclick="addChromeAction(this)"></i>&nbsp;
+				<i class="fa fa-minus-square" style="cursor: pointer" onclick="removeChromeAction(this)"></i>
+				<div class="col-md-5">
+					<input type="text" class="form-control" placeholder="请输入等待时长" name="Chrome.wait" />
+				</div>
+			</div>`,
+		"evaluate":`
+			<div class="form-group chrome-actions">
+				<label class="control-label col-md-2">执行JS:</label>
+				<i class="fa fa-plus-square" style="cursor: pointer" onclick="addChromeAction(this)"></i>&nbsp;
+				<i class="fa fa-minus-square" style="cursor: pointer" onclick="removeChromeAction(this)"></i>
+				<div class="col-md-5">
+					<input type="text" class="form-control" placeholder="请输入JS" name="Chrome.evaluate" />
+				</div>
+			</div>`,
+		"outerhtml":`
+			<div class="form-group chrome-actions">
+				<label class="control-label col-md-2">获取HTML:</label>
+				<i class="fa fa-plus-square" style="cursor: pointer" onclick="addChromeAction(this)"></i>&nbsp;
+				<i class="fa fa-minus-square" style="cursor: pointer" onclick="removeChromeAction(this)"></i>
+				<div class="col-md-5">
+					<input type="text" class="form-control" placeholder="请输入selector" name="Chrome.outerhtml" />
+				</div>
+				<label class="control-label col-md-2">Selector:</label>
+				<div class="col-md-2">
+					<select sel="Chrome.outerhtml.selector">
+						<option>ByQuery</option>
+						<option>ByID</option>
+					</select>
+				</div>
+			</div>`,
+		"listhref":`
+			<div class="form-group chrome-actions">
+				<label class="control-label col-md-2">匹配列表链接:</label>
+				<i class="fa fa-plus-square" style="cursor: pointer" onclick="addChromeAction(this)"></i>&nbsp;
+				<i class="fa fa-minus-square" style="cursor: pointer" onclick="removeChromeAction(this)"></i>
+				<div class="col-md-5">
+					<input type="text" class="form-control" placeholder="请输入获取列表页a链接selector" name="Chrome.listhref" />
+				</div>
+			</div>`,
+		"listhtml":`
+			<div class="form-group chrome-actions">
+				<label class="control-label col-md-2">获取列表HTML:</label>
+				<i class="fa fa-plus-square" style="cursor: pointer" onclick="addChromeAction(this)"></i>&nbsp;
+				<i class="fa fa-minus-square" style="cursor: pointer" onclick="removeChromeAction(this)"></i>
+				<div class="col-md-5">
+					<input type="text" class="form-control" placeholder="请输入获取列表页html与a链接的层级关系" name="Chrome.listhtml" />
+				</div>
+				<h6 style="color: red">(同级:0;父级:1;爷级:2)</h6>
+			</div>`,
+	}
   function spiderTypeChange(){
     var val = $("#spiderType").val();
     if (val == "increment") {//选择增量模式

+ 129 - 47
src/web/templates/spideredit.html

@@ -211,19 +211,20 @@
           <div class="nav-tabs-custom">
             <ul class="nav nav-tabs edit-step">
                 <li class="active"  data-mode="{{if.T.lua.type_time}}{{if eq .T.lua.type_time 0}}guide{{else}}expert{{end}}{{else}}guide{{end}}"><a href="#tab_1" data-toggle="tab" >最后发布时间</a></li>
-                <li data-mode="{{if.T.lua.type_list}}{{if eq .T.lua.type_list 0}}guide{{else}}expert{{end}}{{else}}guide{{end}}"><a href="#tab_2" data-toggle="tab"  >列表页</a></li>
-                <li  data-mode="{{if.T.lua.type_content}}{{if eq .T.lua.type_content 0}}guide{{else}}expert{{end}}{{else}}guide{{end}}"><a href="#tab_3" data-toggle="tab" >三级页</a></li>
+                <li data-mode="{{if.T.lua.type_list}}{{if eq .T.lua.type_list 2}}chrome{{else if eq .T.lua.type_list 1}}expert{{else}}guide{{end}}{{else}}guide{{end}}"><a href="#tab_2" data-toggle="tab"  >列表页</a></li>
+                <li  data-mode="{{if.T.lua.type_content}}{{if eq .T.lua.type_content 2}}chrome{{else if eq .T.lua.type_content 1}}expert{{else}}guide{{end}}{{else}}guide{{end}}"><a href="#tab_3" data-toggle="tab" >三级页</a></li>
                 <li style="display: none" id="copyTabDom"  data-mode="{{if.T.lua.type_content}}{{if eq .T.lua.type_content 0}}guide{{else}}expert{{end}}{{else}}guide{{end}}"><a href="#tab_re3" data-toggle="tab" >复制三级页</a></li>
-				        <li style="padding: 10px 15px;">
-                  <input id="copyTab" type="checkbox"/>
-                  <label for="copyTab">复制三级页</label>
-                </li>
+				    <li data-mode="copy_tab" style="padding: 10px 15px;">
+					  <input id="copyTab" type="checkbox"/>
+					  <label for="copyTab">复制三级页</label>
+					</li>
                 <li class="pull-right">
-					        <div class="btn-group guide">
-                        <button type="button" class="btn btn-default  active" data-mode="guide">向导</button>
-                     	<button type="button" class="btn btn-default" data-mode="expert">专家</button>
+					<div class="btn-group guide">
+						<button type="button" id="modal_chrome" class="btn btn-default" data-mode="chrome">Chrome</button>
+                        <button type="button" id="modal_guide" class="btn btn-default  active" data-mode="guide">向导</button>
+                     	<button type="button" id="modal_expert" class="btn btn-default" data-mode="expert">专家</button>
                  	</div>
-				        </li>
+				</li>
             </ul>
             <div class="tab-content">
             {{include "step1.html"}}
@@ -258,53 +259,59 @@
 </div>
 	
 <script>
+	var actionsHtml = ""
+	var parentNode
+	var luaIsChrome = {{.T.lua.platform}} == "chrome";
 	$(function(){
-		editor2_js = CodeMirror.fromTextArea($("#step2_js")[0], {
+		editor2_js = CodeMirror.fromTextArea($("#Step2_js")[0], {
 			theme:"solarized light",
 			lineNumbers: true,
 			indentUnit:4,
 			smartIndent:true
 		});
 		editor2_js.setSize("auto","300");
-		editor3_js = CodeMirror.fromTextArea($("#step3_js")[0], {
+		editor3_js = CodeMirror.fromTextArea($("#Step3_js")[0], {
 			theme:"solarized light",
 			lineNumbers: true,
 			indentUnit:4,
 			smartIndent:true
 		});
 		editor3_js.setSize("auto","300");
+		//step1隐藏chrome
+		if(!luaIsChrome || $(".edit-step li.active").text() == "最后发布时间"){
+			$("#modal_chrome").hide();
+		}
 
+		if({{.T.lua.iscopycontent}}){
+		  $("#copyTab").prop('checked','checked');
+		  $("#copyTabDom").show()
+		  //$("#copyTabDom").find('a').trigger('click')
+		  //editor_re3.refresh()
+		}
 
-    if({{.T.lua.iscopycontent}}){
-      $("#copyTab").prop('checked','checked');
-      $("#copyTabDom").show()
-      //$("#copyTabDom").find('a').trigger('click')
-      //editor_re3.refresh()
-    }
-
-    $("#copyTab").on('change', function () {
-      var result = $(this).prop('checked')
-      if (result) {
-        $("#copyTabDom").show()
-        $("#copyTabDom").find('a').trigger('click')
-        editor_re3.refresh()
-      } else {
-        $("#copyTabDom").hide()
-        $("#copyTabDom").prev().find('a').trigger('click')
-      }
-    })
+		$("#copyTab").on('change', function () {
+		  var result = $(this).prop('checked')
+		  if (result) {
+			$("#copyTabDom").show()
+			$("#copyTabDom").find('a').trigger('click')
+			editor_re3.refresh()
+		  } else {
+			$("#copyTabDom").hide()
+			$("#copyTabDom").prev().find('a').trigger('click')
+		  }
+		})
 
-    // showTip("注意修改:最大页和间隔时间", 3000);
-    $(document).keydown(function(e){
-        if(e.keyCode==13){
-          $("#com-alert").modal("hide");
-        }
-  });
+		// showTip("注意修改:最大页和间隔时间", 3000);
+		$(document).keydown(function(e){
+			if(e.keyCode==13){
+			  $("#com-alert").modal("hide");
+			}
+	  });
 		//初始化编辑器
 		common.setActive("spider");
 		common.spider.guideActive($(".edit-step li:eq(0)").attr("data-mode"),$(".edit-step li:eq(0)").get(0));
+		//切换step1、step2、step3
 		$(".edit-step li[data-mode]").click(function(node){
-			// console.log(1);
 			common.spider.guideActive($(this).attr("data-mode"),this);
 			switch ($(this).index()+1){
 				case 1:
@@ -328,7 +335,15 @@
 					},50)
 					break;
 			}
+			setTimeout(function(){
+				if(luaIsChrome && $(".edit-step li.active").text() != "最后发布时间"){
+					$("#modal_chrome").show();//step1隐藏chrome模式
+				}else{
+					$("#modal_chrome").hide();
+				}
+			},200)
 		});
+		//切换模式
 		$(".guide button").click(function(){
 			if($(".edit-step li.active").attr("data-mode")!=$(this).attr("data-mode")){
 				$(".edit-step li.active").attr("data-mode",$(this).attr("data-mode"));
@@ -339,7 +354,6 @@
 				editor_4.refresh();
         		editor_re3.refresh();
 			}
-
 		})
 
 		$.getJSON("/province.json",function(json){
@@ -348,7 +362,7 @@
 
 		})
 		$("legend a").click(function(event,editor){
-      		var node = $(this).parent().find("input[type='radio']:checked").val()
+      		var node = $(this).parent().find("input[type='radio']:checked").val()//测试线路
 			var target=$(this).attr("for");
 			var check=function(me){
 				var name=$(me).attr("name")
@@ -364,10 +378,17 @@
 				return
 			}else{
 				common.maskShow();
-				var modal=target.replace("step","#tab_");
+				var modal=target.replace("Step","#tab_");
 				var data=common.form.serializeArray(target);
 				modal=$("a[href='"+modal+"']").parent().attr("data-mode");
-				modal=modal=="guide"?0:1;
+				//modal=modal=="guide"?0:1;
+				if (modal == "chrome"){
+					modal = 2
+				}else if (modal == "expert"){
+					modal = 1
+				}else if (modal == "guide"){
+					modal = 0
+				}
 				data["imodal"]=modal;
 				data["step"]=target;
 				var baseinfo=common.form.serializeArray("baseinfo");
@@ -381,7 +402,7 @@
 				//data中加入选择的节点
 				data["downloadnode"]= node
 				//测试页码
-				if (data["step"] == "step2"){
+				if (data["step"] == "Step2"){
 					data["Base.SpiderStartPage"] = data["pageno"]
 				}
 				// console.log(data)
@@ -518,21 +539,20 @@
   //编辑js
   function editJs(step) {
 	  if (step == "list"){//list
-		  $("#step2_js_pre").removeClass("hide")
-		  $("#step3_js_pre").addClass("hide")
+		  $("#Step2_js_pre").removeClass("hide")
+		  $("#Step3_js_pre").addClass("hide")
 		  $("#js_name").val({{.T.lua.js_list.js_name}});
 		  $("#js_alias").val({{.T.lua.js_list.js_alias}});
 		  // $("#param_type").val({{.T.lua.js_list.js_param}});
 		  // $("#return_type").val({{.T.lua.js_list.js_return}});
 	  }else if (step == "detail"){//detail
-		  $("#step2_js_pre").addClass("hide")
-		  $("#step3_js_pre").removeClass("hide")
+		  $("#Step2_js_pre").addClass("hide")
+		  $("#Step3_js_pre").removeClass("hide")
 		  $("#js_name").val({{.T.lua.js_detail.js_name}});
 		  $("#js_alias").val({{.T.lua.js_detail.js_alias}});
 		  // $("#param_type").val({{.T.lua.js_detail.js_param}});
 		  // $("#return_type").val({{.T.lua.js_detail.js_return}});
 	  }
-	  console.log(step)
 	  $("#savejs").attr("step",step)
 	  common.spider.editjs(step);
   }
@@ -574,6 +594,68 @@
 		  }
 	  })
   }
+  //添加chrome动作
+  function addChromeAction(a){
+	  parentNode = $(a).parent();
+	  //选择动作https://maplemei.gitee.io/xm-select/#/basic/autoRow
+	  xmSelect.get("#selectList").reset;//重置
+	  xmSelect.render({
+		  el: '#selectList',
+		  model: {
+			  icon: 'hidden',
+		  },
+		  toolbar:{
+			  show: true,
+			  showIcon: false,
+		  },
+		  checkbox: true,
+		  repeat: true,
+		  autoRow: true,
+		  filterable: true,
+		  prop: {name: 'name', value: 'value',},
+		  height: '400px',
+		  tips: '请选择',
+		  autoRow:true,
+		  tree: {
+			  show: true,
+			  showFolderIcon: false,
+			  showLine: true,
+			  indent: 20,
+			  expandedKeys: [-3],
+			  strict: false,
+		  },
+		  data: function () {
+			  return [{name:'链接地址(navigate)',value:'navigate'},{name:'切换IP(changeip)',value:'changeip'},{name:'点击(click)',value:'click'},{name:'元素加载完毕(waitready)',value:'waitready'},{name:'元素可见(waitvisible)',value:'waitvisible'},{name:'等待休息(wait)',value:'wait'},{name:'执行JS(evaluate)',value:'evaluate'},{name:'获取HTML(outerhtml)',value:'outerhtml'},{name:'匹配列表链接(listhref)',value:'listhref'},{name:'获取列表HTML(listhtml)',value:'listhtml'}];
+		  },
+		  on: function (data) {
+			  var actions = data.arr;//arr:  当前多选已选中的数据
+			  actionsHtml = "";//重置
+			  for(var i in actions){
+				  var action = actions[i].value;
+				  actionsHtml = actionsHtml +actionHtmlMap[action];
+			  }
+			  // parentNode.after(actionsHtml);
+			  // //change, 此次选择变化的数据,数组
+			  // var change = data.change;
+			  // //isAdd, 此次操作是新增还是删除
+			  // var isAdd = data.isAdd;
+			  // console.log(change,isAdd)
+		  },
+	  });
+	  $("#chrome-task").modal("show");
+  }
+
+	//保存动作
+	function saveActions() {
+		// $("#chrome-base-action-list").append(actionsHtml)
+		parentNode.after(actionsHtml);
+		$("#chrome-task").modal("hide");
+	}
+	//删除动作
+	function removeChromeAction(a) {
+		$(a).parents(".chrome-actions").remove();
+	}
+
 </script>
 {{include "socket.html"}}
 {{include "bottom.html"}}

+ 64 - 43
src/web/templates/spiderview.html

@@ -15,25 +15,26 @@
 	          <div class="nav-tabs-custom">
 	            <ul class="nav nav-tabs edit-step">
 	              <li class="active"  data-mode="{{if.T.lua.type_time}}{{if eq .T.lua.type_time 0}}guide{{else}}expert{{end}}{{else}}guide{{end}}"><a href="#tab_1" data-toggle="tab" >最后发布时间</a></li>
-	              <li data-mode="{{if.T.lua.type_list}}{{if eq .T.lua.type_list 0}}guide{{else}}expert{{end}}{{else}}guide{{end}}"><a href="#tab_2" data-toggle="tab"  >列表页</a></li>
-	              <li  data-mode="{{if.T.lua.type_content}}{{if eq .T.lua.type_content 0}}guide{{else}}expert{{end}}{{else}}guide{{end}}"><a href="#tab_3" data-toggle="tab" >三级页</a></li>
-	              <li style="display: none" id="copyTabDom"  data-mode="{{if.T.lua.type_content}}{{if eq .T.lua.type_content 0}}guide{{else}}expert{{end}}{{else}}guide{{end}}"><a href="#tab_re3" data-toggle="tab" >复制三级页</a></li>
-				        <li style="padding: 10px 15px;">
-                  <input id="copyTab" type="checkbox"/>
-                  <label for="copyTab">复制三级页</label>
-                </li>
-                <li class="pull-right">
-							  <div class="btn-group guide">
-	                      <button type="button" class="btn btn-default  active" data-mode="guide">向导</button>
-	                      <button type="button" class="btn btn-default" data-mode="expert">专家</button>
-                  		</div>
+					<li data-mode="{{if.T.lua.type_list}}{{if eq .T.lua.type_list 2}}chrome{{else if eq .T.lua.type_list 1}}expert{{else}}guide{{end}}{{else}}guide{{end}}"><a href="#tab_2" data-toggle="tab"  >列表页</a></li>
+					<li  data-mode="{{if.T.lua.type_content}}{{if eq .T.lua.type_content 2}}chrome{{else if eq .T.lua.type_content 1}}expert{{else}}guide{{end}}{{else}}guide{{end}}"><a href="#tab_3" data-toggle="tab" >三级页</a></li>
+					<li style="display: none" id="copyTabDom"  data-mode="{{if.T.lua.type_content}}{{if eq .T.lua.type_content 0}}guide{{else}}expert{{end}}{{else}}guide{{end}}"><a href="#tab_re3" data-toggle="tab" >复制三级页</a></li>
+					<li data-mode="copy_tab" style="padding: 10px 15px;">
+						<input id="copyTab" type="checkbox"/>
+						<label for="copyTab">复制三级页</label>
+					</li>
+					<li class="pull-right">
+						  <div class="btn-group guide">
+							  <button type="button" id="modal_chrome" class="btn btn-default" data-mode="chrome">Chrome</button>
+							  <button type="button" id="modal_guide" class="btn btn-default  active" data-mode="guide">向导</button>
+							  <button type="button" id="modal_expert" class="btn btn-default" data-mode="expert">专家</button>
+						</div>
 					</li>
 	            </ul>
 	            <div class="tab-content">
 	            {{include "step1.html"}}
 	            {{include "step2.html"}}
-				      {{include "step3.html"}}
-              {{include "stepre3.html"}}
+				{{include "step3.html"}}
+                {{include "stepre3.html"}}
 	            </div>
 	          </div>
 			 		<div class="callout callout-info lead nav-tabs-top">
@@ -63,14 +64,17 @@
 	
 	<script>
 	$(function(){
-		editor2_js = CodeMirror.fromTextArea($("#step2_js")[0], {
+		var actionsHtml = ""
+		var parentNode
+		var luaIsChrome = {{.T.lua.platform}} == "chrome";
+		editor2_js = CodeMirror.fromTextArea($("#Step2_js")[0], {
 			theme:"solarized light",
 			lineNumbers: true,
 			indentUnit:4,
 			smartIndent:true
 		});
 		editor2_js.setSize("auto","300");
-		editor3_js = CodeMirror.fromTextArea($("#step3_js")[0], {
+		editor3_js = CodeMirror.fromTextArea($("#Step3_js")[0], {
 			theme:"solarized light",
 			lineNumbers: true,
 			indentUnit:4,
@@ -78,24 +82,29 @@
 		});
 		editor3_js.setSize("auto","300");
 
-      if({{.T.lua.iscopycontent}}){
-      $("#copyTab").prop('checked','checked');
-      $("#copyTabDom").show()
-      //$("#copyTabDom").find('a').trigger('click')
-      //editor_re3.refresh()
-    }
+		//step1隐藏chrome
+		if(!luaIsChrome || $(".edit-step li.active").text() == "最后发布时间"){
+			$("#modal_chrome").hide();
+		}
+
+		if({{.T.lua.iscopycontent}}){
+		  $("#copyTab").prop('checked','checked');
+		  $("#copyTabDom").show()
+		  //$("#copyTabDom").find('a').trigger('click')
+		  //editor_re3.refresh()
+		}
     
-    $("#copyTab").on('change', function () {
-      var result = $(this).prop('checked')
-      if (result) {
-        $("#copyTabDom").show()
-        $("#copyTabDom").find('a').trigger('click')
-        editor_re3.refresh()
-      } else {
-        $("#copyTabDom").hide()
-        $("#copyTabDom").prev().find('a').trigger('click')
-      }
-    })
+		$("#copyTab").on('change', function () {
+		  var result = $(this).prop('checked')
+		  if (result) {
+			$("#copyTabDom").show()
+			$("#copyTabDom").find('a').trigger('click')
+			editor_re3.refresh()
+		  } else {
+			$("#copyTabDom").hide()
+			$("#copyTabDom").prev().find('a').trigger('click')
+		  }
+		});
 			//初始化编辑器
 			common.setActive("spider");
 			common.spider.guideActive($(".edit-step li:eq(0)").attr("data-mode"),$(".edit-step li:eq(0)").get(0));
@@ -105,24 +114,31 @@
 					case 1:
 						setTimeout(function(){
 							editor_1.refresh();
-						},500)
+						},50)
 						break;
 					case 2:
 						setTimeout(function(){
 							editor_2.refresh();
-						},500)
+						},50)
 						break;
 					case 3:
 						setTimeout(function(){
 							editor_3.refresh();
-						},500)
+						},50)
 						break;
-          case 4:
+          			case 4:
 					setTimeout(function(){
 						editor_re3.refresh();
 					},50)
 					break;	
 				}
+				setTimeout(function(){
+					if(luaIsChrome && $(".edit-step li.active").text() != "最后发布时间"){
+						$("#modal_chrome").show();//step1隐藏chrome模式
+					}else{
+						$("#modal_chrome").hide();
+					}
+				},200)
 			});
 			$(".guide button").click(function(){
 				if($(".edit-step li.active").attr("data-mode")!=$(this).attr("data-mode")){
@@ -132,9 +148,8 @@
 					editor_2.refresh();
 					editor_3.refresh();
 					editor_4.refresh();
-          editor_re3.refresh();
+          			editor_re3.refresh();
 				}
-				
 			})
 			
 			$.getJSON("/province.json",function(json){
@@ -144,7 +159,7 @@
 			})
 			
 			$("legend a").click(function(event,editor){
-         var node = $(this).parent().find("input[type='radio']:checked").val()
+         			var node = $(this).parent().find("input[type='radio']:checked").val()
 					var target=$(this).attr("for");
 					var check=function(me){
 						var name=$(me).attr("name")
@@ -160,10 +175,16 @@
 						return
 					}else{	
 						common.maskShow();
-						var modal=target.replace("step","#tab_");
+						var modal=target.replace("Step","#tab_");
 						var data=common.form.serializeArray(target);
 						modal=$("a[href='"+modal+"']").parent().attr("data-mode");
-						modal=modal=="guide"?0:1;
+						if (modal == "chrome"){
+							modal = 2
+						}else if (modal == "expert"){
+							modal = 1
+						}else if (modal == "guide"){
+							modal = 0
+						}
 						data["imodal"]=modal;
 						data["step"]=target;
 						var baseinfo=common.form.serializeArray("baseinfo");
@@ -177,7 +198,7 @@
 						//data中加入选择的节点
 						data["downloadnode"]= node
 						//测试页码
-						if (data["step"] == "step2"){
+						if (data["step"] == "Step2"){
 							data["Base.SpiderStartPage"] = data["pageno"]
 						}
 						common.spider.test(data,function(me){

+ 6 - 6
src/web/templates/step1.html

@@ -1,9 +1,9 @@
 <div class="tab-pane active" id="tab_1">
-	<form class="form-horizontal" id="step1">
+	<form class="form-horizontal" id="Step1">
 			<fieldset data-mode="guide">
 				<legend>
           <div style="display: flex;flex-direction: row;align-items: center;">
-            第一步 &nbsp;&nbsp;<a class="btn btn-default btn-sm" for="step1">测&nbsp;&nbsp;试</a>
+            第一步 &nbsp;&nbsp;<a class="btn btn-default btn-sm" for="Step1">测&nbsp;&nbsp;试</a>
             <div style="display: flex;flex-direction: row;align-items: center;">
                 <span style="margin-left: 10px;margin-right: 10px;">线路:</span>
 								<div style="font-size: 16px;">
@@ -51,7 +51,7 @@
 			<fieldset data-mode="expert" class="hide">
 				<legend>
            <div style="display: flex;flex-direction: row;align-items: center;flex-wrap: wrap;">
-           第一步(专家模式)&nbsp;&nbsp;<a class="btn btn-default btn-sm" for="step1">测&nbsp;&nbsp;试</a>
+           第一步(专家模式)&nbsp;&nbsp;<a class="btn btn-default btn-sm" for="Step1">测&nbsp;&nbsp;试</a>
             <div style="display: flex;flex-direction: row;align-items: center;">
                 <span style="margin-left: 10px;margin-right: 10px;">线路:</span>
 								<div style="font-size: 16px;">
@@ -60,15 +60,15 @@
 									<input type="radio" name="jd-1-2" value="bid">线路2</input>
 								</div>
 					  </div>
-            <small style="font-size:14px;text-align:right;width:100%">编辑器热键(F11:全屏/还原 F10:向导模式转专家代码 F9:插入调试代码段 F8:插入下载附件代码段)</small>
+            <small style="font-size:14px;text-align:right;width:100%">热键(F11:全屏/还原 F10:向导模式转专家代码 F9:插入调试代码段 F8:插入下载附件代码段)</small>
           </div>
         
         </legend>
 				
         {{if.T.lua.str_time}}
-				<textarea id="step1_mirror" name="Step1.Expert">{{.T.lua.str_time}}</textarea>
+				<textarea id="Step1_mirror" name="Step1.Expert">{{.T.lua.str_time}}</textarea>
 				{{else}}
-				<textarea id="step1_mirror" name="Step1.Expert">function getLastPublishTime()
+				<textarea id="Step1_mirror" name="Step1.Expert">function getLastPublishTime()
 end</textarea>
 {{end}}
 			</fieldset>

+ 52 - 7
src/web/templates/step2.html

@@ -1,9 +1,55 @@
 <div class="tab-pane" id="tab_2">
-	<form class="form-horizontal" id="step2">
+	<form class="form-horizontal" id="Step2">
+		<fieldset data-mode="chrome">
+			<legend>
+				<div style="display: flex;flex-direction: row;align-items: center;">
+					第二步 &nbsp;&nbsp;<a class="btn btn-default btn-sm" for="Step2">测&nbsp;&nbsp;试</a>
+					<div style="display: flex;flex-direction: row;align-items: center;">
+						<span style="margin-left: 10px;margin-right: 10px;">线路:</span>
+						<div style="font-size: 16px;">
+							<input type="radio" checked name="jd-2-0" value="test">默认</input>
+							<input type="radio" name="jd-2-0" value="comm">线路1</input>
+<!--							<input type="radio" name="jd-2-1" value="bid">线路2</input>-->
+						</div>
+					</div>
+				</div>
+			</legend>
+			<p1>编辑动作集</p1>
+			<div class="form-group chrome-actions" style="display: inline-block">
+					<i class="fa fa-plus-square" onclick="addChromeAction(this)"></i>
+<!--				<label class="control-label col-md-2 ">列表页地址:</label>-->
+<!--				<i class="fa fa-plus-square" onclick="addChromeAction(this)"></i>&nbsp;-->
+<!--				<i class="fa fa-times-circle" style="color: red;margin-top: 7px;"></i>-->
+<!--				<div class="col-md-5">-->
+<!--					<input type="text" class="form-control" placeholder="请输入地址" name="Chrome.navigate" />-->
+<!--				</div>-->
+<!--				<h6 style="color: red">(不可删除)</h6>-->
+			</div>
+			<script>
+				var Step2_Chrome = {{.T.lua.param_list_chrome}};
+				//先铺html
+				var Step2ChromeHtml = "";
+				for (var i in Step2_Chrome){
+					 var action = Step2_Chrome[i].action
+					 Step2ChromeHtml+=actionHtmlMap[action];
+				}
+				$("#Step2 .chrome-actions").after(Step2ChromeHtml);
+				//再赋值
+				for (var i in Step2_Chrome){
+					var action = Step2_Chrome[i].action
+					var param = Step2_Chrome[i].param
+					var selector = Step2_Chrome[i].selector
+					$("#Step2 [name='Chrome."+action+"']").val(param);
+					if (selector != ""){
+						$("#Step2 [sel='Chrome."+action+".selector']").val(selector);
+					}
+				}
+			</script>
+		</fieldset>
 		<fieldset data-mode="guide">
 			<legend>
 				<div style="display: flex;flex-direction: row;align-items: center;">
-					第二步&nbsp;&nbsp;<a class="btn btn-default btn-sm" for="step2">测&nbsp;&nbsp;试</a>
+					第二步 &nbsp;&nbsp;<a class="btn btn-default btn-sm" for="Step2">测&nbsp;&nbsp;试</a>
 					<div style="display: flex;flex-direction: row;align-items: center;">
 						<span style="margin-left: 10px;margin-right: 10px;">线路:</span>
 						<div style="font-size: 16px;">
@@ -20,7 +66,6 @@
 					<input type="text" class="form-control" placeholder="http://www.ccgp.gov.cn/zycg/zycgdt/index#pageno#.htm" name="Step2.Listadd" value="{{if .T.lua.param_list}}{{index .T.lua.param_list 0}}{{end}}" />
 				</div>
 			</div>
-
 			<div class="form-group fixurl ">
 				<label class="control-label col-md-3 ">固定地址:</label>
 				<div class="col-md-6">
@@ -85,7 +130,7 @@
 				<div style="display: flex;flex-direction: row;align-items: center;flex-wrap: wrap;">
 			   第二步(专家模式)&nbsp;&nbsp;
 					<button type="button" class="btn btn-primary" onclick="editJs('list')">js</button>&nbsp;&nbsp;
-					<a class="btn btn-default btn-sm" for="step2">测&nbsp;&nbsp;试</a>
+					<a class="btn btn-default btn-sm" for="Step2">测&nbsp;&nbsp;试</a>
 					<div style="font-size: 16px;">
 						<span style="margin-left: 10px">页码:</span>
 						<select name="pageno">
@@ -109,13 +154,13 @@
 										<input type="radio" name="jd-2-2" value="bid">线路2</input>
 									</div>
 						  </div>
-				<small style="font-size:14px;text-align:right;width:100%">编辑器热键(F11:全屏/还原 F10:向导模式转专家代码 F9:插入调试代码段 F8:插入下载附件代码段)</small>
+				<small style="font-size:14px;text-align:right;width:100%">热键(F11:全屏/还原 F10:向导模式转专家代码 Ctrl+F10:插入Chrome下载代码 F9:插入调试代码段 F8:插入下载附件代码段)</small>
 			  </div>
 			</legend>
 				{{if.T.lua.str_list}}
-				<textarea id="step2_mirror" name="Step2.Expert">{{.T.lua.str_list}}</textarea>
+				<textarea id="Step2_mirror" name="Step2.Expert">{{.T.lua.str_list}}</textarea>
 				{{else}}
-				<textarea id="step2_mirror" name="Step2.Expert">function downloadAndParseListPage(pageno)
+				<textarea id="Step2_mirror" name="Step2.Expert">function downloadAndParseListPage(pageno)
 end</textarea>
 				{{end}}
 				

+ 52 - 7
src/web/templates/step3.html

@@ -1,9 +1,55 @@
 <div class="tab-pane" id="tab_3">
-	<form class="form-horizontal" id="step3">
+	<form class="form-horizontal" id="Step3">
+		<fieldset data-mode="chrome">
+			<legend>
+				<div style="display: flex;flex-direction: row;align-items: center;">
+					第三步 &nbsp;&nbsp;<a class="btn btn-default btn-sm" for="Step3">测&nbsp;&nbsp;试</a>
+					<div style="display: flex;flex-direction: row;align-items: center;">
+						<span style="margin-left: 10px;margin-right: 10px;">线路:</span>
+						<div style="font-size: 16px;">
+							<input type="radio" checked name="jd-3-0" value="test">默认</input>
+							<input type="radio" name="jd-3-0" value="comm">线路1</input>
+<!--							<input type="radio" name="jd-3-1" value="bid">线路2</input>-->
+						</div>
+					</div>
+				</div>
+			</legend>
+			<p1>编辑动作集</p1>
+			<div class="form-group chrome-actions"  style="display: inline-block">
+				<i class="fa fa-plus-square" onclick="addChromeAction(this)"></i>
+<!--				<label class="control-label col-md-2 ">详情页地址:</label>-->
+<!--				<i class="fa fa-plus-square" onclick="addChromeAction(this)"></i>&nbsp;-->
+<!--				<i class="fa fa-times-circle" style="color: red;margin-top: 7px;"></i>-->
+<!--				<div class="col-md-5">-->
+<!--					<input type="text" class="form-control" placeholder="请输入地址" name="Chrome.navigate" />-->
+<!--				</div>-->
+<!--				<h6 style="color: red">(不可删除)</h6>-->
+			</div>
+			<script>
+				var Step3_Chrome = {{.T.lua.param_content_chrome}};
+				//先铺html
+				var Step3ChromeHtml = "";
+				for (var i in Step3_Chrome){
+					var action = Step3_Chrome[i].action
+					Step3ChromeHtml+=actionHtmlMap[action];
+				}
+				$("#Step3 .chrome-actions").after(Step3ChromeHtml);
+				//再赋值
+				for (var i in Step3_Chrome){
+					var action = Step3_Chrome[i].action
+					var param = Step3_Chrome[i].param
+					var selector = Step3_Chrome[i].selector
+					$("#Step3 [name='Chrome."+action+"']").val(param);
+					if (selector != ""){
+						$("#Step3 [sel='Chrome."+action+".selector']").val(selector);
+					}
+				}
+			</script>
+		</fieldset>
 		<fieldset data-mode="guide">
 				<legend>
          <div style="display: flex;flex-direction: row;align-items: center;">
-             第三步 &nbsp;&nbsp;<a class="btn btn-default btn-sm" for="step3">测&nbsp;&nbsp;试</a>
+             第三步 &nbsp;&nbsp;<a class="btn btn-default btn-sm" for="Step3">测&nbsp;&nbsp;试</a>
             <div style="display: flex;flex-direction: row;align-items: center;">
                 <span style="margin-left: 10px;margin-right: 10px;">线路:</span>
 								<div style="font-size: 16px;">
@@ -55,13 +101,12 @@
 		</div>
 		
 		</fieldset>
-		
 		<fieldset data-mode="expert" class="hide">
 			<legend>
           <div style="display: flex;flex-direction: row;align-items: center;flex-wrap: wrap;">
            第三步(专家模式)&nbsp;&nbsp;
 			  <button type="button" class="btn btn-primary" onclick="editJs('detail')">js</button>&nbsp;&nbsp;
-			<a class="btn btn-default btn-sm" for="step3">测&nbsp;&nbsp;试</a>
+			<a class="btn btn-default btn-sm" for="Step3">测&nbsp;&nbsp;试</a>
             <div style="display: flex;flex-direction: row;align-items: center;">
                 <span style="margin-left: 10px;margin-right: 10px;">线路:</span>
 								<div style="font-size: 16px;">
@@ -70,13 +115,13 @@
 									<input type="radio" name="jd-3-2" value="bid">线路2</input>
 								</div>
 					  </div>
-            <small style="font-size:14px;text-align:right;width:100%">编辑器热键(F11:全屏/还原 F10:向导模式转专家代码 F9:插入调试代码段 F8:插入下载附件代码段)</small>
+			  <small style="font-size:14px;text-align:right;width:100%">热键(F11:全屏/还原 F10:向导模式转专家代码 Ctrl+F10:插入Chrome下载代码 F9:插入调试代码段 F8:插入下载附件代码段)</small>
           </div>
       </legend>
 			{{if .T.lua.str_content}}
-				<textarea id="step3_mirror"  name="Step3.Expert">{{.T.lua.str_content}}</textarea>
+				<textarea id="Step3_mirror"  name="Step3.Expert">{{.T.lua.str_content}}</textarea>
 			{{else}}
-			<textarea id="step3_mirror"  name="Step3.Expert">function downloadDetailPage(data)
+			<textarea id="Step3_mirror"  name="Step3.Expert">function downloadDetailPage(data)
     data = com.dataNil(data)
 end</textarea>
 			{{end}}

+ 2 - 2
src/web/templates/stepre3.html

@@ -1,5 +1,5 @@
 <div class="tab-pane" id="tab_re3">
-	<form class="form-horizontal" id="stepre3">
+	<form class="form-horizontal" id="Stepre3">
 		<!--<fieldset data-mode="guide">
 				<legend>
          <div style="display: flex;flex-direction: row;align-items: center;">
@@ -68,7 +68,7 @@
 									<input type="radio" name="jd-3-2" value="bid">线路2</input>
 								</div>
 					  </div>
-            <small style="font-size:14px;text-align:right;width:100%">编辑器热键(F11:全屏/还原 F10:向导模式转专家代码 F9:插入调试代码段 F8:插入下载附件代码段)</small>
+            <small style="font-size:14px;text-align:right;width:100%">热键(F11:全屏/还原 F10:向导模式转专家代码 Ctrl+F10:插入Chrome下载代码 F9:插入调试代码段 F8:插入下载附件代码段)</small>
           </div>
       </legend>-->
 			{{if .T.lua.str_recontent}}