904118851 2 months ago
commit
c38b9a4c5d
81 changed files with 9777 additions and 0 deletions
  1. 3 0
      bin/kill.sh
  2. 1 0
      bin/kill_back.sh
  3. 3 0
      bin/run.sh
  4. 2 0
      bin/run_back.sh
  5. BIN
      common/dbproxy/.DS_Store
  6. 60 0
      common/dbproxy/db_filter_config.lua
  7. 24 0
      common/dbproxy/dbproxy.lua
  8. 66 0
      common/dbproxy/mongodb/mongodb_slave.lua
  9. 101 0
      common/dbproxy/mongodb/mongodbpool.lua
  10. 73 0
      common/dbproxy/mongodbx.lua
  11. 45 0
      common/dbproxy/mongohelper.lua
  12. 45 0
      common/dbproxy/mysqldb/mysqldb_slave.lua
  13. 63 0
      common/dbproxy/mysqldb/mysqldbpool.lua
  14. 27 0
      common/dbproxy/mysqldbx.lua
  15. 16 0
      common/dbproxy/mysqlhelper.lua
  16. 248 0
      common/dbproxy/redisdb/redisbackup.lua
  17. 210 0
      common/dbproxy/redisdb/redisdb_slave.lua
  18. 64 0
      common/dbproxy/redisdb/redisdbpool.lua
  19. 19 0
      common/dbproxy/redisdbx.lua
  20. 9 0
      common/dbproxy/redishelper.lua
  21. 96 0
      common/dbproxy/tg_app.lua
  22. 636 0
      common/dbproxy/tg_main.lua
  23. 151 0
      common/dbproxy/tg_max_zhuanhua.lua
  24. 355 0
      common/dbproxy/tg_platform.lua
  25. 51 0
      common/dbproxy/tg_temp_app.lua
  26. 244 0
      common/dbproxy/tg_zhanghu.lua
  27. 1598 0
      common/preload/functions.lua
  28. 334 0
      common/preload/inspect.lua
  29. 41 0
      common/preload/inspect_api.lua
  30. 56 0
      common/preload/logger_api.lua
  31. 8 0
      etc/config.path
  32. 17 0
      etc/config_node1
  33. 18 0
      etc/prodconfig
  34. 87 0
      lualib/service.lua
  35. 129 0
      lualib/tools.lua
  36. 13 0
      preload.lua
  37. 221 0
      service/agent.lua
  38. 171 0
      service/agent_manager.lua
  39. 45 0
      service/backmgr/ad_convert_type.lua
  40. 58 0
      service/backmgr/aweme_auth_list.lua
  41. 12 0
      service/backmgr/back_response.lua
  42. 93 0
      service/backmgr/book_black_list.lua
  43. 67 0
      service/backmgr/checks.lua
  44. 64 0
      service/backmgr/data_manager.lua
  45. 154 0
      service/backmgr/filter_data.lua
  46. 425 0
      service/backmgr/filter_task.lua
  47. 68 0
      service/backmgr/fq_book.lua
  48. 68 0
      service/backmgr/fq_mf_book.lua
  49. 140 0
      service/backmgr/init.lua
  50. 158 0
      service/backmgr/log.lua
  51. 45 0
      service/backmgr/material_platform.lua
  52. 88 0
      service/backmgr/material_review.lua
  53. 71 0
      service/backmgr/no_filter_origin.lua
  54. 85 0
      service/backmgr/origin_data.lua
  55. 67 0
      service/backmgr/origin_video_titles.lua
  56. 49 0
      service/backmgr/other_book.lua
  57. 63 0
      service/backmgr/platform_shared.lua
  58. 14 0
      service/backmgr/processlist.lua
  59. 97 0
      service/backmgr/promotion_audit_suggestions.lua
  60. 85 0
      service/backmgr/pull_data_config.lua
  61. 17 0
      service/backmgr/pull_data_status.lua
  62. 17 0
      service/backmgr/push_msg.lua
  63. 113 0
      service/backmgr/review_user.lua
  64. 45 0
      service/backmgr/statistics_platform.lua
  65. 132 0
      service/backmgr/task_material_queue_queue.lua
  66. 66 0
      service/backmgr/tg_butler.lua
  67. 87 0
      service/backmgr/tg_main_price_template.lua
  68. 53 0
      service/backmgr/tg_mini_program_platform.lua
  69. 24 0
      service/backmgr/user.lua
  70. 289 0
      service/backmgr/video_applet_product.lua
  71. 331 0
      service/backmgr/video_material.lua
  72. 375 0
      service/backmgr/video_product.lua
  73. 182 0
      service/backmgr/video_product_material.lua
  74. 124 0
      service/backmgr/video_titles.lua
  75. 112 0
      service/backmgr/wechat_miniapp_product.lua
  76. 58 0
      service/backmgr/yw_book.lua
  77. 223 0
      service/doc/cmd_sql.sql
  78. 48 0
      service/http_work/init.lua
  79. 78 0
      service/main.lua
  80. 20 0
      service/tools_work/init.lua
  81. 62 0
      service/userlog.lua

+ 3 - 0
bin/kill.sh

@@ -0,0 +1,3 @@
+lsof -i :9879 | grep LISTEN | awk '{print $2}' | xargs sudo kill -9
+# lsof -i :9902 | grep LISTEN | awk '{print $2}' | xargs sudo kill -9
+# lsof -i :9904 | grep LISTEN | awk '{print $2}' | xargs sudo kill -9

+ 1 - 0
bin/kill_back.sh

@@ -0,0 +1 @@
+kill -9 `cat jl_tg_config_back.pid`

+ 3 - 0
bin/run.sh

@@ -0,0 +1,3 @@
+bash /home/auto_book/bin/kill.sh
+# bash ./start_nginx.sh
+/home/skynet/skynet /home/auto_book/etc/config_node$1

+ 2 - 0
bin/run_back.sh

@@ -0,0 +1,2 @@
+sleep 1
+../../skynet/skynet ../etc/prodconfig 

BIN
common/dbproxy/.DS_Store


+ 60 - 0
common/dbproxy/db_filter_config.lua

@@ -0,0 +1,60 @@
+--主体
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+local shaixuan_config = {}
+--platform_select 1是黑岩 2是番茄 3是全部
+--is_guajian 1 是打开 0 是关闭
+--like_num 点在数大于等于
+--kepp_num 收藏数大于等于
+--shared_num 分享数大于等于
+--comment_num 评论数大于等于
+--material_time 素材时效 天数
+--status 1 是开启 0 是关闭
+--genre 1是长篇 2是短片 3是全部
+--数据库筛选
+function M.modifyConfig(msg_body)
+    local isok ,key =  tools.checkData({"platform_select","is_guajian","like_num","kepp_num",
+    "shared_num","comment_num","material_time","status","genre","source_filter"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local obj = {}
+    local sql = string.format("UPDATE `db_filter_config` SET  config = '%s'  WHERE config_id = 1 ",
+    cjson.encode(msg_body))
+    local res = mysqldbx.query(sql) 
+    shaixuan_config = msg_body
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateFilterConfig"}))
+    return true
+end
+
+function M.getConfig()
+    if #shaixuan_config <=0 then
+        local sql = string.format("select config from `db_filter_config` WHERE config_id = 1 ")
+        local res = mysqldbx.query(sql)
+        local obj = {}
+        if #res>0 and res[1].config~=nil then
+            obj = cjson.decode(res[1].config)
+        else
+            obj = {
+                platform_select = {1,2},
+                is_guajian = 1,
+                like_num = 10,
+                kepp_num = 10,
+                shared_num = 10,
+                comment_num = 10,
+                material_time =2,
+                status = 1,
+                genre = {1,2},
+                source_filter = {"来源1","来源2"}
+            }
+            M.modifyConfig(obj)
+        end
+        shaixuan_config = obj;
+    end
+    return true,shaixuan_config
+end
+
+return M

+ 24 - 0
common/dbproxy/dbproxy.lua

@@ -0,0 +1,24 @@
+local skynet = require "skynet"
+require "skynet.manager"
+local settings = require "run_config"
+
+local skynet_node_name = ...
+
+local CMD = {}
+
+
+local function start()
+    local conf = settings.db_cnf[skynet_node_name]
+    for _, proxy in ipairs(conf.dbproxy) do
+        skynet.uniqueservice(proxy .. "pool", skynet_node_name)
+    end
+end
+
+skynet.start(function()
+    start()
+    skynet.dispatch("lua", function(_, _, cmd, ...)
+        local f = assert(CMD[cmd], cmd .. "not found")
+        skynet.retpack(f(...))
+    end)
+    skynet.register('.' .. SERVICE_NAME)
+end)

+ 66 - 0
common/dbproxy/mongodb/mongodb_slave.lua

@@ -0,0 +1,66 @@
+local skynet = require "skynet"
+require "skynet.manager"
+local cjson = require "cjson"
+local mongodb_tb = require "settings".mongodb_tb
+
+local CMD = {}
+
+local db = {}
+
+
+local function init_db(cnf)
+    local dbc = require "mongodb.mongodb"
+    return dbc:start(cnf)
+end
+
+function CMD.start(cnf)
+    for _, v in pairs(mongodb_tb) do
+        db[v] = init_db({host = cnf.host, port = cnf.port, db_name = v})
+        assert(db[v])
+    end
+end
+
+--cname -> collection name
+
+function CMD.find(dbname, cname, ...)
+    skynet.error("call_mongodb_slave:",dbname,cname,cjson.encode(...))
+    local res =  db[dbname]:find(cname, ...)
+    skynet.error("call_mongodb_slave:",cjson.encode(res))
+    return res
+end
+
+function CMD.findOne(dbname, cname, select)
+    return db[dbname]:findOne(cname, select)
+end
+
+function CMD.aggregate(dbname, cname, operation)
+    return db[dbname]:aggregate(cname, operation)
+end
+
+function CMD.update(dbname, cname, select, datas)
+    return db[dbname]:update(cname, select, datas, true)
+end
+
+function CMD.updateMany(dbname, cname, select, datas)
+    return db[dbname]:updateMany(cname, select, datas)
+end
+
+function CMD.insert(dbname, cname, data)
+    return db[dbname]:insert(cname, data)
+end
+
+function CMD.batch_insert(dbname, cname, data)
+    return db[dbname]:batch_insert(cname, data)
+end
+
+function CMD.del(dbname, cname, select)
+    return db[dbname]:delete(cname, select)
+end
+
+
+skynet.start(function()
+    skynet.dispatch("lua", function(_, _, cmd, ...)
+        local f = assert(CMD[cmd], cmd .. "not found")
+        skynet.retpack(f(...))
+    end)
+end)

+ 101 - 0
common/dbproxy/mongodb/mongodbpool.lua

@@ -0,0 +1,101 @@
+
+local skynet = require "skynet"
+require "skynet.manager"
+local setting_template = require "settings"
+
+local skynet_node_name = ...
+
+local CMD = {}
+local pool = {}
+
+local next_id = 0
+local maxconn = 1
+
+local function next_conn()
+    local id = next_id % maxconn + 1
+    next_id = next_id + 1
+    if id > maxconn then
+        id = 1
+    end
+    return pool[id]
+end
+
+local function getconn(key)
+    if key and (type(key) == "number" or tonumber(key)) then
+       local id = math.floor((tonumber(key) - 1) % maxconn) + 1
+        return pool[id]
+    else
+        return next_conn()
+    end
+end
+
+local function call_mongodb_slave(addr, cmd, ...)
+    return skynet.call(addr, "lua", cmd, ...)
+end
+
+local function send_mongodb_slave(addr, cmd, ...)
+    skynet.send(addr, "lua", cmd, ...)
+end
+
+local function start()
+    local settings = setting_template.db_cnf[skynet_node_name]
+    INFO("mongodbpool 启动", skynet_node_name, inspect(settings))
+    maxconn = tonumber(settings.mongodb_maxinst) or 1
+    for i = 1, maxconn do
+        local mongodb_slave = skynet.newservice("mongodb_slave")
+        skynet.call(mongodb_slave, "lua", "start", settings.mongodb_cnf)
+        table.insert(pool, mongodb_slave)
+    end
+end
+
+function CMD.find(table_name, cname, ...)
+    local executer = getconn()
+    return call_mongodb_slave(executer, "find", table_name, cname, ...)
+end
+
+function CMD.findOne(table_name, cname, conds)
+    local executer = getconn()
+    return call_mongodb_slave(executer, "findOne", table_name, cname, conds)
+end
+
+function CMD.aggregate(dbname, cname, operation)
+    local executer = getconn()
+    return call_mongodb_slave(executer, "aggregate", table_name, cname, operation)
+end
+
+function CMD.upsert(table_name, cname, datas, conds)
+    local executer = getconn()
+    return call_mongodb_slave(executer, "update", table_name, cname, conds, datas)
+end
+
+
+function CMD.updateMany(table_name, cname, datas, conds)
+    local executer = getconn()
+    return call_mongodb_slave(executer, "updateMany", table_name, cname, conds, datas)
+end
+
+function CMD.insert(table_name, cname, datas)
+    local executer = getconn()
+    return call_mongodb_slave(executer, "insert", table_name, cname, datas)
+end
+
+function CMD.batch_insert(table_name, cname, datas)
+    local executer = getconn()
+    return call_mongodb_slave(executer, "batch_insert", table_name, cname, datas)
+end
+
+function CMD.del(table_name, cname, conds)
+    local executer = getconn()
+    return call_mongodb_slave(executer, "del", table_name, cname, conds)
+end
+
+skynet.start(function()
+    start()
+
+    skynet.dispatch("lua", function(_, _, cmd, ...)
+        local f = assert(CMD[cmd], cmd .. " not found")
+        skynet.retpack(f(...))
+    end)
+
+    skynet.register('.' .. SERVICE_NAME)
+end)

+ 73 - 0
common/dbproxy/mongodbx.lua

@@ -0,0 +1,73 @@
+local mongodbx = {}
+
+local skynet = require "skynet"
+
+local MONGODBL_POOL
+
+-- 有些 服务 不允许在 init 阶段处理
+-- 暂时需改成 第一次调用 查询
+-- skynet.init(function ()
+--     MONGODBL_POOL = skynet.queryservice("mongodbpool")
+-- end)
+
+--show dbs;
+-- use ant_account
+--db.dropDatabase()
+-- show collections
+-- db.collection.find() --collection需替换对应具体名字
+--db.collection.find( { qty: { $gt: 4 } } )
+
+local function block_query()
+    -- body
+    if not MONGODBL_POOL then
+        MONGODBL_POOL = skynet.queryservice("mongodbpool")
+    end
+end
+
+function mongodbx.find(table_name, cname, conds)
+    block_query()
+    return skynet.call(MONGODBL_POOL, "lua", "find", table_name, cname, conds)
+end
+
+function mongodbx.findOne(table_name, cname, conds)
+    block_query()
+    return skynet.call(MONGODBL_POOL, "lua", "findOne", table_name, cname, conds)
+end
+
+function mongodbx.aggregate(table_name, cname, operation)
+    block_query()
+    return skynet.call(MONGODBL_POOL, "lua", "aggregate", table_name, cname, operation)
+end
+
+function mongodbx.upsert(table_name, cname, conds, datas)
+    block_query()
+    return skynet.call(MONGODBL_POOL, "lua", "upsert", table_name, cname, conds, datas)
+end
+
+
+function mongodbx.updateMany(table_name, cname, conds, datas)
+    block_query()
+    return skynet.call(MONGODBL_POOL, "lua", "updateMany", table_name, cname, conds, datas)
+end
+
+function mongodbx.insert(table_name, cname, datas)
+    block_query()
+    return skynet.call(MONGODBL_POOL, "lua", "insert", table_name, cname, datas)
+end
+
+function mongodbx.batch_insert(table_name, cname, datas)
+    block_query()
+    return skynet.call(MONGODBL_POOL, "lua", "batch_insert", table_name, cname, datas)
+end
+
+function mongodbx.del(table_name, cname, conds)
+    block_query()
+    return skynet.call(MONGODBL_POOL, "lua", "del", table_name, cname, conds)
+end
+
+function mongodbx.exec(cmd, ...)
+    block_query()
+    return skynet.call(MONGODBL_POOL, "lua", cmd, ...)
+end
+
+return mongodbx

+ 45 - 0
common/dbproxy/mongohelper.lua

@@ -0,0 +1,45 @@
+local M = {}
+
+local mongodbx = require "dbproxy.mongodbx"
+
+function M.find(...)
+    return mongodbx.find(...)
+end
+
+function M.findOne(...)
+    return mongodbx.findOne(...)
+end
+
+function M.aggregate(...)
+    return mongodbx.aggregate(...)
+end
+
+function M.upsert(...)
+    return mongodbx.upsert(...)
+end
+
+function M.updateMany(...)
+    return mongodbx.updateMany(...)
+end
+
+function M.insert(...)
+    return mongodbx.insert(...)
+end
+
+function M.batch_insert(...)
+    return mongodbx.batch_insert(...)
+end
+
+function M.del(...)
+    return mongodbx.del(...)
+end
+
+function M.fetch_all(...)
+    return mongodbx.fetch_all(...)
+end
+
+function M.exec(cmd, ...)
+    return mongodbx.exec(cmd, ...)
+end
+
+return M

+ 45 - 0
common/dbproxy/mysqldb/mysqldb_slave.lua

@@ -0,0 +1,45 @@
+local skynet = require "skynet"
+require "skynet.manager"
+local mysql = require "skynet.db.mysql"
+-- local sql_template = require "sql_template"
+
+local CMD = {}
+local db
+
+
+function CMD.start(conf)
+    local function on_connect(db)
+        db:query("set charset utf8mb4");
+    end
+
+    db = mysql.connect{
+        host=conf.ip,
+        port=conf.port,
+        database=conf.db,
+        user=conf.user,
+        password=conf.password,
+        charset="utf8mb4",
+        max_packet_size = 1024 * 1024,
+        on_connect = on_connect
+    }
+    if not db then
+        error("mysql connect fail")
+    end
+    skynet.fork(function()
+        while true do
+            db:ping()
+            skynet.sleep(300)
+        end
+    end)
+end
+
+function CMD.query(sql)
+    return db:query(sql)
+end
+
+skynet.start(function()
+    skynet.dispatch("lua", function(_, _, cmd, ...)
+        local f = assert(CMD[cmd], cmd .. "not found")
+        skynet.retpack(f(...))
+    end)
+end)

+ 63 - 0
common/dbproxy/mysqldb/mysqldbpool.lua

@@ -0,0 +1,63 @@
+
+local skynet = require "skynet"
+require "skynet.manager"
+local setting_template = require "run_config"
+
+local skynet_node_name = ...
+
+local CMD = {}
+local pool = {}
+
+local next_id = 0
+local maxconn = 1
+
+local function next_conn()
+    local id = next_id % maxconn + 1
+    next_id = next_id + 1
+    if id > maxconn then
+        id = 1
+    end
+    return pool[id]
+end
+
+local function getconn(key)
+    if key and (type(key) == "number" or tonumber(key)) then
+        local id = math.floor((tonumber(key) - 1) % maxconn) + 1
+        return pool[id]
+    else
+        return next_conn()
+    end
+end
+
+local function call_mysqldb_slave(addr, ...)
+    return skynet.call(addr, "lua", "query", ...)
+end
+
+local function start()
+    local settings = setting_template.db_cnf[skynet_node_name]
+    INFO("mysqldbpool 启动", skynet_node_name, inspect(settings))
+    maxconn = tonumber(settings.mysqldb_maxinst) or 1
+    for i = 1, maxconn do
+        local mysqldb_slave = skynet.newservice("mysqldb_slave")
+        skynet.call(mysqldb_slave, "lua", "start", settings.mysqldb_cnf)
+        table.insert(pool, mysqldb_slave)
+    end
+end
+
+
+function CMD.query(sql)
+    local executer = getconn()
+    return call_mysqldb_slave(executer, sql)
+end
+
+
+skynet.start(function()
+    start()
+
+    skynet.dispatch("lua", function(_, _, cmd, ...)
+        local f = assert(CMD[cmd], cmd .. "not found")
+        skynet.retpack(f(...))
+    end)
+
+    skynet.register('.' .. SERVICE_NAME)
+end)

+ 27 - 0
common/dbproxy/mysqldbx.lua

@@ -0,0 +1,27 @@
+local mysqldbx = {}
+
+local skynet = require "skynet"
+
+local MYSQLABL_POOL
+
+-- 有些 服务 不允许在 init 阶段处理
+-- 暂时需改成 第一次调用 查询
+-- skynet.init(function ()
+--     MYSQLABL_POOL = skynet.queryservice("mysqldbpool")
+-- end)
+
+
+local function block_query()
+    -- body
+    if not MYSQLABL_POOL then
+        MYSQLABL_POOL = skynet.queryservice("mysqldbpool")
+    end
+end
+
+function mysqldbx.query(sql)
+    block_query()
+    return skynet.call(MYSQLABL_POOL, "lua", "query", sql)
+end
+
+
+return mysqldbx

+ 16 - 0
common/dbproxy/mysqlhelper.lua

@@ -0,0 +1,16 @@
+local M = {}
+
+local mysqldbx = require "mysqldbx"
+-- local tg_app = require "tg_app"
+
+
+-- function M.loaduser(id)
+--     local sql = string.format("select * from `sg_user` where id = %d", id)
+--     return mysqldbx.query(sql)
+-- end
+
+function M.selectSql(tab_name,key,value)
+    return  string.format("select * from `%s` where %s = %d",tab_name, key,value)
+end
+
+return M

+ 248 - 0
common/dbproxy/redisdb/redisbackup.lua

@@ -0,0 +1,248 @@
+--[[  config
+root = "./"
+
+listen = "127.0.0.1:8786"
+redisaddr = "127.0.0.1:6379[1]"
+dbfile = root .. "backup.db"
+
+thread = 4
+logger = nil
+harbor = 1
+address = "127.0.0.1:8788"
+master = "127.0.0.1:8787"
+start = "redisbackup"
+standalone = "127.0.0.1:8787"
+luaservice = root.."service/?.lua"
+cpath = root.."service/?.so"
+]]
+
+local skynet = require "skynet"
+local socket = require "socket"
+
+local NAME = "redisbackup"
+
+local mode, id , db = ...
+local fd = nil	-- redis socket fd
+
+if mode == nil then
+	local listen_addr = skynet.getenv "listen"
+	local addr, port = string.match(listen_addr, "([^:%s]+)%s*:%s*([^:%s]+)")
+	print(string.format("Listen on %s:%d", addr, port))
+
+	skynet.start(function()
+		local db = skynet.newservice(NAME , "dbserver")
+		local id = socket.listen(addr, port)
+		socket.start(id , function(id, addr)
+			-- you can also call skynet.newservice for this socket id
+			skynet.newservice(NAME, "dispatcher", id, db)
+		end)
+	end)
+
+elseif mode == "dispatcher" then
+	id = tonumber(id)
+	db = tonumber(db)
+
+	local function mainloop()
+		while true do
+			local str = socket.readline(id,"\n")
+			if str then
+				local cmd, key = string.match(str, "(%w+)%s*(.*)")
+				if cmd == "S" or cmd == "L" or cmd == "C" then
+					skynet.send(db, "lua", cmd, key)
+				elseif cmd == "V" then
+					local ret = skynet.call(db, "lua", cmd, key)
+					if ret then
+						socket.write(id, tostring(ret))
+					end
+				else
+					print("Unknown command", cmd, key)
+				end
+			else
+				socket.close(id)
+				skynet.exit()
+				return
+			end
+		end
+	end
+
+	skynet.start(function()
+		socket.start(id)
+		skynet.fork(mainloop)
+	end)
+
+elseif mode == "dbserver" then
+	local unqlite = require "unqlite"
+
+	local dbfile = skynet.getenv "dbfile"
+	local unqlite_db = unqlite.open(dbfile)
+	print("Open db file : ", dbfile)
+	-- mark in _G
+	unqlite_db_gc = setmetatable({} , { __gc = function() unqlite.close(unqlite_db) end })
+
+	local redis_addr = skynet.getenv "redisaddr"
+	local addr, port, db = string.match(redis_addr, "([^:%s]+)%s*:%s*([^:%s%[]+)%s*%[%s*(%d+)%]")
+	port = tonumber(port)
+	db = tostring(db)
+	print(string.format("Redis %s : %d select(%d)", addr, port, db))
+
+----- redis response
+
+	local function readline()
+		return assert(socket.readline(fd, "\r\n"))
+	end
+
+	local function readbytes(bytes)
+		return assert(socket.read(fd, bytes))
+	end
+
+	local function read_response(firstline)
+		local firstchar = string.byte(firstline)
+		local data = string.sub(firstline,2)
+		if firstchar == 42 then -- '*'
+			local n = tonumber(data)
+			if n <= 0 then
+				return n
+			end
+			local bulk = {}
+			for i = 1,n do
+				local line = readline()
+				bulk[i*2-1] = line .. "\r\n"
+				local bytes = tonumber(string.sub(line,2))
+				if bytes >= 0 then
+					local data = readbytes(bytes + 2)
+					-- bulk[i] = nil when bytes < 0
+					bulk[i*2] = data
+				else
+					bulk[i*2] = ""
+				end
+			end
+			return n, table.concat(bulk)
+		end
+		if firstchar == 36 then -- '$'
+			local bytes = tonumber(data)
+			if bytes < 0 then
+				return data
+			end
+			local firstline = skynet.readbytes(fd, bytes+2)
+			return data .. "\r\n" .. firstline
+		end
+		return firstline
+	end
+-----------------------
+
+	local command = {}
+	local dbcmd = { head = 1, tail = 1 }
+
+	local cache = {}
+
+	local function push(v)
+		dbcmd[dbcmd.tail] = v
+		dbcmd.tail = dbcmd.tail + 1
+	end
+
+	local function pop()
+		if dbcmd.head == dbcmd.tail then
+			return
+		end
+		local v = dbcmd[dbcmd.head]
+		dbcmd[dbcmd.head] = nil
+		dbcmd.head = dbcmd.head + 1
+		if dbcmd.head == dbcmd.tail then
+			dbcmd.head = 1
+			dbcmd.tail = 1
+		end
+		return v
+	end
+
+	function command.S(key)
+		local load_command = string.format("*2\r\n$7\r\nHGETALL\r\n$%d\r\n%s\r\n",#key,key)
+		push(load_command)
+		pcall(socket.write,fd,load_command)
+	end
+
+	function command.L(key)
+		local v = unqlite.load(unqlite_db , key)
+		if v then
+			push(v)
+			pcall(socket.write,fd,v)
+		end
+	end
+
+	function command.C()
+		local ok, err = pcall(unqlite.commit,unqlite_db)
+		if not ok then
+			print("Commit error:", err)
+		end
+	end
+
+	function command.D(key)
+		print("delete", key)
+	end
+
+	function command.V(key)
+		local v = unqlite.load(unqlite_db , key)
+		skynet.ret(skynet.pack(v))
+	end
+
+	local dispatcher
+
+	local function connect_redis(addr, port, db)
+		fd = socket.open(addr, port)
+		if fd then
+			socket.write(fd, string.format("*2\r\n$6\r\nSELECT\r\n$%d\r\n%d\r\n",#db,db))
+			local ok = readline()
+			assert(ok == "+OK", string.format("Select %d failed", db))
+			for i = dbcmd.head, dbcmd.tail -1 do
+				socket.write(fd, dbcmd[i])
+			end
+			print("connect ok")
+			skynet.fork(dispatcher)
+			return true
+		end
+	end
+
+	local function dispatch_one()
+		local firstline = readline()
+		if firstline == "+OK" then
+			pop()
+		else
+			local r,data = read_response(firstline)
+			if type(r) == "number" and r > 0 then
+				-- save key
+				local cmd = pop()
+				local key = string.match(cmd,"\r\n([^%s]+)\r\n$")
+				unqlite.save(unqlite_db , key, string.format("*%d\r\n$5\r\nHMSET\r\n$%d\r\n%s\r\n%s", r+2, #key, key, data))
+			else
+				print("error:", r, data)
+				pop()
+			end
+		end
+	end
+
+	-- local function
+	function dispatcher()
+		while true do
+			local ok , err = pcall(dispatch_one)
+			if not ok then
+				-- reconnect
+				print("redis disconnected:" , err)
+				local ok, err = pcall(connect_redis, addr, port, db)
+				if not ok then
+					fd = nil
+					print("Connect redis error: " ..  tostring(err))
+					skynet.sleep(1000)
+				end
+				return
+			end
+		end
+	end
+
+	skynet.start(function()
+		assert(connect_redis(addr,port,db) , "Connect failed")
+		skynet.dispatch("lua", function(session,addr, cmd, ...)
+			command[cmd](...)
+		end)
+	end)
+else
+	error ("Invalid mode " .. mode)
+end

+ 210 - 0
common/dbproxy/redisdb/redisdb_slave.lua

@@ -0,0 +1,210 @@
+local skynet = require "skynet"
+require "skynet.manager"
+local redis = require "skynet.db.redis"
+
+
+local CMD = {}
+local db = nil
+
+
+function CMD.start(cnf)
+    -- DEBUG("redis slave cnf = ", DUMP(cnf))
+    local ok, d = pcall(redis.connect, cnf)
+    if ok then
+        db = d
+        -- db:flushall()
+    else
+        ERROR("---redis connect error---", inspect(cnf) )
+    end
+    skynet.fork(function()
+        while true do
+            local ping = db:ping()
+            -- DEBUG("ping = ", ping)
+            skynet.sleep(1000)
+        end
+    end)
+end
+
+function CMD.set(key, value, type, time)
+    if type ~= nil then
+        return db:set(key, value, type, time)
+    else
+        return db:set(key,value)
+    end
+end
+
+function CMD.expire(key, ex)
+    return db:expire(key, ex)
+end
+
+function CMD.get(key)
+    return db:get(key)
+end
+
+function CMD.hmset(key, t)
+    local data = {}
+    for k, v in pairs(t) do
+        table.insert(data, k)
+        table.insert(data, v)
+    end
+    return db:hmset(key, table.unpack(data))
+end
+
+function CMD.hmget(key, ...)
+    return db:hmget(key, ...)
+end
+
+function CMD.hset(key, filed, value)
+    return db:hset(key,filed,value)
+end
+
+function CMD.hget(key, filed)
+    return db:hget(key, filed)
+end
+
+function CMD.hgetall(key)
+    return db:hgetall(key)
+end
+
+function CMD.zadd(...)
+    return db:zadd(...)
+end
+
+function CMD.keys(key)
+    return db:keys(key)
+end
+
+function CMD.zrange(key, from, to, scores)
+    if not scores then
+        return db:zrange(key, from, to)
+    else
+        return db:zrange(key, from, to, scores)
+    end
+end
+
+function CMD.zincrby(key, score, member)
+    return db:zincrby(key, score, member)
+end
+
+function CMD.zrevrange(key, from, to, scores)
+    if not scores then
+        return db:zrevrange(key,from,to)
+    else
+        return db:zrevrange(key,from,to,scores)
+    end
+end
+
+function CMD.zrangebyscore(key, from, to, scores, limit, offset, count)
+    if not scores then
+        if not limit then
+            return db:zrangebyscore(key,from,to)
+        else
+            return db:zrangebyscore(key,from,to, limit,offset, count)
+        end
+    else
+        if not limit then
+            return db:zrangebyscore(key,from,to,scores)
+        else
+            return db:zrangebyscore(key,from,to,scores,limit, offset, count)
+        end
+    end
+end
+
+function CMD.zrevrangebyscore(key, max, min, scores, limit, offset, count)
+    if not scores then
+        if not limit then
+            return db:zrevrangebyscore(key, max, min)
+        else
+            return db:zrevrangebyscore(key,max, min, limit, offset, count)
+        end
+    else
+        if not limit then
+            return db:zrevrangebyscore(key,max, min,scores)
+        else
+            return db:zrevrangebyscore(key,max, min,scores,limit, offset, count)
+        end
+    end
+end
+
+function CMD.zrank(key, member)
+    return db:zrank(key,member)
+end
+
+function CMD.zrevrank(key, member)
+    return db:zrevrank(key,member)
+end
+
+function CMD.zscore(key, member)
+    return db:zscore(key, member)
+end
+
+function CMD.zcount(key, from, to)
+    return db:zcount(key,from,to)
+end
+
+function CMD.zcard(key)
+    return db:zcard(key)
+end
+
+function CMD.incr(key)
+    return db:incr(key)
+end
+
+function CMD.del(key)
+    return db:del(key)
+end
+
+function CMD.hexists(key )
+    local r = db:hexists(key)
+    return r == 1 and true or false
+end
+
+function CMD.exists(key)
+    return db:exists(key) == 1
+end
+
+function CMD.hdel(... )
+    return db:hdel(...)
+end
+
+function CMD.hincrby(key, field, increment)
+    return tonumber(db:hincrby(key, field, increment))
+end
+
+function CMD.incrby(key, increment)
+    return tonumber(db:incrby(key, increment))
+end
+
+function CMD.setnx(key, value)
+    return db:setnx(key, value) == 1
+end
+
+function CMD.hsetnx(key, field, value)
+    return db:hsetnx(key, field, value) == 1
+end
+
+function CMD.hkeys(key)
+    return db:hkeys(key)
+end
+
+function CMD.getbit(key, offset)
+    return db:getbit(key, offset)
+end
+
+
+function CMD.setbit(key, offset, value)
+    return db:setbit(key, offset, value)
+end
+
+
+function CMD.eval(...)
+    return db:eval(...)
+end
+
+skynet.start(function()
+    skynet.dispatch("lua", function(_, _, cmd, ...)
+        skynet.error("redis slave cmd = ", ...)
+        local f = assert(CMD[cmd], cmd .. " not found")
+        skynet.retpack(f(...))
+    end)
+end)

+ 64 - 0
common/dbproxy/redisdb/redisdbpool.lua

@@ -0,0 +1,64 @@
+local skynet = require "skynet"
+require "skynet.manager"
+local setting_template = require "run_config"
+
+local skynet_node_name = ...
+
+local CMD = {}
+local pool = {}
+
+local next_id = 0
+local maxconn = 1
+
+local function next_conn()
+    local id = next_id % maxconn + 1
+    next_id = next_id + 1
+    if id > maxconn then
+        id = 1
+    end
+    return pool[id]
+end
+
+local function getconn(key)
+    if key and (type(key) == "number" or tonumber(key)) then
+        local id = math.floor((tonumber(key) - 1) % maxconn) + 1
+        return pool[id]
+    else
+        return next_conn()
+    end
+end
+
+local function call_redis_slave(addr, cmd, ...)
+    return skynet.call(addr, "lua", cmd, ...)
+end
+
+local function send_redis_slave(addr, cmd, ...)
+    skynet.send(addr, "lua", cmd, ...)
+end
+
+local function start()
+    local settings = setting_template.db_cnf[skynet_node_name]
+    INFO("redisdbpool 启动", skynet_node_name, inspect(settings))
+    maxconn = tonumber(settings.redisdb_maxinst) or 1
+    for i = 1, maxconn do
+        local redis_slave = skynet.newservice("redisdb_slave")
+        skynet.call(redis_slave, "lua", "start", settings.redisdb_cnf)
+        table.insert(pool, redis_slave)
+    end
+end
+
+function CMD.exec(cmd, uid, ...)
+    local db = getconn(uid)
+    return call_redis_slave(db, cmd, ...)
+end
+
+skynet.start(function()
+    start()
+
+    skynet.dispatch("lua", function(_, _, cmd, ...)
+        local f = assert(CMD[cmd], cmd .. "not found")
+        skynet.retpack(f(...))
+    end)
+
+    skynet.register("." .. SERVICE_NAME)
+end)

+ 19 - 0
common/dbproxy/redisdbx.lua

@@ -0,0 +1,19 @@
+local redisdbx = {}
+
+local skynet = require "skynet"
+
+local REDISABL_POOL
+
+
+local function block_query()
+    if not REDISABL_POOL then
+        REDISABL_POOL = skynet.queryservice("redisdbpool")
+    end
+end
+
+function redisdbx.exec(cmd, uid, ...)
+    block_query()
+    return skynet.call(REDISABL_POOL, "lua", "exec", cmd, uid, ...)
+end
+
+return redisdbx

+ 9 - 0
common/dbproxy/redishelper.lua

@@ -0,0 +1,9 @@
+local M = {}
+
+local redisdbx = require "dbproxy.redisdbx"
+
+
+function M.exec(cmd, uid, ...)
+    return redisdbx.exec(cmd, uid, ...)
+end
+return M

+ 96 - 0
common/dbproxy/tg_app.lua

@@ -0,0 +1,96 @@
+--小程序
+local M = {}
+local skynet = require "skynet"
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local cjson = require "cjson"
+
+--获取所有小程序
+function M.getAppList()
+    local sql = string.format("select * from `tg_app` ")
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res <= 0 then
+        return true ,{}
+    end
+    return true, res
+end
+--所属账户ID advertiser_id
+--资产ID instance_id
+--小程序ID app_id
+--小程序名称 name
+--添加小程序
+function M.addApp(msg_body)
+    local isok ,key =  tools.checkData({"oce_product_advertiser_id","copyright","oce_product_platform_id","system_platform","wx_origin_id","butler_id","tg_platform_id","app_id","instance_id","name","advertiser_id","landing_page","titles"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    msg_body.create_time = current_time
+    local sql = string.format("INSERT INTO `tg_app` (oce_product_advertiser_id,copyright,oce_product_platform_id,system_platform,wx_origin_id,butler_id,tg_platform_id,app_id, instance_id, name,advertiser_id,landing_page,titles)  VALUES (%d,'%s','%s',%d,'%s',%d,%d,'%s','%s','%s','%s','%s','%s')",
+    msg_body.oce_product_advertiser_id,
+    msg_body.copyright,
+    msg_body.oce_product_platform_id,
+    msg_body.system_platform,
+    msg_body.wx_origin_id,
+    msg_body.butler_id,
+    msg_body.tg_platform_id,
+    msg_body.app_id,
+    msg_body.instance_id,msg_body.name,msg_body.advertiser_id,msg_body.landing_page,msg_body.titles)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateAppConfig"}))
+    return true
+end
+
+
+--修改小程序
+function M.modifyApp(msg_body)
+    local isok ,key =  tools.checkData({"oce_product_advertiser_id","copyright","oce_product_platform_id","system_platform","wx_origin_id","butler_id","id","tg_platform_id","app_id","instance_id","name","advertiser_id","landing_page","titles"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    msg_body.update_time = current_time
+    local sql = string.format("UPDATE `tg_app` SET oce_product_advertiser_id = %d , copyright = '%s' , oce_product_platform_id = '%s' ,system_platform = %d , wx_origin_id = '%s' , butler_id = %d , tg_platform_id =%d ,app_id ='%s' , instance_id ='%s' , name ='%s' , advertiser_id ='%s'  , update_time ='%s'   , landing_page ='%s'  , titles ='%s' WHERE id = %d ",
+    msg_body.oce_product_advertiser_id,msg_body.copyright,msg_body.oce_product_platform_id,msg_body.system_platform,msg_body.wx_origin_id,msg_body.butler_id,msg_body.tg_platform_id,msg_body.app_id,msg_body.instance_id,msg_body.name,msg_body.advertiser_id,msg_body.update_time,msg_body.landing_page,msg_body.titles,msg_body.id)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateAppConfig"}))
+    return true
+end
+
+function M.search(msg_body)
+    local isok ,key =  tools.checkData({"system_platform","tg_platform_id","butler_id","page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    
+    local tg_platform_id_param = ""
+    if msg_body.tg_platform_id~="" then
+        tg_platform_id_param = "AND tg_platform_id = "..msg_body.tg_platform_id.." "
+    end
+
+    local butler_id_param = ""
+    if msg_body.butler_id ~= "" then
+        butler_id_param = " AND butler_id = "..msg_body.butler_id.." "
+    end
+
+
+    local system_platform_param = ""
+    if msg_body.system_platform ~= "" then
+        system_platform_param = " AND system_platform = "..msg_body.system_platform.." "
+    end
+
+    local param = tg_platform_id_param..butler_id_param..system_platform_param
+    local sql = "SELECT COUNT(*) AS total FROM tg_app  WHERE 1=1 "..param
+    local total = mysqldbx.query(sql)
+
+    sql = "SELECT * FROM tg_app  WHERE 1=1 "..param..string.format(" ORDER BY id LIMIT %d OFFSET %d ",page_size, offset)
+    local res;
+    res = mysqldbx.query(sql)
+    return true,res,total[1].total
+end
+
+return M

+ 636 - 0
common/dbproxy/tg_main.lua

@@ -0,0 +1,636 @@
+--主体
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+local mysql = require "skynet.db.mysql"
+local config = require "run_config"
+local mysqldtaskbx = {}
+local db
+
+function M.getOpenMainList()
+    local sql = string.format("select * from `tg_main` where running_status = 1 ")
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res <= 0 then
+        return true , {}
+    end
+    return true, res
+end
+
+function M.getCloseMainList()
+    local sql = string.format("select * from `tg_main` where running_status = 0 ")
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res <= 0 then
+        return true , {}
+    end
+    return true, res
+end
+
+
+function M.getOpenCreateLinkMainList()
+    local sql = string.format("select * from `tg_main` where is_open_create_link = 1 ")
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res <= 0 then
+        return true , {}
+    end
+    return true, res
+end
+
+function M.getCloseCreateLinkMainList()
+    local sql = string.format("select * from `tg_main` where is_open_create_link = 0 ")
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res <= 0 then
+        return true , {}
+    end
+    return true, res
+end
+--page_size  是你想要在每页中显示的记录数。
+--page_number 页数
+--获取所有主体
+function M.getMainList()
+    local sql = string.format("select * from `tg_main` ")
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res <= 0 then
+        return true , {}
+    end
+    return true, res
+end
+
+function M.search(msg_body)
+
+    local isok ,key =  tools.checkData({"title_pay_type","is_boost","is_reservation","title_type_id","is_group_record","tf_time_interval","mini_program_platform_id","is_comment","material_rule_id","parent_main_id","id","ads_operation_status","statistics_platform_id","converted_time_duration","cbo_status","project_type","oce_product_id","oce_product_platform_id","delivery_mode","material_platform_id","wx_miniapp_create_status","genre","template_bid","cpa_bid","page_size","page_number","main_name","running_status","custom_budget","pay_type","tg_platform_id","butler_id","tg_app_index","is_open_create_link","is_delete"},msg_body)
+   
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local page_size = msg_body.page_size
+
+    local page_number = msg_body.page_number
+
+    local offset = (page_number - 1) * page_size
+
+    local title_pay_type_param = ""
+    if msg_body.title_pay_type~="" then
+        title_pay_type_param =  " AND title_pay_type = "..msg_body.title_pay_type
+    end
+
+    local is_boost_param = ""
+    if msg_body.is_boost~="" then
+        is_boost_param =  " AND is_boost = "..msg_body.is_boost
+    end
+
+    local is_reservation_param = ""
+    if msg_body.is_reservation~="" then
+        is_reservation_param =  " AND is_reservation = "..msg_body.is_reservation
+    end
+
+    local title_type_id_param = ""
+    if msg_body.title_type_id~="" then
+        title_type_id_param =  " AND title_type_id = "..msg_body.title_type_id
+    end
+
+    local is_group_record_param = ""
+    if msg_body.is_group_record~="" then
+        is_group_record_param =  " AND is_group_record = "..msg_body.is_group_record
+    end
+
+    local tf_time_interval_param = ""
+    if msg_body.tf_time_interval~="" then
+        tf_time_interval_param =  " AND tf_time_interval = "..msg_body.tf_time_interval
+    end
+
+    local mini_program_platform_id_param = ""
+    if msg_body.mini_program_platform_id~="" then
+        mini_program_platform_id_param =  " AND mini_program_platform_id = "..msg_body.mini_program_platform_id
+    end
+
+    local is_comment_param = ""
+    if msg_body.is_comment~="" then
+        is_comment_param =  " AND is_comment = "..msg_body.is_comment
+    end
+
+    local material_rule_id_param = ""
+    if msg_body.material_rule_id~="" then
+        material_rule_id_param =  " AND material_rule_id = "..msg_body.material_rule_id
+    end
+
+    local parent_main_id_param = ""
+    if msg_body.parent_main_id~="" then
+        parent_main_id_param =  " AND parent_main_id = "..msg_body.parent_main_id
+    end
+
+    local id_param = ""
+    if msg_body.id~="" then
+        id_param =  " AND id = "..msg_body.id
+    end
+
+    local ads_operation_status_param = ""
+    if msg_body.ads_operation_status~=""  then
+        ads_operation_status_param = string.format(" AND ads_operation_status =  '%s' ",msg_body.ads_operation_status) 
+    end
+
+    local statistics_platform_id_param = ""
+    if msg_body.statistics_platform_id~=""  then
+        statistics_platform_id_param = string.format(" AND statistics_platform_id =  %d ",msg_body.statistics_platform_id) 
+    end
+
+
+    local converted_time_duration_param = ""
+    if msg_body.converted_time_duration~=""  then
+        converted_time_duration_param = string.format(" AND converted_time_duration = '%s' ",msg_body.converted_time_duration) 
+    end
+
+    local infra_status_param = ""
+    if msg_body.infra_status~=""  then
+        infra_status_param = string.format(" AND infra_status =  %d ",msg_body.infra_status) 
+    end
+
+    local cbo_script_status_param = ""
+    if msg_body.cbo_script_status~=""  then
+        cbo_script_status_param = string.format(" AND cbo_script_status =  %d ",msg_body.cbo_script_status) 
+    end
+
+    local cbo_status_param = ""
+    if msg_body.cbo_status~=""  then
+        cbo_status_param = string.format(" AND cbo_status =  %d ",msg_body.cbo_status) 
+    end
+
+    local project_type_param = ""
+    if msg_body.project_type~=""  then
+        project_type_param = string.format(" AND project_type =  %d ",msg_body.project_type) 
+    end
+
+    local oce_product_id_param = ""
+    if msg_body.oce_product_id~="" and msg_body.oce_product_id~=nil then
+        oce_product_id_param = string.format(" AND oce_product_id =  '%s' ",msg_body.oce_product_id) 
+    end
+
+    local oce_product_platform_id_param = ""
+    if msg_body.oce_product_platform_id~="" and msg_body.oce_oce_product_platform_idproduct_id~=nil then
+        oce_product_platform_id_param = string.format(" AND oce_product_platform_id =  '%s' ",msg_body.oce_product_platform_id) 
+    end
+    
+    local delivery_mode_param = ""
+    if msg_body.delivery_mode~="" and msg_body.delivery_mode~=nil then
+        delivery_mode_param = string.format(" AND delivery_mode =  '%s' ",msg_body.delivery_mode) 
+    end
+
+    local main_name_param = ""
+    if msg_body.main_name~="" then
+        main_name_param = string.format(" AND  ( main_name LIKE CONCAT( '%%%s%%')) ",msg_body.main_name)
+    end
+
+    local wx_miniapp_create_status_param = ""
+    if msg_body.wx_miniapp_create_status~="" then
+        wx_miniapp_create_status_param = string.format(" AND wx_miniapp_create_status = %d ",msg_body.wx_miniapp_create_status) 
+    end
+
+    local tg_platform_param = ""
+    if msg_body.tg_platform_id~="" then
+        tg_platform_param = string.format(" AND tg_platform_id = %d ",msg_body.tg_platform_id) 
+    end
+
+    local material_platform_id_param = ""
+    if msg_body.material_platform_id~="" then
+        material_platform_id_param = string.format(" AND material_platform_id = %d ",msg_body.material_platform_id) 
+    end
+
+    local running_status_param = ""
+    if msg_body.running_status~="" then
+        running_status_param = string.format(" AND running_status = %d ",msg_body.running_status) 
+    end
+
+    local pay_type_param = ""
+    if msg_body.pay_type~="" then
+        pay_type_param = string.format(" AND pay_type = %d ",msg_body.pay_type) 
+    end
+
+    local butler_id_param = ""
+    if msg_body.butler_id~="" then
+        butler_id_param = string.format(" AND butler_id = %d ",msg_body.butler_id) 
+    end
+
+    local tg_app_index_param = ""
+    if msg_body.tg_app_index~="" then
+        tg_app_index_param = string.format(" AND tg_app_index = %d ",msg_body.tg_app_index) 
+    end
+
+    local is_open_create_link_param = ""
+    if msg_body.is_open_create_link~="" then
+        is_open_create_link_param = string.format(" AND is_open_create_link = %d ",msg_body.is_open_create_link) 
+    end
+
+
+    local is_delete_param = ""
+    if msg_body.is_delete~="" then
+        is_delete_param = string.format(" AND is_delete = %d ",msg_body.is_delete) 
+    end
+
+    local custom_budget_param = ""
+    if msg_body.custom_budget~="" then
+        custom_budget_param = string.format(" AND custom_budget LIKE '%%%d%%' ", msg_body.custom_budget)
+    end
+
+    local cpa_bid_param = ""
+    if msg_body.cpa_bid~="" then
+        cpa_bid_param = string.format(" AND cpa_bid LIKE '%%%d%%' ", msg_body.cpa_bid)
+    end
+
+    local template_bid_param = ""
+    if msg_body.template_bid~="" then
+        template_bid_param = string.format(" AND template_bid LIKE '%%%d%%' ", msg_body.template_bid)
+    end
+
+    local genre_param = ""
+    if msg_body.genre~="" then
+        genre_param =  string.format(" AND genre = %d ",msg_body.genre) 
+    end
+
+    local param =  title_pay_type_param..is_boost_param..is_reservation_param..title_type_id_param..is_group_record_param..tf_time_interval_param..mini_program_platform_id_param..is_comment_param..material_rule_id_param..parent_main_id_param..id_param..ads_operation_status_param..statistics_platform_id_param..converted_time_duration_param..infra_status_param..cbo_script_status_param..cbo_status_param..project_type_param..oce_product_platform_id_param..oce_product_id_param..delivery_mode_param..main_name_param..tg_platform_param..running_status_param..pay_type_param..butler_id_param..tg_app_index_param..is_open_create_link_param..is_delete_param..custom_budget_param..cpa_bid_param..template_bid_param..genre_param..wx_miniapp_create_status_param..material_platform_id_param;
+
+    local sql = "SELECT * FROM tg_main where 1=1 "..param..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local res = mysqldbx.query(sql)
+
+    sql =  "SELECT  COUNT(*) AS total  FROM tg_main where 1=1 "..param
+
+    local total = mysqldbx.query(sql)
+
+    return true,res,total[1].total
+
+end
+-- `main_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '主体名称',
+-- `app_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '小程序ID',
+-- `running_status` tinyint(1) DEFAULT '1' COMMENT '运行状态 0-停止 1-运行中',
+-- `ad_quantity` int NOT NULL DEFAULT '40' COMMENT '广告数量',
+-- `cpa_bid` bigint NOT NULL DEFAULT '1750' COMMENT 'CPA出价(分), 默认17.5元',
+-- `bid_type` tinyint(1) DEFAULT '1' COMMENT '出价方式 0-常规 1-最大化 2 两种存储',
+-- `bid_ratio` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '1' COMMENT '出价方式比例(如 1:2)',
+-- `budget` bigint NOT NULL DEFAULT '9000000' COMMENT '预算金额(分), 默认9万元',
+-- `tg_platform_id` int NOT NULL DEFAULT '0' COMMENT '平台',
+-- `daily_new_limit` int DEFAULT '0' COMMENT '今天新上数量上限',
+
+function M.addMain(msg_body)
+    local isok ,key =  tools.checkData({"title_pay_type","is_boost","is_reservation","title_type_id","is_group_record","tf_time_interval","mat_roi","reduce_roi","boost_high_price_end_time","boost_high_price_number","reduce_consume_amount","reduce_bid_amount","is_comment","member_token","zy_conifg","convert_cnt","material_rule_id","material_rule_number","parent_main_id","tg_day","valid_timer_like_num" ,"ads_operation_status","statistics_platform_id","hide_if_converted","converted_time_duration","cbo_script_time","cbo_script_status","cbo_status","project_type","tf_status","tf_start_time","min_book_word","max_book_word","stat_cost","hy_accountId","oce_product_id","oce_product_platform_id","material_platform_id","delivery_mode","advertiser_id","wx_miniapp_create_status","genre","ad_act","template_bid","zh_id","roi_goal","ql_bid","infra_status","pay_type","qm_id","ldy_template_site_id","yw_id","parent_platform_id","platform_shared_id","distributor_id","is_delete","ad_convert_type","aweme_id","tg_app_index","butler_id","mini_program_platform_id","landing_page","valid_timer_time","valid_timer_number","channelId","no_bid_budget","max_ad_quantity","tg_link_config","tg_platform_id","app_id","main_name","running_status","ad_quantity","cpa_bid","bid_type","bid_ratio","custom_budget","daily_new_limit","valid_time","group_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    msg_body.create_time = current_time
+    local sql = string.format("INSERT INTO `tg_main` (title_pay_type,is_boost,is_reservation,title_type_id,is_group_record,tf_time_interval,mat_roi,reduce_roi,boost_high_price_end_time,boost_high_price_number,reduce_consume_amount,reduce_bid_amount,is_comment,member_token,zy_conifg,convert_cnt,material_rule_id,material_rule_number,parent_main_id,tg_day,valid_timer_like_num,ads_operation_status,statistics_platform_id,hide_if_converted,converted_time_duration,cbo_script_time,cbo_script_status,cbo_status,project_type,tf_status,tf_start_time,min_book_word,max_book_word,stat_cost,hy_accountId,oce_product_id,oce_product_platform_id,material_platform_id,delivery_mode,advertiser_id,wx_miniapp_create_status,genre,ad_act,template_bid,zh_id,roi_goal,ql_bid,infra_status,pay_type,qm_id,ldy_template_site_id,yw_id,parent_platform_id,platform_shared_id,distributor_id,is_delete,ad_convert_type,aweme_id,tg_app_index,butler_id,mini_program_platform_id,landing_page,valid_timer_time,valid_timer_number,channelId,no_bid_budget,max_ad_quantity,tg_link_config,tg_platform_id,app_id,main_name,running_status,ad_quantity,cpa_bid,bid_type,bid_ratio,custom_budget,daily_new_limit,valid_time,group_id)  VALUES (%d, %d, %d,%d,  %d,%d,%f,%f,%d,%d,%f,%f,%d,'%s','%s',%d,%d,%d, %d,%d,%d,'%s',%d,'%s','%s','%s',%d,%d,%d,%d,'%s',%d,%d,%d,'%s','%s','%s',%d,'%s','%s',%d,%d,%d,%d,'%s',%d,%d,%d,%d,'%s','%s','%s',%d,%d,'%s',%d,'%s','%s', %d, %d, %d,'%s', %d, '%s', '%s',%d, %d, '%s', %d, '%s', '%s', %d, %d, %d,%d, '%s', %d, %d, '%s', '%s')",
+    msg_body.title_pay_type,
+    msg_body.is_boost,
+    msg_body.is_reservation,
+    msg_body.title_type_id,
+    msg_body.is_group_record,
+    msg_body.tf_time_interval,
+    msg_body.mat_roi,
+    msg_body.reduce_roi,
+    msg_body.boost_high_price_end_time,
+    msg_body.boost_high_price_number,
+    msg_body.reduce_consume_amount,
+    msg_body.reduce_bid_amount,
+    msg_body.is_comment,
+    msg_body.member_token,
+    cjson.encode(msg_body.zy_conifg),
+    msg_body.convert_cnt,
+    msg_body.material_rule_id,
+    msg_body.material_rule_number,
+    msg_body.parent_main_id,
+    msg_body.tg_day,
+    msg_body.valid_timer_like_num,
+    msg_body.ads_operation_status,
+    msg_body.statistics_platform_id,
+    msg_body.hide_if_converted,
+    msg_body.converted_time_duration,
+    msg_body.cbo_script_time,
+    msg_body.cbo_script_status,
+    msg_body.cbo_status,
+    msg_body.project_type,
+    msg_body.tf_status,
+    msg_body.tf_start_time,
+    msg_body.min_book_word,
+    msg_body.max_book_word,
+    msg_body.stat_cost,
+    msg_body.hy_accountId,
+    msg_body.oce_product_id,
+    msg_body.oce_product_platform_id,
+    msg_body.material_platform_id,
+    msg_body.delivery_mode,
+    msg_body.advertiser_id,
+    msg_body.wx_miniapp_create_status,
+    msg_body.genre,
+    msg_body.ad_act,
+    msg_body.template_bid,
+    msg_body.zh_id,
+    msg_body.roi_goal,
+    msg_body.ql_bid,
+    msg_body.infra_status,
+    msg_body.pay_type,
+    msg_body.qm_id,
+    msg_body.ldy_template_site_id,
+    msg_body.yw_id,
+    msg_body.parent_platform_id,
+    msg_body.platform_shared_id,
+    msg_body.distributor_id,
+    msg_body.is_delete,
+    msg_body.ad_convert_type,
+    msg_body.aweme_id,
+    msg_body.tg_app_index,
+    msg_body.butler_id,
+    msg_body.mini_program_platform_id,
+    msg_body.landing_page,
+    msg_body.valid_timer_time,
+    msg_body.valid_timer_number,
+    msg_body.channelId,
+    msg_body.no_bid_budget,
+    msg_body.max_ad_quantity,
+    cjson.encode(msg_body.tg_link_config),
+    msg_body.tg_platform_id,
+    msg_body.app_id,
+    msg_body.main_name,
+    msg_body.running_status,
+    msg_body.ad_quantity,
+    msg_body.cpa_bid,
+    msg_body.bid_type,
+    msg_body.bid_ratio,
+    msg_body.custom_budget,
+    msg_body.daily_new_limit,
+    msg_body.valid_time,
+    msg_body.group_id)
+    skynet.error(sql)
+    local res = mysqldbx.query(sql)
+    if msg_body.parent_main_id ~= 0 then
+        M.updateParentMain(msg_body.parent_main_id)
+    end
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateMainConfig"}))
+    -- pushAddMainMsg(msg_body)
+    return true
+end
+--此主体将书库的书都发布到小程序书籍
+function M.syncMain(msg_body)
+    local isok ,key =  tools.checkData({"id","min_stat_cost","max_stat_cost"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("select * from `tg_main` where id = %d LIMIT 1 ",msg_body.id)
+    local res = mysqldbx.query(sql)
+    res[1].min_stat_cost = msg_body.min_stat_cost
+    res[1].max_stat_cost = msg_body.max_stat_cost
+    res[1].start_publish_time = ""
+    res[1].end_publish_time = ""
+    if msg_body.start_publish_time~="" and msg_body.start_publish_time~=nil then
+        res[1].start_publish_time = msg_body.start_publish_time
+    end
+    if msg_body.end_publish_time~="" and msg_body.end_publish_time~=nil then
+        res[1].end_publish_time = msg_body.end_publish_time
+    end
+
+    syncMainAppletProduct(res[1])
+    return true,{}
+end
+
+function syncMainAppletProduct(main_info)
+    -- local tg_platform_id = main_info.tg_platform_id
+    -- local app_id = main_info.app_id
+    -- local sql = string.format("SELECT * FROM video_product where book_platform = %d ",tg_platform_id)
+    -- local video_product_list = mysqldtaskbx.Singleton().query(sql)
+
+
+    -- function isHaveAppletProdut(product_id)
+    --     local s = string.format("SELECT * FROM video_applet_product where dy_small_applet_app_id = '%s' and product_id = '%s' and main_id = %d and book_platform = %d LIMIT 1",app_id,product_id,main_info.id,tg_platform_id)
+    --     local r = mysqldtaskbx.Singleton().query(sql)
+    --     return #r>0
+    -- end
+
+    -- local need_create_link_list = {}
+    -- local verify_list = {}
+    -- for i = 1, #video_product_list, 1 do
+    --     local product = video_product_list[i]
+    --     if not isHaveAppletProdut(product.product_id) and not verify_list[product.product_id] then
+    --         verify_list[product.product_id] = true
+    --         table.insert(need_create_link_list,#need_create_link_list+1,{product_name=product.product_name,product_id=product.product_id,book_platform=product.book_platform})
+    --     end
+    -- end
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="syncMain",data={main_info=main_info}}))
+end
+
+function pushAddMainMsg(msg_body)
+    local sql = string.format("select * from `tg_main` where main_name = '%s' and app_id = '%s'  LIMIT 1 ",msg_body.main_name,msg_body.app_id)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    skynet.error("sql:",sql)
+    tools.dump(res)
+    if #res > 0 then
+        local main_info =  res[1]
+        skynet.fork(function ()
+        
+            -- local getMainInfoByAppid = function(app_id)
+            --     local temp_list = {}
+            --     for i = 1, #main_list, 1 do
+            --         local main_item = main_list[i]
+            --         if (main_item.app_id==app_id) then
+            --             table.insert(temp_list,#temp_list+1,main_item)
+            --         end
+            --     end
+            --     return temp_list
+            -- end
+            --获取书籍小程序列表
+            sql = string.format("SELECT * FROM video_applet_product ")
+    
+            res = mysqldtaskbx.Singleton().query(sql)
+    
+            local video_applet_product_list = {}
+    
+            if #res>0 then
+                for i = 1, #res, 1 do
+                    table.insert(video_applet_product_list,i,res[i])
+                end
+            end
+    
+            local need_create_link_list = {}
+    
+            -- local isCreateLinkByMainIdAndProductId = function(main_id,product_id)
+            --     local isCreate = false
+            --     for i = 1, #video_applet_product_list, 1 do
+            --         local item = video_applet_product_list[i]
+            --         if (item.product_id==product_id and item.main_id == main_id) then
+            --             isCreate = true
+            --             break
+            --         end
+            --     end
+            --     return isCreate
+            -- end
+            --根据小程序id 筛选出所有需要创建的书籍
+            local video_applet_product_of_main_list = {}
+            local verify_list = {}
+            for i = 1, #video_applet_product_list, 1 do
+                local applet_item = video_applet_product_list[i]
+                if verify_list[applet_item.product_id]==nil then
+                    if applet_item.status == 1 and applet_item.dy_small_applet_app_id == main_info.app_id then
+                        verify_list[applet_item.product_id] = true
+                        table.insert(video_applet_product_of_main_list,#video_applet_product_of_main_list+1,{product_name=applet_item.product_name,product_id=applet_item.product_id,book_platform=applet_item.book_platform,dy_small_applet_app_id=applet_item.dy_small_applet_app_id})
+                    end
+                end
+            end
+            skynet.error("找到所有小程序!",#video_applet_product_of_main_list)
+            skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="addMain",data={list=video_applet_product_of_main_list,main_info=main_info}}))
+        end)
+    end
+   
+end
+function M.modifyMain(msg_body)
+    local isok ,key =  tools.checkData({"title_pay_type","is_boost","is_reservation","title_type_id","is_group_record","tf_time_interval","mat_roi","reduce_roi","boost_high_price_end_time","boost_high_price_number","reduce_consume_amount","reduce_bid_amount","is_comment","member_token","zy_conifg","convert_cnt","material_rule_id","material_rule_number","tg_day","valid_timer_like_num","ads_operation_status","statistics_platform_id","hide_if_converted","converted_time_duration","cbo_script_time","cbo_script_status","cbo_status","project_type","tf_status","tf_start_time","min_book_word","max_book_word","stat_cost","hy_accountId","oce_product_id","oce_product_platform_id","material_platform_id","delivery_mode","advertiser_id","wx_miniapp_create_status","genre","ad_act","template_bid","zh_id","roi_goal","ql_bid","infra_status","pay_type","pay_type","qm_id","ldy_template_site_id","yw_id","parent_platform_id","platform_shared_id","distributor_id","is_delete","ad_convert_type","aweme_id","tg_app_index","butler_id","mini_program_platform_id","landing_page","valid_timer_time","valid_timer_number","channelId","no_bid_budget","max_ad_quantity","tg_link_config","id","tg_platform_id","app_id","main_name","running_status","ad_quantity","cpa_bid","bid_type","bid_ratio","custom_budget","daily_new_limit","valid_time","group_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    msg_body.update_time = current_time
+    local sql = string.format("UPDATE  `tg_main` SET title_pay_type = %d , is_boost = %d , is_reservation = %d , title_type_id = %d , is_group_record = %d , tf_time_interval = %d , mat_roi = %f , reduce_roi = %f , boost_high_price_end_time = %d , boost_high_price_number = %d , reduce_consume_amount = %f , reduce_bid_amount = %f , is_comment = %d , member_token = '%s' , zy_conifg = '%s' , convert_cnt = %d , material_rule_id = %d , material_rule_number = %d , tg_day = %d ,  valid_timer_like_num = %d , ads_operation_status = '%s' , statistics_platform_id = %d , hide_if_converted = '%s' ,converted_time_duration = '%s' ,cbo_script_time = '%s' , cbo_script_status = %d , cbo_status = %d ,  project_type = %d ,tf_status = %d , tf_start_time = '%s' , min_book_word = %d ,  max_book_word = %d , stat_cost = %d , hy_accountId = '%s' , oce_product_id = '%s' , oce_product_platform_id = '%s' , material_platform_id = %d , delivery_mode = '%s' , advertiser_id = '%s' ,wx_miniapp_create_status = %d , genre = %d , ad_act = %d ,template_bid = %d , zh_id = '%s', roi_goal = %d , ql_bid = %d, infra_status = %d , pay_type = %d ,qm_id = '%s' , ldy_template_site_id = '%s' , yw_id = '%s' , parent_platform_id = %d , platform_shared_id = %d ,distributor_id = '%s' , is_delete = %d , ad_convert_type = '%s', aweme_id = '%s' ,tg_app_index = %d , butler_id = %d , mini_program_platform_id = %d , landing_page = '%s' , valid_timer_time = %d , valid_timer_number = %d ,channelId = '%s' , no_bid_budget = %d , max_ad_quantity = %d ,tg_platform_id = %d , app_id = '%s' ,main_name = '%s' , update_time = '%s' , running_status = %d ,ad_quantity = %d ,cpa_bid = %d ,bid_type = %d ,bid_ratio = '%s' ,custom_budget = %d ,daily_new_limit = %d ,valid_time = %d ,tg_link_config = '%s' ,group_id = '%s' WHERE id = %d ",
+    msg_body.title_pay_type,msg_body.is_boost,msg_body.is_reservation,msg_body.title_type_id,msg_body.is_group_record,msg_body.tf_time_interval,msg_body.mat_roi,msg_body.reduce_roi,msg_body.boost_high_price_end_time,msg_body.boost_high_price_number,msg_body.reduce_consume_amount,msg_body.reduce_bid_amount,msg_body.is_comment,msg_body.member_token,cjson.encode(msg_body.zy_conifg),msg_body.convert_cnt,msg_body.material_rule_id,msg_body.material_rule_number,msg_body.tg_day,msg_body.valid_timer_like_num,msg_body.ads_operation_status,msg_body.statistics_platform_id,msg_body.hide_if_converted,msg_body.converted_time_duration,msg_body.cbo_script_time,msg_body.cbo_script_status,msg_body.cbo_status,msg_body.project_type,msg_body.tf_status,msg_body.tf_start_time,msg_body.min_book_word,msg_body.max_book_word,msg_body.stat_cost,msg_body.hy_accountId,msg_body.oce_product_id,msg_body.oce_product_platform_id,msg_body.material_platform_id,msg_body.delivery_mode,msg_body.advertiser_id,msg_body.wx_miniapp_create_status,msg_body.genre,msg_body.ad_act,msg_body.template_bid,msg_body.zh_id,msg_body.roi_goal,msg_body.ql_bid,msg_body.infra_status,msg_body.pay_type,msg_body.qm_id,msg_body.ldy_template_site_id,msg_body.yw_id,msg_body.parent_platform_id,msg_body.platform_shared_id,msg_body.distributor_id,msg_body.is_delete,msg_body.ad_convert_type,msg_body.aweme_id,msg_body.tg_app_index,msg_body.butler_id,msg_body.mini_program_platform_id,msg_body.landing_page,tonumber(msg_body.valid_timer_time),tonumber(msg_body.valid_timer_number),msg_body.channelId,msg_body.no_bid_budget,msg_body.max_ad_quantity,msg_body.tg_platform_id,msg_body.app_id,msg_body.main_name,msg_body.update_time,msg_body.running_status,msg_body.ad_quantity,msg_body.cpa_bid,msg_body.bid_type,msg_body.bid_ratio,msg_body.custom_budget,
+    tonumber(msg_body.daily_new_limit),tonumber(msg_body.valid_time),cjson.encode(msg_body.tg_link_config),msg_body.group_id,msg_body.id)
+    tools.dump(mysqldbx.query(sql))
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateMainConfig"}))
+    return true
+end
+
+--配置主体推广链接
+function M.tgLinkConfig(msg_body)
+    local isok ,key =  tools.checkData({"id","is_open","huichuan_id","chongzhi_id","kadian_id","f_chongzhi_id","site_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("select tg_link_config from `tg_main` WHERE id = %d ",msg_body.id)
+    local res = mysqldbx.query(sql)
+    sql = string.format("UPDATE `tg_main` SET  tg_link_config = '%s'  WHERE id = %d ",
+    cjson.encode(msg_body),msg_body.id)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+--设置创建链接状态
+function M.set_open_create_link_status(msg_body)
+    local isok ,key =  tools.checkData({"id","is_open_create_link"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE `tg_main` SET  is_open_create_link = %d  WHERE id = %d ",
+    msg_body.is_open_create_link,msg_body.id)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+--获取主体下的运行总数
+function M.get_main_ad_run_number(msg_body)
+    local isok ,key =  tools.checkData({"main_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql ="SELECT * FROM advertiser WHERE main_id = " .. msg_body.main_id;
+    local res = mysqldbx.query(sql)
+    local all_run_number = 0
+    for i = 1, #res, 1 do
+        local run_number = res[i].ad_run_number
+        all_run_number = all_run_number + run_number
+    end
+    local nums = #res
+    sql = string.format("select * from `tg_main` where id = %d LIMIT 1 ",msg_body.main_id)
+    res = mysqldbx.query(sql)
+    local max = nums * res[1].max_ad_quantity
+    return true,{all_run_number=all_run_number,max=max}
+end
+
+
+function M.search_info_by_id(msg_body)
+    local isok ,key =  tools.checkData({"query_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local idString = table.concat(msg_body.query_list, ",")
+    local sql = string.format("SELECT * FROM tg_main WHERE id IN (%s)",idString)
+    local res = mysqldbx.query(sql)
+    return true,res
+end
+
+
+function M.search_info_by_tg_app_index(msg_body)
+    local isok ,key =  tools.checkData({"query_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local idString = table.concat(msg_body.query_list, ",")
+    local sql = string.format("SELECT * FROM tg_main WHERE tg_app_index IN (%s)",idString)
+    local res = mysqldbx.query(sql)
+    return true,res
+end
+
+
+function M.updateParentMain(parent_main_id)
+    local sql = string.format("select * from `tg_main` where id = '%s'  LIMIT 1 ",parent_main_id)
+    local res = mysqldbx.query(sql)
+    local main_info = nil
+    if #res>0 then
+        main_info = res[1]
+    end
+
+    if main_info~=nil then
+        sql = string.format("select * from `tg_main` where parent_main_id = %d LIMIT 500 ",parent_main_id)
+        res = mysqldbx.query(sql)
+        local child_list = nil
+        local id_list = {}
+        if #res>0 then
+            child_list = res
+            for i = 1, #child_list, 1 do
+                table.insert(id_list,i,child_list[i].id)
+            end
+        end
+
+        if child_list ~= nil then
+            local idString = table.concat(id_list, ",")
+            sql = string.format("UPDATE `tg_main` SET child_main_list = '%s' WHERE id = %d ",idString,parent_main_id)
+            mysqldbx.query(sql)
+        end
+    end
+
+end
+
+function mysqldtaskbx.start()
+    local function on_connect(db)
+        db:query("set charset utf8mb4");
+    end
+    local conf = config.db_cnf.book_server.mysqldb_task_cnf
+    db = mysql.connect{
+        host=conf.ip,
+        port=conf.port,
+        database=conf.db,
+        user=conf.user,
+        password=conf.password,
+        charset="utf8mb4",
+        max_packet_size = 1024 * 1024,
+        on_connect = on_connect
+    }
+    if not db then
+        error("mysql connect fail")
+    end
+end
+
+
+function mysqldtaskbx.Singleton()
+    if db == nil then
+        mysqldtaskbx.start()
+    end
+    return mysqldtaskbx
+end
+function mysqldtaskbx.query(sql)
+    return db:query(sql)
+end
+
+return M

+ 151 - 0
common/dbproxy/tg_max_zhuanhua.lua

@@ -0,0 +1,151 @@
+--最大转化
+local M = {}
+local db
+local mysqldtaskbx = {}
+local mysqldbx = require "mysqldbx"
+require "skynet.manager"
+local mysql = require "skynet.db.mysql"
+local config = require "run_config"
+local tools = require "tools"
+local skynet = require "skynet"
+
+--添加转化账户
+function M.addZhuanHuaZhangHu(msg_body)
+    local isok ,key =  tools.checkData({"advertiser_id","advertiser_name","status","is_deleted","budget"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local isok , find_data = M.findZhuangHuById({id=msg_body.advertiser_id})
+    if find_data==nil then
+        return false,string.format("advertiser_id 失败 : %d.", msg_body.advertiser_id)
+    end
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    msg_body.create_time = current_time
+    local sql = string.format("INSERT INTO `ad_cbo_advertiser_id` (advertiser_id,advertiser_name, create_time, update_time,status,is_deleted,budget)  VALUES (%d,'%s','%s','%s',%d,%d,%d)",
+    msg_body.advertiser_id,
+    msg_body.advertiser_name,
+    msg_body.create_time,
+    msg_body.create_time,
+    msg_body.status,msg_body.is_deleted,msg_body.budget)
+    local res = mysqldtaskbx.Singleton().query(sql)
+    skynet.error(sql)
+    tools.dump(res)
+    skynet.error(res)
+    return true
+end
+
+--modify
+function M.modifyZhuanHuaZhangHu(msg_body)
+    local isok ,key =  tools.checkData({"advertiser_id","advertiser_name","status","is_deleted","budget"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    msg_body.update_time = current_time
+    local sql = string.format("UPDATE `ad_cbo_advertiser_id` SET update_time ='%s', advertiser_id =%d ,advertiser_name ='%s' , status =%d , is_deleted =%d , budget =%d  WHERE id = %d ",
+    msg_body.update_time,msg_body.advertiser_id,msg_body.advertiser_name,msg_body.status,msg_body.is_deleted,msg_body.budget,msg_body.id)
+    skynet.error(sql)
+    mysqldtaskbx.Singleton().query(sql)
+    return true
+end
+
+
+--delete
+function M.deleteZhuanHuaZhangHu(msg_body)
+    local isok ,key =  tools.checkData({"id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    msg_body.update_time = current_time
+    for i = 1, #msg_body.id_list, 1 do
+       local id = msg_body.id_list[i]
+       local sql = string.format("UPDATE `ad_cbo_advertiser_id` SET update_time ='%s', is_deleted =%d WHERE id = %d ",
+       msg_body.update_time,1,id)
+       mysqldtaskbx.Singleton().query(sql)
+    end
+    return true
+end
+
+--获取转换列表
+function M.getZhuanHuanList(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number","status"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local status = msg_body.status --状态 1:正常 0:禁用 2:全部
+    local status_cmd = "SELECT * FROM ad_cbo_advertiser_id WHERE is_deleted = 0 " ..string.format("and status = %d  ",status)
+    if status == 2 then
+        status_cmd = "SELECT * FROM ad_cbo_advertiser_id WHERE is_deleted = 0 "
+    end
+    local offset = (page_number - 1) * page_size
+    local sql = status_cmd .. string.format(" ORDER BY id LIMIT %d OFFSET %d",page_size, offset)
+    local isok,res;
+    res = mysqldtaskbx.Singleton().query(sql)
+    -- tools.dump(res)
+    -- skynet.error(sql)
+    if #res <= 0 then
+        return true ,{}
+    end
+    return true, res
+end
+
+--获取转换总数
+function M.getTotal()
+    local sql = "SELECT COUNT(*) AS total FROM ad_cbo_advertiser_id WHERE is_deleted = 0"
+    local res = mysqldtaskbx.Singleton().query(sql)
+    return true,res[1]
+end
+
+
+function mysqldtaskbx.start()
+    local function on_connect(db)
+        db:query("set charset utf8mb4");
+    end
+    local conf = config.db_cnf.book_server.mysqldb_task_cnf
+    db = mysql.connect{
+        host=conf.ip,
+        port=conf.port,
+        database=conf.db,
+        user=conf.user,
+        password=conf.password,
+        charset="utf8mb4",
+        max_packet_size = 1024 * 1024,
+        on_connect = on_connect
+    }
+    if not db then
+        error("mysql connect fail")
+    end
+end
+
+
+--根据id获取账户
+function M.findZhuangHuById(msg_body)
+    local isok ,key =  tools.checkData({"id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    msg_body.update_time = current_time
+    local sql = string.format("select * from advertiser WHERE advertiser_id = '%s'  LIMIT 1",tostring(msg_body.id))
+    local res = mysqldbx.query(sql)
+    local info = nil
+    if #res>0 then
+        info = res
+    end
+    return true,info
+end
+
+function mysqldtaskbx.Singleton()
+    if db == nil then
+        mysqldtaskbx.start()
+    end
+    return mysqldtaskbx
+end
+function mysqldtaskbx.query(sql)
+    return db:query(sql)
+end
+
+return M

+ 355 - 0
common/dbproxy/tg_platform.lua

@@ -0,0 +1,355 @@
+--书籍平台
+local M = {}
+local skynet = require "skynet"
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local cjson = require "cjson"
+
+--获取所有平台
+function M.getPlatformList()
+    local sql = string.format("select * from `tg_platform` ")
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res <= 0 then
+        return true , {}
+    end
+    return true, res
+end
+
+--添加平台
+function M.addPlatform(msg_body)
+    local isok ,key ,id=  tools.checkData({"material_platform_id","pay_type","parent_platform_id","filter_guajian_logic_list","platform_shared_id","mini_program_platform_id","tg_platform_name","filter_guajian_logic"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local _,data = M.getTotal()
+    local id = data.total + 1
+    local sql = string.format("INSERT INTO `tg_platform` (material_platform_id,pay_type,parent_platform_id,filter_guajian_logic_list,platform_shared_id,mini_program_platform_id,tg_platform_id,tg_platform_name,filter_guajian_logic)  VALUES (%d,%d,%d,'%s',%d,%d,%d,'%s','%s')",
+    msg_body.material_platform_id,
+    msg_body.pay_type,
+    msg_body.parent_platform_id, 
+    cjson.encode(msg_body.filter_guajian_logic_list),msg_body.platform_shared_id,msg_body.mini_program_platform_id,id,msg_body.tg_platform_name,msg_body.filter_guajian_logic)
+    skynet.error(sql)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updatePlatformConfig"}))
+    return true
+end
+
+
+function M.set_huichuan(msg_body)
+    local isok ,key =  tools.checkData({"huichuan","id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE `tg_platform` SET  huichuan = '%s'  WHERE id = %d ",
+    cjson.encode(msg_body.huichuan),msg_body.id)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updatePlatformConfig"}))
+    return true
+end
+
+function M.set_chongzhi(msg_body)
+    local isok ,key =  tools.checkData({"chongzhi","id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE `tg_platform` SET  chongzhi = '%s'  WHERE id = %d ",
+    cjson.encode(msg_body.chongzhi),msg_body.id)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updatePlatformConfig"}))
+    return true
+end
+
+function M.set_kadian(msg_body)
+    local isok ,key =  tools.checkData({"kadian","id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE `tg_platform` SET  kadian = '%s'  WHERE id = %d ",
+    cjson.encode(msg_body.kadian),msg_body.id)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updatePlatformConfig"}))
+    return true
+end
+
+function M.set_f_chongzhi(msg_body)
+    local isok ,key =  tools.checkData({"f_chongzhi","id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE `tg_platform` SET  f_chongzhi = '%s'  WHERE id = %d ",
+    cjson.encode(msg_body.f_chongzhi),msg_body.id)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updatePlatformConfig"}))
+    return true
+end
+
+--修改平台
+function M.modifyPlatform(msg_body)
+    local isok ,key =  tools.checkData({"material_platform_id","pay_type","parent_platform_id","filter_guajian_logic_list","platform_shared_id","mini_program_platform_id","tg_platform_name","id","filter_guajian_logic"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE `tg_platform` SET material_platform_id = %d , pay_type = %d , parent_platform_id = %d , filter_guajian_logic_list = '%s' , platform_shared_id = %d , mini_program_platform_id = %d , filter_guajian_logic = '%s' , tg_platform_name = '%s'  WHERE id = %d ",
+    msg_body.material_platform_id,
+    msg_body.pay_type,
+    msg_body.parent_platform_id,
+    cjson.encode(msg_body.filter_guajian_logic_list),
+    msg_body.platform_shared_id,
+    msg_body.mini_program_platform_id,
+    msg_body.filter_guajian_logic,
+    msg_body.tg_platform_name,msg_body.id)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updatePlatformConfig"}))
+    return true
+end
+
+
+
+--添加回传规则
+function M.addHuiChuanRule(msg_body)
+    local isok ,key =  tools.checkData({"name","id","value"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("select huichuan from `tg_platform` WHERE id = %d ",msg_body.id)
+    local res = mysqldbx.query(sql)
+    local obj = {}
+    if res[1].huichuan~=nil then
+        obj = cjson.decode(res[1].huichuan)
+    end
+    local id = #obj+1
+    table.insert(obj,id,{id=id,name=msg_body.name,value=msg_body.value})
+    sql = string.format("UPDATE `tg_platform` SET  huichuan = '%s'  WHERE id = %d ",
+    cjson.encode(obj),msg_body.id)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updatePlatformConfig"}))
+    return true, obj
+end
+
+--修改回传规则
+function M.modifyHuiChuanRule(msg_body)
+    local isok ,key =  tools.checkData({"name","id","value","table_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("select huichuan from `tg_platform` WHERE id = %d ",msg_body.id)
+    local res = mysqldbx.query(sql)
+    local obj = {}
+    if res[1].huichuan~=nil then
+        obj = cjson.decode(res[1].huichuan)
+    end
+    for i = 1, #obj, 1 do
+        if obj[i].id == msg_body.table_id then
+            obj[i].name = msg_body.name
+            obj[i].value = msg_body.value
+            break
+        end
+    end
+    sql = string.format("UPDATE `tg_platform` SET  huichuan = '%s'  WHERE id = %d ",
+    cjson.encode(obj),msg_body.id)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updatePlatformConfig"}))
+    return true,obj
+end
+
+--添加收费卡点
+function M.addShouFeiKaDian(msg_body)
+    local isok ,key =  tools.checkData({"name","id","value"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("select kadian from `tg_platform` WHERE id = %d ",msg_body.id)
+    local res = mysqldbx.query(sql)
+    local obj = {}
+    if res[1].kadian~=nil then
+        obj = cjson.decode(res[1].kadian)
+    end
+    local id = #obj+1
+    table.insert(obj,id,{id=id,name=msg_body.name,value=msg_body.value})
+    sql = string.format("UPDATE `tg_platform` SET  kadian = '%s'  WHERE id = %d ",
+    cjson.encode(obj),msg_body.id)
+    mysqldbx.query(sql)
+    return true, obj
+end
+
+--修改收费卡点
+function M.modifyShouFeiKaDian(msg_body)
+    local isok ,key =  tools.checkData({"name","id","table_id","value"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("select kadian from `tg_platform` WHERE id = %d ",msg_body.id)
+    local res = mysqldbx.query(sql)
+    local obj = {}
+    if res[1].kadian~=nil then
+        obj = cjson.decode(res[1].kadian)
+    end
+    for i = 1, #obj, 1 do
+        if obj[i].id == msg_body.table_id then
+            obj[i].name = msg_body.name
+            obj[i].value = msg_body.value
+            break
+        end
+    end
+    sql = string.format("UPDATE `tg_platform` SET  kadian = '%s'  WHERE id = %d ",
+    cjson.encode(obj),msg_body.id)
+    mysqldbx.query(sql)
+    return true,obj
+end
+
+--添加充值模板
+function M.addChongZhiTemplate(msg_body)
+    local isok ,key =  tools.checkData({"name","id","value"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("select chongzhi from `tg_platform` WHERE id = %d ",msg_body.id)
+    local res = mysqldbx.query(sql)
+    local obj = {}
+    if res[1].chongzhi~=nil then
+        obj = cjson.decode(res[1].chongzhi)
+    end
+    local id = #obj+1
+    table.insert(obj,id,{id=id,name=msg_body.name,value=msg_body.value})
+    sql = string.format("UPDATE `tg_platform` SET  chongzhi = '%s'  WHERE id = %d ",
+    cjson.encode(obj),msg_body.id)
+    mysqldbx.query(sql)
+    return true, obj
+end
+
+--修改充值模板
+function M.modifyChongZhiTemplate(msg_body)
+    local isok ,key =  tools.checkData({"name","id","table_id","value"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("select chongzhi from `tg_platform` WHERE id = %d ",msg_body.id)
+    local res = mysqldbx.query(sql)
+    local obj = {}
+    if res[1].chongzhi ~=nil then
+        obj = cjson.decode(res[1].chongzhi)
+    end
+    for i = 1, #obj, 1 do
+        if obj[i].id == msg_body.table_id then
+            obj[i].name = msg_body.name
+            obj[i].value = msg_body.value
+            break
+        end
+    end
+    sql = string.format("UPDATE `tg_platform` SET  chongzhi = '%s'  WHERE id = %d ",
+    cjson.encode(obj),msg_body.id)
+    mysqldbx.query(sql)
+    return true,obj
+end
+
+
+
+--添加复充值模板
+function M.addFChongZhiTemplate(msg_body)
+    local isok ,key =  tools.checkData({"name","id","value"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("select f_chongzhi from `tg_platform` WHERE id = %d ",msg_body.id)
+    local res = mysqldbx.query(sql)
+    local obj = {}
+    if res[1].f_chongzhi~=nil then
+        obj = cjson.decode(res[1].f_chongzhi)
+    end
+    local id = #obj+1
+    table.insert(obj,id,{id=id,name=msg_body.name,value=msg_body.value})
+    sql = string.format("UPDATE `tg_platform` SET  f_chongzhi = '%s'  WHERE id = %d ",
+    cjson.encode(obj),msg_body.id)
+    mysqldbx.query(sql)
+    return true, obj
+end
+
+--修改复充值模板
+function M.modifyFChongZhiTemplate(msg_body)
+    local isok ,key =  tools.checkData({"name","id","table_id","value"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("select f_chongzhi from `tg_platform` WHERE id = %d ",msg_body.id)
+    local res = mysqldbx.query(sql)
+    local obj = {}
+    if res[1].f_chongzhi ~=nil then
+        obj = cjson.decode(res[1].f_chongzhi)
+    end
+    for i = 1, #obj, 1 do
+        if obj[i].id == msg_body.table_id then
+            obj[i].name = msg_body.name
+            obj[i].value = msg_body.value
+            break
+        end
+    end
+    sql = string.format("UPDATE `tg_platform` SET  f_chongzhi = '%s'  WHERE id = %d ",
+    cjson.encode(obj),msg_body.id)
+    mysqldbx.query(sql)
+    return true,obj
+end
+
+
+--添加推广小程序平台
+function M.addMiniProgramPlatform(msg_body)
+    local isok ,key =  tools.checkData({"name","id","value"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("select m_p_platform from `tg_platform` WHERE id = %d ",msg_body.id)
+    local res = mysqldbx.query(sql)
+    local obj = {}
+    if res[1].m_p_platform~=nil then
+        obj = cjson.decode(res[1].m_p_platform)
+    end
+    local id = #obj+1
+    table.insert(obj,id,{id=id,name=msg_body.name,value=msg_body.value})
+    sql = string.format("UPDATE `tg_platform` SET  m_p_platform = '%s'  WHERE id = %d ",
+    cjson.encode(obj),msg_body.id)
+    mysqldbx.query(sql)
+    return true, obj
+end
+
+--修改推广小程序平台
+function M.modifyMiniProgramPlatform(msg_body)
+    local isok ,key =  tools.checkData({"name","id","table_id","value"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("select m_p_platform from `tg_platform` WHERE id = %d ",msg_body.id)
+    local res = mysqldbx.query(sql)
+    local obj = {}
+    if res[1].m_p_platform~=nil then
+        obj = cjson.decode(res[1].m_p_platform)
+    end
+    for i = 1, #obj, 1 do
+        if obj[i].id == msg_body.table_id then
+            obj[i].name = msg_body.name
+            obj[i].value = msg_body.value
+            break
+        end
+    end
+    sql = string.format("UPDATE `tg_platform` SET  m_p_platform = '%s'  WHERE id = %d ",
+    cjson.encode(obj),msg_body.id)
+    mysqldbx.query(sql)
+    return true,obj
+end
+
+function M.set_filter_guajian_logic(msg_body)
+    local isok ,key =  tools.checkData({"id","filter_guajian_logic"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local  sql = string.format("UPDATE `tg_platform` SET  filter_guajian_logic = '%s'  WHERE id = %d ",msg_body.filter_guajian_logic,msg_body.id)
+    mysqldbx.query(sql)
+    return true,{}
+end
+
+function M.getTotal()
+    local sql = "SELECT COUNT(*) AS total FROM tg_platform"
+    local res = mysqldbx.query(sql)
+    return true,res[1]
+end
+
+return M

+ 51 - 0
common/dbproxy/tg_temp_app.lua

@@ -0,0 +1,51 @@
+--小程序
+local M = {}
+local skynet = require "skynet"
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+
+--获取所有小程序
+function M.getAppList()
+    local sql = string.format("select * from `tools_micro_app` ")
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res <= 0 then
+        return true ,{}
+    end
+    return true, res
+end
+
+--添加小程序
+function M.addApp(msg_body)
+    local isok ,key =  tools.checkData({"tg_platform_id","app_id","instance_id","name","advertiser_id","reason","audit_status","landing_page","titles","source","cpa_bid","budget"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    msg_body.create_time = current_time
+    local sql = string.format("INSERT INTO `tools_micro_app` (tg_platform_id,app_id, instance_id, name,advertiser_id,reason,create_time,audit_status,landing_page,titles,source,cpa_bid,budget,update_time)  VALUES (%d,'%s','%s','%s' ,'%s','%s','%s', '%s','%s','%s', '%s',%d, %d, '%s')",
+    msg_body.tg_platform_id,
+    msg_body.app_id,
+    msg_body.instance_id,msg_body.name,msg_body.advertiser_id,msg_body.reason,msg_body.create_time,msg_body.audit_status,msg_body.landing_page,msg_body.titles,msg_body.source,msg_body.cpa_bid,msg_body.budget,msg_body.create_time)
+    skynet.error(sql)
+    mysqldbx.query(sql)
+    return true
+end
+
+
+--修改小程序
+function M.modifyApp(msg_body)
+    local isok ,key =  tools.checkData({"tg_platform_id","id","app_id","instance_id","name","name","advertiser_id","reason","audit_status","landing_page","titles","source","cpa_bid","budget"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    msg_body.update_time = current_time
+    local sql = string.format("UPDATE `tools_micro_app` SET  tg_platform_id =%d ,app_id ='%s' , instance_id ='%s' , name ='%s' , advertiser_id ='%s'  , reason ='%s'  , audit_status ='%s'  , landing_page ='%s'   , titles ='%s'  , source ='%s'   , cpa_bid =%d   , budget =%d  , update_time ='%s'  WHERE id = %d ",
+    msg_body.tg_platform_id,msg_body.app_id,msg_body.instance_id,msg_body.name,msg_body.advertiser_id,msg_body.reason,msg_body.audit_status,msg_body.landing_page,msg_body.titles,msg_body.source,msg_body.cpa_bid,msg_body.budget,msg_body.update_time,msg_body.id)
+    skynet.error(sql)
+    mysqldbx.query(sql)
+    return true
+end
+
+return M

+ 244 - 0
common/dbproxy/tg_zhanghu.lua

@@ -0,0 +1,244 @@
+--账户
+local M = {}
+
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local httpc = require "http.httpc"
+--page_size  是你想要在每页中显示的记录数。
+--page_number 页数
+--获取所有账户
+function M.getZhangHuList(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    local sql = string.format("SELECT * FROM advertiser ORDER BY id LIMIT %d OFFSET %d", page_size, offset)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res <= 0 then
+        return true ,{}
+    end
+    return true, res
+end
+
+function M.getTotal()
+    local sql = "SELECT COUNT(*) AS total FROM advertiser"
+    local res = mysqldbx.query(sql)
+    return true,res[1]
+end
+
+
+function M.advertiserListOfMain(msg_body)
+    local isok ,key =  tools.checkData({"id_list","main_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local fail_list = {}
+    for i = 1, #msg_body.id_list, 1 do
+       local id = msg_body.id_list[i]
+       local sql = string.format("SELECT * FROM advertiser where advertiser_id = '%s' and main_id = %d ", id,msg_body.main_id)
+       local isok,res;
+       res = mysqldbx.query(sql)
+       if #res <1 then
+            table.insert(fail_list,#fail_list+1,id)
+       end
+    end
+    return true,fail_list
+end
+
+
+function M.setZhanghuOfMain(msg_body)
+    local isok ,key =  tools.checkData({"id_list","main_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    msg_body.update_time = current_time
+    for i = 1, #msg_body.id_list, 1 do
+        local id = msg_body.id_list[i]
+        local sql = string.format("UPDATE `advertiser` SET main_id = %d  WHERE id = %d ",
+        msg_body.main_id,id)
+        skynet.error(sql)
+        mysqldbx.query(sql)
+    end
+    return true,{}
+end
+
+function M.searchZhanghu(msg_body)
+    local isok ,key =  tools.checkData({"advertiser_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("SELECT * FROM advertiser  WHERE advertiser_id = '%s'  LIMIT 1 ", tostring(msg_body.advertiser_id))
+    local res;
+    res = mysqldbx.query(sql)
+    local info = {}
+    if #res>0 then
+        info = res[1]
+    end
+    return true,info
+end
+
+function M.searchName(msg_body)
+    local isok ,key =  tools.checkData({"content","page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+    local sql = string.format(" SELECT COUNT(*) AS total FROM advertiser  advertiser_name LIKE '%%%s%%' ",  msg_body.content)
+    local total = mysqldbx.query(sql)
+
+    sql = string.format("SELECT * FROM advertiser WHERE advertiser_name LIKE '%%%s%%'  ORDER BY id LIMIT %d OFFSET %d ", msg_body.content, page_size, offset)
+    local res;
+    res = mysqldbx.query(sql)
+    return true,res,total[1].total
+end
+
+function M.switch(msg_body)
+    local isok ,key =  tools.checkData({"id_list","status"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    for i = 1, #msg_body.id_list, 1 do
+        local id = msg_body.id_list[i]
+        local sql = string.format("UPDATE `advertiser` SET status = %d  WHERE id = %d ",
+        msg_body.status,id)
+        local res;
+        res = mysqldbx.query(sql)
+    end
+    return true,{}
+end
+function M.mainFilter(msg_body)
+    local isok ,key =  tools.checkData({"content","main_id","page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+    local main_id_param = ""
+    if msg_body.main_id ~= "" then
+        main_id_param = " AND main_id = "..msg_body.main_id.." "
+    end
+
+    local content_param = ""
+    if msg_body.content ~= "" then
+        content_param = string.format(" AND  (advertiser_name LIKE CONCAT( '%%%s%%')) OR (advertiser_id LIKE CONCAT('%%%s%%'))",msg_body.content,msg_body.content)
+    end
+    local sql = "SELECT COUNT(*) AS total FROM advertiser  WHERE 1=1 "..main_id_param..content_param
+    local total = mysqldbx.query(sql)
+
+    sql = "SELECT * FROM advertiser  WHERE 1=1 "..main_id_param..content_param..string.format(" ORDER BY id LIMIT %d OFFSET %d ",page_size, offset)
+    local res;
+    res = mysqldbx.query(sql)
+    return true,res,total[1].total
+end
+
+function M.search(msg_body)
+    local isok ,key =  tools.checkData({"avatar_status","property_status","main_id","content","page_size","page_number","status"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    
+    local property_status_param = ""
+    if msg_body.property_status~="" then
+        property_status_param = "AND property_status = "..msg_body.property_status.." "
+    end
+
+    local avatar_status_param = ""
+    if msg_body.avatar_status~="" then
+        avatar_status_param = "AND avatar_status = "..msg_body.avatar_status.." "
+    end
+
+    local statuss_param = ""
+    if msg_body.status~="" then
+        statuss_param = "AND status = "..msg_body.status.." "
+    end
+
+    local main_id_param = ""
+    if msg_body.main_id ~= "" then
+        main_id_param = " AND main_id = "..msg_body.main_id.." "
+    end
+
+    local content_param = ""
+    if msg_body.content ~= "" then
+        content_param = string.format(" AND  (advertiser_name LIKE CONCAT( '%%%s%%')) OR (advertiser_id LIKE CONCAT('%%%s%%'))",msg_body.content,msg_body.content)
+    end
+
+    local param = avatar_status_param..property_status_param..statuss_param..main_id_param..content_param
+    local sql = "SELECT COUNT(*) AS total FROM advertiser  WHERE 1=1 "..param
+    local total = mysqldbx.query(sql)
+
+    sql = "SELECT * FROM advertiser  WHERE 1=1 "..param..string.format(" ORDER BY id LIMIT %d OFFSET %d ",page_size, offset)
+    local res;
+    res = mysqldbx.query(sql)
+    return true,res,total[1].total
+end
+
+function M.search_info_by_id(msg_body)
+    local isok ,key =  tools.checkData({"query_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local temp = {}
+    for i = 1, #msg_body.query_list, 1 do
+        local zhang_hu_id = msg_body.query_list[i].zhang_hu_id..""
+        local key = msg_body.query_list[i].id
+        local sql = string.format("SELECT * FROM advertiser WHERE advertiser_id = '%s' LIMIT 1",zhang_hu_id)
+        local res = mysqldbx.query(sql)
+        if #res >0 then
+            table.insert(temp,#temp+1,res[1])
+        end
+    end
+    return true,temp
+end
+
+function M.update_zhanghu(msg_body)
+    httpc.dns() -- set dns server
+    httpc.timeout = 100 -- set timeout 1 second
+    local status, body = httpc.get('https://clipvideoup.s6kuwan.com/adoce/advertiser/sync_center_advertiser','',{})
+    if status == 200 then
+        return true,{}
+    else
+        return false,{}
+    end
+    return true,{}
+end
+function searchZhanghuName(name,id)
+    local sql = string.format("SELECT * FROM advertiser WHERE advertiser_name LIKE '%%%s%%'", name)
+    local res;
+    res = mysqldbx.query(sql)
+    local id_list = {}
+    for i = 1, #res, 1 do
+        table.insert(id_list,i,res[i].id)
+    end
+    if #id_list> 0 then
+        M.setZhanghuOfMain({id_list=id_list,main_id=id})
+    end
+end
+function M.init()
+    local sql = string.format("select * from `tg_main` ")
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res > 0 then
+        tools.dump(res)
+        for i = 1, #res, 1 do
+            local name = res[i].main_name
+            searchZhanghuName(name,res[i].id)
+        end
+    end
+    return true,{}
+end
+return M

+ 1598 - 0
common/preload/functions.lua

@@ -0,0 +1,1598 @@
+--[[
+
+Copyright (c) 2011-2014 chukong-inc.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+]]
+
+--[[--
+
+提供一组常用函数,以及对 Lua 标准库的扩展
+
+]]
+
+--[[--
+
+输出格式化字符串
+
+~~~ lua
+
+printf("The value = %d", 100)
+
+~~~
+
+@param string fmt 输出格式
+@param [mixed ...] 更多参数
+
+]]
+function printf(fmt, ...)
+    print(string.format(tostring(fmt), ...))
+end
+
+local skynet = require "skynet"
+local cjson  = require "cjson"
+
+function table.empty(tlb)
+    local t = tlb or {}
+    for k, v in pairs(tlb) do
+        return false
+    end
+
+    return true
+end
+
+function table.array(array)
+    return setmetatable(array, cjson.empty_array_mt)
+end
+
+function table.dumpdebug(value, desciption, nesting)
+    if type(nesting) ~= "number" then nesting = 3 end
+
+    local lookupTable = {}
+    local result = {}
+
+    local function _v(v)
+        if type(v) == "string" then
+            v = "\"" .. v .. "\""
+        end
+        return tostring(v)
+    end
+
+    local traceback = string.split(debug.traceback("", 2), "\n")
+    if not ngx then
+        skynet.error("dump from: " .. string.trim(traceback[3]))
+    else
+        ngx.log(ngx.DEBUG,"dump from: " .. string.trim(traceback[3]))
+    end
+
+    local function _dump(value, desciption, indent, nest, keylen)
+        desciption = desciption or "<var>"
+        spc = ""
+        if type(keylen) == "number" then
+            spc = string.rep(" ", keylen - string.len(_v(desciption)))
+        end
+        if type(value) ~= "table" then
+            result[#result +1 ] = string.format("%s%s%s = %s", indent, _v(desciption), spc, _v(value))
+        elseif lookupTable[value] then
+            result[#result +1 ] = string.format("%s%s%s = *REF*", indent, desciption, spc)
+        else
+            lookupTable[value] = true
+            if nest > nesting then
+                result[#result +1 ] = string.format("%s%s = *MAX NESTING*", indent, desciption)
+            else
+                result[#result +1 ] = string.format("%s%s = {", indent, _v(desciption))
+                local indent2 = indent.."    "
+                local keys = {}
+                local keylen = 0
+                local values = {}
+                for k, v in pairs(value) do
+                    keys[#keys + 1] = k
+                    local vk = _v(k)
+                    local vkl = string.len(vk)
+                    if vkl > keylen then keylen = vkl end
+                    values[k] = v
+                end
+                table.sort(keys, function(a, b)
+                    if type(a) == "number" and type(b) == "number" then
+                        return a < b
+                    else
+                        return tostring(a) < tostring(b)
+                    end
+                end)
+                for i, k in ipairs(keys) do
+                    _dump(values[k], k, indent2, nest + 1, keylen)
+                end
+                result[#result +1] = string.format("%s}", indent)
+            end
+        end
+    end
+    _dump(value, desciption, "- ", 1)
+
+    for i, line in ipairs(result) do
+        if not ngx then
+            skynet.error(line)
+        else
+            ngx.log(ngx.DEBUG,line)
+        end
+    end
+end
+
+string.split = function(s, p)
+
+    local rt= {}
+    string.gsub(s, '[^'..p..']+', function(w) table.insert(rt, w) end )
+    return rt
+
+end
+
+--[[--
+
+检查并尝试转换为数值,如果无法转换则返回 0
+
+@param mixed value 要检查的值
+@param [integer base] 进制,默认为十进制
+
+@return number
+
+]]
+function checknumber(value, base)
+    return tonumber(value, base) or 0
+end
+
+--[[--
+
+检查并尝试转换为整数,如果无法转换则返回 0
+
+@param mixed value 要检查的值
+
+@return integer
+
+]]
+function checkint(value)
+    return math.round(checknumber(value))
+end
+
+--[[--
+
+检查并尝试转换为布尔值,除了 nil 和 false,其他任何值都会返回 true
+
+@param mixed value 要检查的值
+
+@return boolean
+
+]]
+function checkbool(value)
+    return (value ~= nil and value ~= false)
+end
+
+--[[--
+
+检查值是否是一个表格,如果不是则返回一个空表格
+
+@param mixed value 要检查的值
+
+@return table
+
+]]
+function checktable(value)
+    if type(value) ~= "table" then value = {} end
+    return value
+end
+
+--[[--
+
+如果表格中指定 key 的值为 nil,或者输入值不是表格,返回 false,否则返回 true
+
+@param table hashtable 要检查的表格
+@param mixed key 要检查的键名
+
+@return boolean
+
+]]
+function isset(hashtable, key)
+    local t = type(hashtable)
+    return (t == "table" or t == "userdata") and hashtable[key] ~= nil
+end
+
+--[[--
+
+深度克隆一个值
+
+~~~ lua
+
+-- 下面的代码,t2 是 t1 的引用,修改 t2 的属性时,t1 的内容也会发生变化
+local t1 = {a = 1, b = 2}
+local t2 = t1
+t2.b = 3    -- t1 = {a = 1, b = 3} <-- t1.b 发生变化
+
+-- clone() 返回 t1 的副本,修改 t2 不会影响 t1
+local t1 = {a = 1, b = 2}
+local t2 = clone(t1)
+t2.b = 3    -- t1 = {a = 1, b = 2} <-- t1.b 不受影响
+
+~~~
+
+@param mixed object 要克隆的值
+
+@return mixed
+
+]]
+function clone(object)
+    local lookup_table = {}
+    local function _copy(object)
+        if type(object) ~= "table" then
+            return object
+        elseif lookup_table[object] then
+            return lookup_table[object]
+        end
+        local new_table = {}
+        lookup_table[object] = new_table
+        for key, value in pairs(object) do
+            new_table[_copy(key)] = _copy(value)
+        end
+        return setmetatable(new_table, getmetatable(object))
+    end
+    return _copy(object)
+end
+
+--[[--
+
+创建一个类
+
+~~~ lua
+
+-- 定义名为 Shape 的基础类
+local Shape = class("Shape")
+
+-- ctor() 是类的构造函数,在调用 Shape.new() 创建 Shape 对象实例时会自动执行
+function Shape:ctor(shapeName)
+    self.shapeName = shapeName
+    printf("Shape:ctor(%s)", self.shapeName)
+end
+
+-- 为 Shape 定义个名为 draw() 的方法
+function Shape:draw()
+    printf("draw %s", self.shapeName)
+end
+
+--
+
+-- Circle 是 Shape 的继承类
+local Circle = class("Circle", Shape)
+
+function Circle:ctor()
+    -- 如果继承类覆盖了 ctor() 构造函数,那么必须手动调用父类构造函数
+    -- 类名.super 可以访问指定类的父类
+    Circle.super.ctor(self, "circle")
+    self.radius = 100
+end
+
+function Circle:setRadius(radius)
+    self.radius = radius
+end
+
+-- 覆盖父类的同名方法
+function Circle:draw()
+    printf("draw %s, raidus = %0.2f", self.shapeName, self.raidus)
+end
+
+--
+
+local Rectangle = class("Rectangle", Shape)
+
+function Rectangle:ctor()
+    Rectangle.super.ctor(self, "rectangle")
+end
+
+--
+
+local circle = Circle.new()             -- 输出: Shape:ctor(circle)
+circle:setRaidus(200)
+circle:draw()                           -- 输出: draw circle, radius = 200.00
+
+local rectangle = Rectangle.new()       -- 输出: Shape:ctor(rectangle)
+rectangle:draw()                        -- 输出: draw rectangle
+
+~~~
+
+### 高级用法
+
+class() 除了定义纯 Lua 类之外,还可以从 C++ 对象继承类。
+
+比如需要创建一个工具栏,并在添加按钮时自动排列已有的按钮,那么我们可以使用如下的代码:
+
+~~~ lua
+
+-- 从 CCNode 对象派生 Toolbar 类,该类具有 CCNode 的所有属性和行为
+local Toolbar = class("Toolbar", function()
+    return display.newNode() -- 返回一个 CCNode 对象
+end)
+
+-- 构造函数
+function Toolbar:ctor()
+    self.buttons = {} -- 用一个 table 来记录所有的按钮
+end
+
+-- 添加一个按钮,并且自动设置按钮位置
+function Toolbar:addButton(button)
+    -- 将按钮对象加入 table
+    self.buttons[#self.buttons + 1] = button
+
+    -- 添加按钮对象到 CCNode 中,以便显示该按钮
+    -- 因为 Toolbar 是从 CCNode 继承的,所以可以使用 addChild() 方法
+    self:addChild(button)
+
+    -- 按照按钮数量,调整所有按钮的位置
+    local x = 0
+    for _, button in ipairs(self.buttons) do
+        button:setPosition(x, 0)
+        -- 依次排列按钮,每个按钮之间间隔 10 点
+        x = x + button:getContentSize().width + 10
+    end
+end
+
+~~~
+
+class() 的这种用法让我们可以在 C++ 对象基础上任意扩展行为。
+
+既然是继承,自然就可以覆盖 C++ 对象的方法:
+
+~~~ lua
+
+function Toolbar:setPosition(x, y)
+    -- 由于在 Toolbar 继承类中覆盖了 CCNode 对象的 setPosition() 方法
+    -- 所以我们要用以下形式才能调用到 CCNode 原本的 setPosition() 方法
+    getmetatable(self).setPosition(self, x, y)
+
+    printf("x = %0.2f, y = %0.2f", x, y)
+end
+
+~~~
+
+**注意:** Lua 继承类覆盖的方法并不能从 C++ 调用到。也就是说通过 C++ 代码调用这个 CCNode 对象的 setPosition() 方法时,并不会执行我们在 Lua 中定义的 Toolbar:setPosition() 方法。
+
+@param string classname 类名
+@param [mixed super] 父类或者创建对象实例的函数
+
+@return table
+
+]]
+function class(classname, super)
+    local superType = type(super)
+    local cls
+
+    if superType ~= "function" and superType ~= "table" then
+        superType = nil
+        super = nil
+    end
+
+    if superType == "function" or (super and super.__ctype == 1) then
+        -- inherited from native C++ Object
+        cls = {}
+
+        if superType == "table" then
+            -- copy fields from super
+            for k,v in pairs(super) do cls[k] = v end
+            cls.__create = super.__create
+            cls.super    = super
+        else
+            cls.__create = super
+            cls.ctor = function() end
+        end
+
+        cls.__cname = classname
+        cls.__ctype = 1
+
+        function cls.new(...)
+            local instance = cls.__create(...)
+            -- copy fields from class to native object
+            for k,v in pairs(cls) do instance[k] = v end
+            instance.class = cls
+            instance:ctor(...)
+            return instance
+        end
+
+    else
+        -- inherited from Lua Object
+        if super then
+            cls = {}
+            setmetatable(cls, {__index = super})
+            cls.super = super
+        else
+            cls = {ctor = function() end}
+        end
+
+        cls.__cname = classname
+        cls.__ctype = 2 -- lua
+        cls.__index = cls
+
+        function cls.new(...)
+            local instance = setmetatable({}, cls)
+            instance.class = cls
+            instance:ctor(...)
+            return instance
+        end
+    end
+
+    return cls
+end
+
+-- 提供假名以避免和 moonscript 发生冲突
+function quick_class(classname, super)
+  return class(classname, super)
+end
+
+
+--[[--
+
+如果对象是指定类或其子类的实例,返回 true,否则返回 false
+
+~~~ lua
+
+local Animal = class("Animal")
+local Duck = class("Duck", Animal)
+
+print(iskindof(Duck.new(), "Animal")) -- 输出 true
+
+~~~
+
+@param mixed obj 要检查的对象
+@param string classname 类名
+
+@return boolean
+
+]]
+function iskindof(obj, classname)
+    local t = type(obj)
+    local mt
+    if t == "table" then
+        mt = getmetatable(obj)
+    elseif t == "userdata" then
+        mt = tolua.getpeer(obj)
+    end
+
+    while mt do
+        if mt.__cname == classname then
+            return true
+        end
+        mt = mt.super
+    end
+
+    return false
+end
+
+--[[--
+
+载入一个模块
+
+import() 与 require() 功能相同,但具有一定程度的自动化特性。
+
+假设我们有如下的目录结构:
+
+~~~
+
+app/
+app/classes/
+app/classes/MyClass.lua
+app/classes/MyClassBase.lua
+app/classes/data/Data1.lua
+app/classes/data/Data2.lua
+
+~~~
+
+MyClass 中需要载入 MyClassBase 和 MyClassData。如果用 require(),MyClass 内的代码如下:
+
+~~~ lua
+
+local MyClassBase = require("app.classes.MyClassBase")
+local MyClass = class("MyClass", MyClassBase)
+
+local Data1 = require("app.classes.data.Data1")
+local Data2 = require("app.classes.data.Data2")
+
+~~~
+
+假如我们将 MyClass 及其相关文件换一个目录存放,那么就必须修改 MyClass 中的 require() 命令,否则将找不到模块文件。
+
+而使用 import(),我们只需要如下写:
+
+~~~ lua
+
+local MyClassBase = import(".MyClassBase")
+local MyClass = class("MyClass", MyClassBase)
+
+local Data1 = import(".data.Data1")
+local Data2 = import(".data.Data2")
+
+~~~
+
+当在模块名前面有一个"." 时,import() 会从当前模块所在目录中查找其他模块。因此 MyClass 及其相关文件不管存放到什么目录里,我们都不再需要修改 MyClass 中的 import() 命令。这在开发一些重复使用的功能组件时,会非常方便。
+
+我们可以在模块名前添加多个"." ,这样 import() 会从更上层的目录开始查找模块。
+
+~
+
+不过 import() 只有在模块级别调用(也就是没有将 import() 写在任何函数中)时,才能够自动得到当前模块名。如果需要在函数中调用 import(),那么就需要指定当前模块名:
+
+~~~ lua
+
+# MyClass.lua
+
+# 这里的 ... 是隐藏参数,包含了当前模块的名字,所以最好将这行代码写在模块的第一行
+local CURRENT_MODULE_NAME = ...
+
+local function testLoad()
+    local MyClassBase = import(".MyClassBase", CURRENT_MODULE_NAME)
+    # 更多代码
+end
+
+~~~
+
+@param string moduleName 要载入的模块的名字
+@param [string currentModuleName] 当前模块名
+
+@return module
+
+]]
+function import(moduleName, currentModuleName)
+    local currentModuleNameParts
+    local moduleFullName = moduleName
+    local offset = 1
+
+    while true do
+        if string.byte(moduleName, offset) ~= 46 then -- .
+            moduleFullName = string.sub(moduleName, offset)
+            if currentModuleNameParts and #currentModuleNameParts > 0 then
+                moduleFullName = table.concat(currentModuleNameParts, ".") .. "." .. moduleFullName
+            end
+            break
+        end
+        offset = offset + 1
+
+        if not currentModuleNameParts then
+            if not currentModuleName then
+                local n,v = debug.getlocal(3, 1)
+                currentModuleName = v
+            end
+
+            currentModuleNameParts = string.split(currentModuleName, ".")
+        end
+        table.remove(currentModuleNameParts, #currentModuleNameParts)
+    end
+
+    return require(moduleFullName)
+end
+
+--[[--
+
+将 Lua 对象及其方法包装为一个匿名函数
+
+在 quick-cocos2d-x 中,许多功能需要传入一个 Lua 函数做参数,然后在特定事件发生时就会调用传入的函数。例如触摸事件、帧事件等等。
+
+~~~ lua
+
+local MyScene = class("MyScene", function()
+    return display.newScene("MyScene")
+end)
+
+function MyScene:ctor()
+    self.frameTimeCount = 0
+    -- 注册帧事件
+    self:addEventListener(cc.ENTER_FRAME_EVENT, self.onEnterFrame)
+end
+
+function MyScene:onEnterFrame(dt)
+    self.frameTimeCount = self.frameTimeCount + dt
+end
+
+~~~
+
+上述代码执行时将出错,报告"Invalid self" ,这就是因为 C++ 无法识别 Lua 对象方法。因此在调用我们传入的 self.onEnterFrame 方法时没有提供正确的参数。
+
+要让上述的代码正常工作,就需要使用 handler() 进行一下包装:
+
+~~~ lua
+
+function MyScene:ctor()
+    self.frameTimeCount = 0
+    -- 注册帧事件
+    self:addEventListener(cc.ENTER_FRAME_EVENT, handler(self, self.onEnterFrame))
+end
+
+~~~
+
+实际上,除了 C++ 回调 Lua 函数之外,在其他所有需要回调的地方都可以使用 handler()。
+
+@param mixed obj Lua 对象
+@param function method 对象方法
+
+@return function
+
+]]
+function handler(obj, method)
+    return function(...)
+        return method(obj, ...)
+    end
+end
+
+--[[--
+
+根据系统时间初始化随机数种子,让后续的 math.random() 返回更随机的值
+
+]]
+function math.newrandomseed()
+    local ok, socket = pcall(function()
+        return require("socket")
+    end)
+
+    if ok then
+        -- 如果集成了 socket 模块,则使用 socket.gettime() 获取随机数种子
+        math.randomseed(socket.gettime() * 1000)
+    else
+        math.randomseed(os.time())
+    end
+    math.random()
+    math.random()
+    math.random()
+    math.random()
+end
+
+--[[--
+
+对数值进行四舍五入,如果不是数值则返回 0
+
+@param number value 输入值
+
+@return number
+
+]]
+function math.round(value)
+    return math.floor(value + 0.5)
+end
+
+function math.angle2radian(angle)
+    return angle*math.pi/180
+end
+
+function math.radian2angle(radian)
+    return radian/math.pi*180
+end
+
+--[[--
+
+检查指定的文件或目录是否存在,如果存在返回 true,否则返回 false
+
+可以使用 CCFileUtils:fullPathForFilename() 函数查找特定文件的完整路径,例如:
+
+~~~ lua
+
+local path = CCFileUtils:sharedFileUtils():fullPathForFilename("gamedata.txt")
+if io.exists(path) then
+    ....
+end
+
+~~~
+
+@param string path 要检查的文件或目录的完全路径
+
+@return boolean
+
+]]
+function io.exists(path)
+    local file = io.open(path, "r")
+    if file then
+        io.close(file)
+        return true
+    end
+    return false
+end
+
+--[[--
+
+读取文件内容,返回包含文件内容的字符串,如果失败返回 nil
+
+io.readfile() 会一次性读取整个文件的内容,并返回一个字符串,因此该函数不适宜读取太大的文件。
+
+@param string path 文件完全路径
+
+@return string
+
+]]
+function io.readfile(path)
+    local file = io.open(path, "r")
+    if file then
+        local content = file:read("*a")
+        io.close(file)
+        return content
+    end
+    return nil
+end
+
+--[[--
+
+以字符串内容写入文件,成功返回 true,失败返回 false
+
+"mode 写入模式" 参数决定 io.writefile() 如何写入内容,可用的值如下:
+
+-   "w+" : 覆盖文件已有内容,如果文件不存在则创建新文件
+-   "a+" : 追加内容到文件尾部,如果文件不存在则创建文件
+
+此外,还可以在 "写入模式" 参数最后追加字符 "b" ,表示以二进制方式写入数据,这样可以避免内容写入不完整。
+
+**Android 特别提示:** 在 Android 平台上,文件只能写入存储卡所在路径,assets 和 data 等目录都是无法写入的。
+
+@param string path 文件完全路径
+@param string content 要写入的内容
+@param [string mode] 写入模式,默认值为 "w+b"
+
+@return boolean
+
+]]
+function io.writefile(path, content, mode)
+    mode = mode or "w+b"
+    local file = io.open(path, mode)
+    if file then
+        if file:write(content) == nil then return false end
+        io.close(file)
+        return true
+    else
+        return false
+    end
+end
+
+--[[--
+
+拆分一个路径字符串,返回组成路径的各个部分
+
+~~~ lua
+
+local pathinfo  = io.pathinfo("/var/app/test/abc.png")
+
+-- 结果:
+-- pathinfo.dirname  = "/var/app/test/"
+-- pathinfo.filename = "abc.png"
+-- pathinfo.basename = "abc"
+-- pathinfo.extname  = ".png"
+
+~~~
+
+@param string path 要分拆的路径字符串
+
+@return table
+
+]]
+function io.pathinfo(path)
+    local pos = string.len(path)
+    local extpos = pos + 1
+    while pos > 0 do
+        local b = string.byte(path, pos)
+        if b == 46 then -- 46 = char "."
+            extpos = pos
+        elseif b == 47 then -- 47 = char "/"
+            break
+        end
+        pos = pos - 1
+    end
+
+    local dirname = string.sub(path, 1, pos)
+    local filename = string.sub(path, pos + 1)
+    extpos = extpos - pos
+    local basename = string.sub(filename, 1, extpos - 1)
+    local extname = string.sub(filename, extpos)
+    return {
+        dirname = dirname,
+        filename = filename,
+        basename = basename,
+        extname = extname
+    }
+end
+
+--[[--
+
+返回指定文件的大小,如果失败返回 false
+
+@param string path 文件完全路径
+
+@return integer
+
+]]
+function io.filesize(path)
+    local size = false
+    local file = io.open(path, "r")
+    if file then
+        local current = file:seek()
+        size = file:seek("end")
+        file:seek("set", current)
+        io.close(file)
+    end
+    return size
+end
+
+--[[--
+
+计算表格包含的字段数量
+
+Lua table 的 "#" 操作只对依次排序的数值下标数组有效,table.nums() 则计算 table 中所有不为 nil 的值的个数。
+
+@param table t 要检查的表格
+
+@return integer
+
+]]
+function table.nums(t)
+    local count = 0
+    for k, v in pairs(t) do
+        count = count + 1
+    end
+    return count
+end
+
+--[[--
+
+返回指定表格中的所有键
+
+~~~ lua
+
+local hashtable = {a = 1, b = 2, c = 3}
+local keys = table.keys(hashtable)
+-- keys = {"a", "b", "c"}
+
+~~~
+
+@param table hashtable 要检查的表格
+
+@return table
+
+]]
+function table.keys(hashtable)
+    local keys = {}
+    for k, v in pairs(hashtable) do
+        keys[#keys + 1] = k
+    end
+    return keys
+end
+
+--[[--
+
+返回指定表格中的所有值
+
+~~~ lua
+
+local hashtable = {a = 1, b = 2, c = 3}
+local values = table.values(hashtable)
+-- values = {1, 2, 3}
+
+~~~
+
+@param table hashtable 要检查的表格
+
+@return table
+
+]]
+function table.values(hashtable)
+    local values = {}
+    for k, v in pairs(hashtable) do
+        values[#values + 1] = v
+    end
+    return values
+end
+
+--[[--
+
+将来源表格中所有键及其值复制到目标表格对象中,如果存在同名键,则覆盖其值
+
+~~~ lua
+
+local dest = {a = 1, b = 2}
+local src  = {c = 3, d = 4}
+table.merge(dest, src)
+-- dest = {a = 1, b = 2, c = 3, d = 4}
+
+~~~
+
+@param table dest 目标表格
+@param table src 来源表格
+
+]]
+function table.merge(dest, src)
+    for k, v in pairs(src) do
+        dest[k] = v
+    end
+end
+
+--[[--
+
+在目标表格的指定位置插入来源表格,如果没有指定位置则连接两个表格
+
+~~~ lua
+
+local dest = {1, 2, 3}
+local src  = {4, 5, 6}
+table.insertto(dest, src)
+-- dest = {1, 2, 3, 4, 5, 6}
+
+dest = {1, 2, 3}
+table.insertto(dest, src, 5)
+-- dest = {1, 2, 3, nil, 4, 5, 6}
+
+~~~
+
+@param table dest 目标表格
+@param table src 来源表格
+@param [integer begin] 插入位置
+
+]]
+function table.insertto(dest, src, begin)
+    begin = checkint(begin)
+    if begin <= 0 then
+        begin = #dest + 1
+    end
+
+    local len = #src
+    for i = 0, len - 1 do
+        dest[i + begin] = src[i + 1]
+    end
+end
+
+--[[
+
+从表格中查找指定值,返回其索引,如果没找到返回 false
+
+~~~ lua
+
+local array = {"a", "b", "c"}
+print(table.indexof(array, "b")) -- 输出 2
+
+~~~
+
+@param table array 表格
+@param mixed value 要查找的值
+@param [integer begin] 起始索引值
+
+@return integer
+
+]]
+function table.indexof(array, value, begin)
+    for i = begin or 1, #array do
+        if array[i] == value then return i end
+    end
+    return false
+end
+
+--[[--
+
+从表格中查找指定值,返回其 key,如果没找到返回 nil
+
+~~~ lua
+
+local hashtable = {name = "dualface", comp = "chukong"}
+print(table.keyof(hashtable, "chukong")) -- 输出 comp
+
+~~~
+
+@param table hashtable 表格
+@param mixed value 要查找的值
+
+@return string 该值对应的 key
+
+]]
+function table.keyof(hashtable, value)
+    for k, v in pairs(hashtable) do
+        if v == value then return k end
+    end
+    return nil
+end
+
+--[[--
+
+从表格中删除指定值,返回删除的值的个数
+
+~~~ lua
+
+local array = {"a", "b", "c", "c"}
+print(table.removebyvalue(array, "c", true)) -- 输出 2
+
+~~~
+
+@param table array 表格
+@param mixed value 要删除的值
+@param [boolean removeall] 是否删除所有相同的值
+
+@return integer
+
+]]
+function table.removebyvalue(array, value, removeall)
+    local c, i, max = 0, 1, #array
+    while i <= max do
+        if array[i] == value then
+            table.remove(array, i)
+            c = c + 1
+            i = i - 1
+            max = max - 1
+            if not removeall then break end
+        end
+        i = i + 1
+    end
+    return c
+end
+
+--[[--
+
+对表格中每一个值执行一次指定的函数,并用函数返回值更新表格内容
+
+~~~ lua
+
+local t = {name = "dualface", comp = "chukong"}
+table.map(t, function(v, k)
+    -- 在每一个值前后添加括号
+    return "[" .. v .. "]"
+end)
+
+-- 输出修改后的表格内容
+for k, v in pairs(t) do
+    print(k, v)
+end
+
+-- 输出
+-- name [dualface]
+-- comp [chukong]
+
+~~~
+
+fn 参数指定的函数具有两个参数,并且返回一个值。原型如下:
+
+~~~ lua
+
+function map_function(value, key)
+    return value
+end
+
+~~~
+
+@param table t 表格
+@param function fn 函数
+
+]]
+function table.map(t, fn)
+    for k, v in pairs(t) do
+        t[k] = fn(v, k)
+    end
+end
+
+--[[--
+
+对表格中每一个值执行一次指定的函数,但不改变表格内容
+
+~~~ lua
+
+local t = {name = "dualface", comp = "chukong"}
+table.walk(t, function(v, k)
+    -- 输出每一个值
+    print(v)
+end)
+
+~~~
+
+fn 参数指定的函数具有两个参数,没有返回值。原型如下:
+
+~~~ lua
+
+function map_function(value, key)
+
+end
+
+~~~
+
+@param table t 表格
+@param function fn 函数
+
+]]
+function table.walk(t, fn)
+    for k,v in pairs(t) do
+        fn(v, k)
+    end
+end
+
+--[[--
+
+对表格中每一个值执行一次指定的函数,如果该函数返回 false,则对应的值会从表格中删除
+
+~~~ lua
+
+local t = {name = "dualface", comp = "chukong"}
+table.filter(t, function(v, k)
+    return v ~= "dualface" -- 当值等于 dualface 时过滤掉该值
+end)
+
+-- 输出修改后的表格内容
+for k, v in pairs(t) do
+    print(k, v)
+end
+
+-- 输出
+-- comp chukong
+
+~~~
+
+fn 参数指定的函数具有两个参数,并且返回一个 boolean 值。原型如下:
+
+~~~ lua
+
+function map_function(value, key)
+    return true or false
+end
+
+~~~
+
+@param table t 表格
+@param function fn 函数
+
+]]
+function table.filter(t, fn)
+    for k, v in pairs(t) do
+        if not fn(v, k) then t[k] = nil end
+    end
+end
+
+--[[--
+
+遍历表格,确保其中的值唯一
+
+~~~ lua
+
+local t = {"a", "a", "b", "c"} -- 重复的 a 会被过滤掉
+local n = table.unique(t)
+
+for k, v in pairs(n) do
+    print(v)
+end
+
+-- 输出
+-- a
+-- b
+-- c
+
+~~~
+
+@param table t 表格
+
+@return table 包含所有唯一值的新表格
+
+]]
+function table.unique(t)
+    local check = {}
+    local n = {}
+    for k, v in pairs(t) do
+        if not check[v] then
+            n[k] = v
+            check[v] = true
+        end
+    end
+    return n
+end
+
+-- 随机洗牌
+function table.shuffle(t)
+    local n = #t
+
+    while n >= 2 do
+        -- n is now the last pertinent index
+        local k = math.random(n) -- 1 <= k <= n
+        -- Quick swap
+        t[n], t[k] = t[k], t[n]
+        n = n - 1
+    end
+
+    return t
+end
+
+-- 切片
+function table.slice(t, begin, offset)
+    local res = {}
+
+    -- default values for range
+    local n = #t
+
+    begin = begin or 1
+    if begin < 1 or begin > n then
+        return res
+    end
+
+    offset = offset or n
+    if offset < 0 then
+        offset = n + offset + 1
+    elseif offset > n then
+        offset = n
+    end
+
+    local k = 1
+    for i = begin, begin + offset - 1 do
+        res[k] = t[i]
+        k = k + 1
+    end
+    return res
+end
+
+string._htmlspecialchars_set = {}
+string._htmlspecialchars_set["&"] = "&amp;"
+string._htmlspecialchars_set["\""] = "&quot;"
+string._htmlspecialchars_set["'"] = "&#039;"
+string._htmlspecialchars_set["<"] = "&lt;"
+string._htmlspecialchars_set[">"] = "&gt;"
+
+--[[--
+
+将特殊字符转为 HTML 转义符
+
+~~~ lua
+
+print(string.htmlspecialchars("<ABC>"))
+-- 输出 &lt;ABC&gt;
+
+~~~
+
+@param string input 输入字符串
+
+@return string 转换结果
+
+]]
+function string.htmlspecialchars(input)
+    for k, v in pairs(string._htmlspecialchars_set) do
+        input = string.gsub(input, k, v)
+    end
+    return input
+end
+
+function string.startwith(s,start)
+   return string.sub(s,1,string.len(start))==start
+end
+
+
+
+--[[--
+
+将 HTML 转义符还原为特殊字符,功能与 string.htmlspecialchars() 正好相反
+
+~~~ lua
+
+print(string.restorehtmlspecialchars("&lt;ABC&gt;"))
+-- 输出 <ABC>
+
+~~~
+
+@param string input 输入字符串
+
+@return string 转换结果
+
+]]
+function string.restorehtmlspecialchars(input)
+    for k, v in pairs(string._htmlspecialchars_set) do
+        input = string.gsub(input, v, k)
+    end
+    return input
+end
+
+--[[--
+
+将字符串中的 \n 换行符转换为 HTML 标记
+
+~~~ lua
+
+print(string.nl2br("Hello\nWorld"))
+-- 输出
+-- Hello<br />World
+
+~~~
+
+@param string input 输入字符串
+
+@return string 转换结果
+
+]]
+function string.nl2br(input)
+    return string.gsub(input, "\n", "<br />")
+end
+
+--[[--
+
+将字符串中的特殊字符和 \n 换行符转换为 HTML 转移符和标记
+
+~~~ lua
+
+print(string.nl2br("<Hello>\nWorld"))
+-- 输出
+-- &lt;Hello&gt;<br />World
+
+~~~
+
+@param string input 输入字符串
+
+@return string 转换结果
+
+]]
+function string.text2html(input)
+    input = string.gsub(input, "\t", "    ")
+    input = string.htmlspecialchars(input)
+    input = string.gsub(input, " ", "&nbsp;")
+    input = string.nl2br(input)
+    return input
+end
+
+--[[--
+
+用指定字符或字符串分割输入字符串,返回包含分割结果的数组
+
+~~~ lua
+
+local input = "Hello,World"
+local res = string.split(input, ",")
+-- res = {"Hello", "World"}
+
+local input = "Hello-+-World-+-Quick"
+local res = string.split(input, "-+-")
+-- res = {"Hello", "World", "Quick"}
+
+~~~
+
+@param string input 输入字符串
+@param string delimiter 分割标记字符或字符串
+
+@return array 包含分割结果的数组
+
+]]
+function string.split(input, delimiter)
+    input = tostring(input)
+    delimiter = tostring(delimiter)
+    if (delimiter=='') then return false end
+    local pos,arr = 0, {}
+    -- for each divider found
+    for st,sp in function() return string.find(input, delimiter, pos, true) end do
+        table.insert(arr, string.sub(input, pos, st - 1))
+        pos = sp + 1
+    end
+    table.insert(arr, string.sub(input, pos))
+    return arr
+end
+
+--[[--
+
+去除输入字符串头部的空白字符,返回结果
+
+~~~ lua
+
+local input = "  ABC"
+print(string.ltrim(input))
+-- 输出 ABC,输入字符串前面的两个空格被去掉了
+
+~~~
+
+空白字符包括:
+
+-   空格
+-   制表符 \t
+-   换行符 \n
+-   回到行首符 \r
+
+@param string input 输入字符串
+
+@return string 结果
+
+@see string.rtrim, string.trim
+
+]]
+function string.ltrim(input)
+    return string.gsub(input, "^[ \t\n\r]+", "")
+end
+
+function string.fromhex(str)
+    return (str:gsub('..', function (cc)
+        return string.char(tonumber(cc, 16))
+    end))
+end
+
+function string.tohex(str)
+    return (str:gsub('.', function (c)
+        return string.format('%02X', string.byte(c))
+    end))
+end
+
+--[[--
+
+去除输入字符串尾部的空白字符,返回结果
+
+~~~ lua
+
+local input = "ABC  "
+print(string.ltrim(input))
+-- 输出 ABC,输入字符串最后的两个空格被去掉了
+
+~~~
+
+@param string input 输入字符串
+
+@return string 结果
+
+@see string.ltrim, string.trim
+
+]]
+function string.rtrim(input)
+    return string.gsub(input, "[ \t\n\r]+$", "")
+end
+
+--[[--
+
+去掉字符串首尾的空白字符,返回结果
+
+@param string input 输入字符串
+
+@return string 结果
+
+@see string.ltrim, string.rtrim
+
+]]
+function string.trim(input)
+    input = string.gsub(input, "^[ \t\n\r]+", "")
+    return string.gsub(input, "[ \t\n\r]+$", "")
+end
+
+
+--[[--
+
+将字符串的第一个字符转为大写,返回结果
+
+~~~ lua
+
+local input = "hello"
+print(string.ucfirst(input))
+-- 输出 Hello
+
+~~~
+
+@param string input 输入字符串
+
+@return string 结果
+
+]]
+function string.ucfirst(input)
+    return string.upper(string.sub(input, 1, 1)) .. string.sub(input, 2)
+end
+
+local function urlencodechar(char)
+    return "%" .. string.format("%02X", string.byte(char))
+end
+
+--[[--
+
+将字符串转换为符合 URL 传递要求的格式,并返回转换结果
+
+~~~ lua
+
+local input = "hello world"
+print(string.urlencode(input))
+-- 输出
+-- hello%20world
+
+~~~
+
+@param string input 输入字符串
+
+@return string 转换后的结果
+
+@see string.urldecode
+
+]]
+function string.urlencode(input)
+    -- convert line endings
+    input = string.gsub(tostring(input), "\n", "\r\n")
+    -- escape all characters but alphanumeric, '.' and '-'
+    input = string.gsub(input, "([^%w%.%- ])", urlencodechar)
+    -- convert spaces to "+" symbols
+    return string.gsub(input, " ", "+")
+end
+
+--[[--
+
+将 URL 中的特殊字符还原,并返回结果
+
+~~~ lua
+
+local input = "hello%20world"
+print(string.urldecode(input))
+-- 输出
+-- hello world
+
+~~~
+
+@param string input 输入字符串
+
+@return string 转换后的结果
+
+@see string.urlencode
+
+]]
+function string.urldecode(input)
+    input = string.gsub (input, "+", " ")
+    input = string.gsub (input, "%%(%x%x)", function(h) return string.char(checknumber(h,16)) end)
+    input = string.gsub (input, "\r\n", "\n")
+    return input
+end
+
+--[[--
+
+计算 UTF8 字符串的长度,每一个中文算一个字符
+
+~~~ lua
+
+local input = "你好World"
+print(string.utf8len(input))
+-- 输出 7
+
+~~~
+
+@param string input 输入字符串
+
+@return integer 长度
+
+]]
+function string.utf8len(input)
+    local len  = string.len(input)
+    local left = len
+    local cnt  = 0
+    local arr  = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}
+    while left ~= 0 do
+        local tmp = string.byte(input, -left)
+        local i   = #arr
+        while arr[i] do
+            if tmp >= arr[i] then
+                left = left - i
+                break
+            end
+            i = i - 1
+        end
+        cnt = cnt + 1
+    end
+    return cnt
+end
+
+--[[--
+
+将数值格式化为包含千分位分隔符的字符串
+
+~~~ lua
+
+print(string.formatnumberthousands(1924235))
+-- 输出 1,924,235
+
+~~~
+
+@param number num 数值
+
+@return string 格式化结果
+
+]]
+function string.formatnumberthousands(num)
+    local formatted = tostring(checknumber(num))
+    local k
+    while true do
+        formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
+        if k == 0 then break end
+    end
+    return formatted
+end

+ 334 - 0
common/preload/inspect.lua

@@ -0,0 +1,334 @@
+local inspect ={
+  _VERSION = 'inspect.lua 3.1.0',
+  _URL     = 'http://github.com/kikito/inspect.lua',
+  _DESCRIPTION = 'human-readable representations of tables',
+  _LICENSE = [[
+    MIT LICENSE
+
+    Copyright (c) 2013 Enrique García Cota
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be included
+    in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+  ]]
+}
+
+local tostring = tostring
+
+inspect.KEY       = setmetatable({}, {__tostring = function() return 'inspect.KEY' end})
+inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end})
+
+local function rawpairs(t)
+  return next, t, nil
+end
+
+-- Apostrophizes the string if it has quotes, but not aphostrophes
+-- Otherwise, it returns a regular quoted string
+local function smartQuote(str)
+  if str:match('"') and not str:match("'") then
+    return "'" .. str .. "'"
+  end
+  return '"' .. str:gsub('"', '\\"') .. '"'
+end
+
+-- \a => '\\a', \0 => '\\0', 31 => '\31'
+local shortControlCharEscapes = {
+  ["\a"] = "\\a",  ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n",
+  ["\r"] = "\\r",  ["\t"] = "\\t", ["\v"] = "\\v"
+}
+local longControlCharEscapes = {} -- \a => nil, \0 => \000, 31 => \031
+for i=0, 31 do
+  local ch = string.char(i)
+  if not shortControlCharEscapes[ch] then
+    shortControlCharEscapes[ch] = "\\"..i
+    longControlCharEscapes[ch]  = string.format("\\%03d", i)
+  end
+end
+
+local function escape(str)
+  return (str:gsub("\\", "\\\\")
+             :gsub("(%c)%f[0-9]", longControlCharEscapes)
+             :gsub("%c", shortControlCharEscapes))
+end
+
+local function isIdentifier(str)
+  return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" )
+end
+
+local function isSequenceKey(k, sequenceLength)
+  return type(k) == 'number'
+     and 1 <= k
+     and k <= sequenceLength
+     and math.floor(k) == k
+end
+
+local defaultTypeOrders = {
+  ['number']   = 1, ['boolean']  = 2, ['string'] = 3, ['table'] = 4,
+  ['function'] = 5, ['userdata'] = 6, ['thread'] = 7
+}
+
+local function sortKeys(a, b)
+  local ta, tb = type(a), type(b)
+
+  -- strings and numbers are sorted numerically/alphabetically
+  if ta == tb and (ta == 'string' or ta == 'number') then return a < b end
+
+  local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb]
+  -- Two default types are compared according to the defaultTypeOrders table
+  if dta and dtb then return defaultTypeOrders[ta] < defaultTypeOrders[tb]
+  elseif dta     then return true  -- default types before custom ones
+  elseif dtb     then return false -- custom types after default ones
+  end
+
+  -- custom types are sorted out alphabetically
+  return ta < tb
+end
+
+-- For implementation reasons, the behavior of rawlen & # is "undefined" when
+-- tables aren't pure sequences. So we implement our own # operator.
+local function getSequenceLength(t)
+  local len = 1
+  local v = rawget(t,len)
+  while v ~= nil do
+    len = len + 1
+    v = rawget(t,len)
+  end
+  return len - 1
+end
+
+local function getNonSequentialKeys(t)
+  local keys, keysLength = {}, 0
+  local sequenceLength = getSequenceLength(t)
+  for k,_ in rawpairs(t) do
+    if not isSequenceKey(k, sequenceLength) then
+      keysLength = keysLength + 1
+      keys[keysLength] = k
+    end
+  end
+  table.sort(keys, sortKeys)
+  return keys, keysLength, sequenceLength
+end
+
+local function countTableAppearances(t, tableAppearances)
+  tableAppearances = tableAppearances or {}
+
+  if type(t) == 'table' then
+    if not tableAppearances[t] then
+      tableAppearances[t] = 1
+      for k,v in rawpairs(t) do
+        countTableAppearances(k, tableAppearances)
+        countTableAppearances(v, tableAppearances)
+      end
+      countTableAppearances(getmetatable(t), tableAppearances)
+    else
+      tableAppearances[t] = tableAppearances[t] + 1
+    end
+  end
+
+  return tableAppearances
+end
+
+local copySequence = function(s)
+  local copy, len = {}, #s
+  for i=1, len do copy[i] = s[i] end
+  return copy, len
+end
+
+local function makePath(path, ...)
+  local keys = {...}
+  local newPath, len = copySequence(path)
+  for i=1, #keys do
+    newPath[len + i] = keys[i]
+  end
+  return newPath
+end
+
+local function processRecursive(process, item, path, visited)
+  if item == nil then return nil end
+  if visited[item] then return visited[item] end
+
+  local processed = process(item, path)
+  if type(processed) == 'table' then
+    local processedCopy = {}
+    visited[item] = processedCopy
+    local processedKey
+
+    for k,v in rawpairs(processed) do
+      processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited)
+      if processedKey ~= nil then
+        processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)
+      end
+    end
+
+    local mt  = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
+    if type(mt) ~= 'table' then mt = nil end -- ignore not nil/table __metatable field
+    setmetatable(processedCopy, mt)
+    processed = processedCopy
+  end
+  return processed
+end
+
+
+
+-------------------------------------------------------------------
+
+local Inspector = {}
+local Inspector_mt = {__index = Inspector}
+
+function Inspector:puts(...)
+  local args   = {...}
+  local buffer = self.buffer
+  local len    = #buffer
+  for i=1, #args do
+    len = len + 1
+    buffer[len] = args[i]
+  end
+end
+
+function Inspector:down(f)
+  self.level = self.level + 1
+  f()
+  self.level = self.level - 1
+end
+
+function Inspector:tabify()
+  self:puts(self.newline, string.rep(self.indent, self.level))
+end
+
+function Inspector:alreadyVisited(v)
+  return self.ids[v] ~= nil
+end
+
+function Inspector:getId(v)
+  local id = self.ids[v]
+  if not id then
+    local tv = type(v)
+    id              = (self.maxIds[tv] or 0) + 1
+    self.maxIds[tv] = id
+    self.ids[v]     = id
+  end
+  return tostring(id)
+end
+
+function Inspector:putKey(k)
+  if isIdentifier(k) then return self:puts(k) end
+  self:puts("[")
+  self:putValue(k)
+  self:puts("]")
+end
+
+function Inspector:putTable(t)
+  if t == inspect.KEY or t == inspect.METATABLE then
+    self:puts(tostring(t))
+  elseif self:alreadyVisited(t) then
+    self:puts('<table ', self:getId(t), '>')
+  elseif self.level >= self.depth then
+    self:puts('{...}')
+  else
+    if self.tableAppearances[t] > 1 then self:puts('<', self:getId(t), '>') end
+
+    local nonSequentialKeys, nonSequentialKeysLength, sequenceLength = getNonSequentialKeys(t)
+    local mt                = getmetatable(t)
+
+    self:puts('{')
+    self:down(function()
+      local count = 0
+      for i=1, sequenceLength do
+        if count > 0 then self:puts(',') end
+        self:puts(' ')
+        self:putValue(t[i])
+        count = count + 1
+      end
+
+      for i=1, nonSequentialKeysLength do
+        local k = nonSequentialKeys[i]
+        if count > 0 then self:puts(',') end
+        self:tabify()
+        self:putKey(k)
+        self:puts(' = ')
+        self:putValue(t[k])
+        count = count + 1
+      end
+
+      if type(mt) == 'table' then
+        if count > 0 then self:puts(',') end
+        self:tabify()
+        self:puts('<metatable> = ')
+        self:putValue(mt)
+      end
+    end)
+
+    if nonSequentialKeysLength > 0 or type(mt) == 'table' then -- result is multi-lined. Justify closing }
+      self:tabify()
+    elseif sequenceLength > 0 then -- array tables have one extra space before closing }
+      self:puts(' ')
+    end
+
+    self:puts('}')
+  end
+end
+
+function Inspector:putValue(v)
+  local tv = type(v)
+
+  if tv == 'string' then
+    self:puts(smartQuote(escape(v)))
+  elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or
+         tv == 'cdata' or tv == 'ctype' then
+    self:puts(tostring(v))
+  elseif tv == 'table' then
+    self:putTable(v)
+  else
+    self:puts('<', tv, ' ', self:getId(v), '>')
+  end
+end
+
+-------------------------------------------------------------------
+
+function inspect.inspect(root, options)
+  options       = options or {}
+
+  local depth   = options.depth   or math.huge
+  local newline = options.newline or '\n'
+  local indent  = options.indent  or '  '
+  local process = options.process
+
+  if process then
+    root = processRecursive(process, root, {}, {})
+  end
+
+  local inspector = setmetatable({
+    depth            = depth,
+    level            = 0,
+    buffer           = {},
+    ids              = {},
+    maxIds           = {},
+    newline          = newline,
+    indent           = indent,
+    tableAppearances = countTableAppearances(root)
+  }, Inspector_mt)
+
+  inspector:putValue(root)
+
+  return table.concat(inspector.buffer)
+end
+
+setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })
+
+return inspect
+

+ 41 - 0
common/preload/inspect_api.lua

@@ -0,0 +1,41 @@
+local inspect_lib = require "inspect"
+
+function inspect(value)
+    return inspect_lib(value, {
+    process = function(item, path)
+        if type(item) == "function" then
+            return nil
+        end
+
+        if path[#path] == inspect_lib.METATABLE then
+            return nil
+        end
+
+        return item
+    end,
+    newline = " ",
+    indent = ""
+})
+end
+
+function DUMP(value)
+    return inspect_lib(value, {
+    process = function(item, path)
+        return item
+    end,
+    newline = " ",
+    indent = ""
+})
+end
+
+function TraceBack()
+    for level = 1, math.huge do
+        local info = debug.getinfo(level, "nSl")
+        if not info then break end
+        if info.what == "C" then -- is a C function?
+            DEBUG(level, "C function")
+        else
+            DEBUG(info.name,string.format("%d, [%s] : %d", level, info.short_src, info.currentline))
+        end
+    end
+end

+ 56 - 0
common/preload/logger_api.lua

@@ -0,0 +1,56 @@
+local skynet = require "skynet"
+-- require "skynet.manager"
+
+
+-- 日志级别
+local log_level = {
+  LOG_DEFAULT   = 1,
+  LOG_TRACE     = 1,
+  LOG_DEBUG     = 2,
+  LOG_INFO      = 3,
+  LOG_WARN      = 4,
+  LOG_ERROR     = 5,
+  LOG_FATAL     = 6,
+}
+
+local defaultLevel = log_level.LOG_DEBUG
+local prefix = ""
+function LOG_PREFIX(pre)
+  prefix = "[" .. pre .. "]"
+end
+
+--日志 --
+local function logger(str, level, color)
+  return function (...)
+    if level >= defaultLevel then
+        local info = table.pack(...)
+        info[#info+1] = "\x1b[0m"
+        skynet.error(string.format("%s%s%s", color, prefix, str), table.unpack(info))
+    end
+  end
+end
+
+
+local M = {
+  TRACE = logger("[trace]", log_level.LOG_TRACE, "\x1b[35m"),
+  DEBUG = logger("[debug]", log_level.LOG_DEBUG, "\x1b[32m"),
+  INFO  = logger("[info]", log_level.LOG_INFO, "\x1b[34m"),
+  WARN  = logger("[warning]", log_level.LOG_WARN, "\x1b[33m"),
+  ERROR   = logger("[error]", log_level.LOG_ERROR, "\x1b[31m"),
+  FATAL = logger("[fatal]", log_level.LOG_FATAL,"\x1b[31m")
+}
+
+-- 错误日志 --
+
+setmetatable(M, {
+  __call = function(t)
+    for k, v in pairs(t) do
+      _G[k] = v
+    end
+  end,
+})
+
+M()
+
+return M
+

+ 8 - 0
etc/config.path

@@ -0,0 +1,8 @@
+root = "../../"
+proj_root = "../"
+lualoader = root .. "skynet/lualib/loader.lua"
+
+luaservice = proj_root.."common/?.lua;" .. "../service/?.lua;" .. "../service/?/init.lua;" .. root .. "skynet/service/?.lua;" .. proj_root .. "common/dbproxy/?.lua;" .. proj_root .. "common/dbproxy/mysqldb/?.lua;" .. proj_root .. "common/dbproxy/mongodb/?.lua;" .. proj_root .. "common/dbproxy/redisdb/?.lua;"
+
+lua_path = proj_root .. "common/dbproxy/?.lua;" .. proj_root .. "common/preload/?.lua;" .. "../luaclib_src/lua-protobuf-master/?.lua;" .. "../etc/?.lua;" .. "../msg/?.lua;" .. "../lualib/?.lua;" .. "../lualib/?/init.lua;" .. root .. "lualib/?.lua;" .. root .. "skynet/lualib/?.lua;" .. root .. "skynet/lualib/?/init.lua"
+lua_cpath = "../luaclib_src/lua-protobuf-master/?.so;" .. root .. "luaclib/?.so;" .. root .. "skynet/luaclib/?.so;" .. "../luaclib/?.so;"

+ 17 - 0
etc/config_node1

@@ -0,0 +1,17 @@
+--必须配置
+include "config.path"
+thread = 8                          --启用多少个工作线程
+cpath = root.."skynet/cservice/?.so"    --用C编写的服务模块的位置
+bootstrap = "snlua bootstrap"       --启动的第一个服务
+preload = root .. "jl_tg_config_back/preload.lua" 
+--bootstrap配置项
+start = "main"                      --主程序入口
+harbor = 0                          --不使用主从节点模式
+
+--后台模式
+--daemon = "./jl_tg_config_back.pid"
+logger = "userlog"
+logpath = "."
+logservice = "snlua"
+--节点
+node = "node1"

+ 18 - 0
etc/prodconfig

@@ -0,0 +1,18 @@
+--必须配置
+include "config.path"
+thread = 8                          --启用多少个工作线程
+cpath = root.."skynet/cservice/?.so"    --用C编写的服务模块的位置
+bootstrap = "snlua bootstrap"       --启动的第一个服务
+preload = root .. "jl_tg_config_back/preload.lua" 
+--bootstrap配置项
+start = "main"                      --主程序入口
+harbor = 0                          --不使用主从节点模式
+
+enablessl = true
+--后台模式
+daemon = "./jl_tg_config_back.pid"
+logger = "userlog"
+logpath = "."
+logservice = "snlua"
+--节点
+node = "node1"

+ 87 - 0
lualib/service.lua

@@ -0,0 +1,87 @@
+local skynet = require "skynet"
+local cluster = require "skynet.cluster"
+
+local M = {
+	--类型和id
+	name = "",
+	id = 0,
+	--回调函数
+	exit = nil,
+	init = nil,
+	--分发方法
+	resp = {},
+}
+
+--[[
+function exit_dispatch()
+	if M.exit then
+		M.exit()
+	end
+	skynet.ret()
+	skynet.exit()
+end
+--]]
+
+function traceback(err)
+	skynet.error(tostring(err))
+	skynet.error(debug.traceback())
+end
+
+local dispatch = function(session, address, cmd, ...)
+	local fun = M.resp[cmd]
+	if not fun then
+		skynet.ret()
+		return
+	end
+	
+	local ret = table.pack(xpcall(fun, traceback, address, ...))
+	local isok = ret[1]
+	
+	if not isok then
+		skynet.ret()
+		return
+	end
+
+	skynet.retpack(table.unpack(ret,2))
+end
+
+function init()
+	skynet.dispatch("lua", dispatch)
+	if M.init then
+		M.init()
+	end
+end
+
+function M.call(node, srv, ...)
+	local mynode = skynet.getenv("node")
+	if node == mynode then
+		return skynet.call(srv, "lua", ...)
+	else
+		return cluster.call(node, srv, ...)
+	end
+end
+
+function M.send(node, srv, ...)
+	local mynode = skynet.getenv("node")
+	if node == mynode then
+		return skynet.send(srv, "lua", ...)
+	else
+		return cluster.send(node, srv, ...)
+	end
+end
+
+function M.start(name, id, ...)
+	M.name = name
+	M.id = tonumber(id)
+	skynet.start(init)
+end
+
+M.resp.exit = function()
+    if M.exit then
+        M.exit()
+    end
+    skynet.ret()
+    skynet.exit()
+end
+
+return M

+ 129 - 0
lualib/tools.lua

@@ -0,0 +1,129 @@
+
+local sockethelper = require "http.sockethelper"
+local skynet = require "skynet"
+local httpd = require "http.httpd"
+local cjson = require "cjson"
+local crypt = require "client.crypt"
+local M = {
+
+}
+local headers = {
+    ['Content-Type'] = 'application/x-www-form-urlencoded',
+    ['Access-Control-Allow-Origin'] = '*', -- 这里写允许访问的域名就可以了,允许所有人访问的话就写*
+    ['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept',
+    ['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS',
+ }
+
+M.read_request = function(id)
+     -- limit request body size to 8192 (you can pass nil to unlimit)
+        -- 一般的业务不需要处理大量上行数据,为了防止攻击,做了一个 8K 限制。这个限制可以去掉。
+    -- local code, url, method, header, body = httpd.read_request(sockethelper.readfunc(id), 8192)
+    local code, url, method, header, body = httpd.read_request(sockethelper.readfunc(id))
+    return {code=code,url=url,method=method,header=header,body=body}
+end
+
+M.response = function(id, code,msg,...)
+    local ok, err = httpd.write_response(sockethelper.writefunc(id),code, msg,...)
+    if not ok then
+        -- if err == sockethelper.socket_error , that means socket closed.
+        skynet.error(string.format("fd = %d, %s", id, err))
+    end
+end
+
+
+
+--检查工具返回的字段是否缺失
+M.checkData= function(origin,table)
+    for _, field in pairs(origin) do
+        if not table[field] then
+            return false,field
+        end
+    end
+    return true
+end
+
+M.dump = function(res, tab)
+    tab = tab or 0
+    if(tab == 0) then
+        skynet.error("............dump...........")
+    end
+    
+    if type(res) == "table" then
+        skynet.error(string.rep("\t", tab).."{")
+        for k,v in pairs(res) do
+            if type(v) == "table" then
+                skynet.error(k.."=")
+                M.dump(v, tab + 1)
+             else
+                skynet.error(string.rep("\t", tab), k, "=", v, ",")
+            end
+        end
+        skynet.error(string.rep("\t", tab).."}")
+    else
+        skynet.error(string.rep("\t", tab) , res)
+    end
+end
+
+M.getDbResData = function(res)
+    local tab = {}
+    if #res >1 then
+        local i = 1;
+        for k, v in pairs(res) do
+            -- skynet.error("Row " .. k)
+            local tab_1 = {}
+            for field, value in pairs(v) do
+                tab_1[field] = value
+                -- skynet.error(field .. ": " .. value)
+            end
+            tab[i] = tab_1;
+            i=i+1;
+        end
+    else
+        for k, v in pairs(res) do
+            for field, value in pairs(v) do
+                tab[field] = value
+            end
+        end
+    end
+    return tab
+end
+
+M.tokenEncode = function(user_data)
+    return crypt.base64encode(user_data)
+end
+
+M.tokenDecode = function(base_str)
+    return crypt.base64decode(base_str)
+end
+
+M.base64decode = function(base_str)
+    return crypt.base64decode(base_str)
+end
+
+M.base64encode = function(base_str)
+    return crypt.base64encode(base_str)
+end
+
+M.sort_table_by_keys = function(tbl)
+    table.sort(tbl)
+    return tbl
+    -- local keys = {}
+    -- -- 提取所有键
+    -- for key in pairs(tbl) do
+    --     table.insert(keys, key)
+    -- end
+    
+    -- -- 使用table.sort对键进行字典序排序
+    -- table.sort(keys, function(a, b)
+    --     return a < b
+    -- end)
+    
+    -- -- 创建一个新table,根据排序后的键来组织内容
+    -- local sorted_tbl = {}
+    -- for _, key in ipairs(keys) do
+    --     sorted_tbl[key] = tbl[key]
+    -- end
+    
+    -- return sorted_tbl
+end
+return M

+ 13 - 0
preload.lua

@@ -0,0 +1,13 @@
+-- This file will execute before every lua service start
+-- See config
+
+print("PRELOAD", ...)
+PROJ_ROOT="../jl_config_back"
+
+require "logger_api"
+require "inspect_api"
+require "functions"
+
+math.randomseed(tostring(os.time()):reverse():sub(1, 6))
+
+collectgarbage()

+ 221 - 0
service/agent.lua

@@ -0,0 +1,221 @@
+local skynet = require "skynet"
+local socket = require "skynet.socket"
+local cjson = require "cjson"
+local tools = require "tools"
+local websocket = require "http.websocket"
+local mysqldbx = require "mysqldbx"
+local closing = false
+local isRunTask = false --是否在工作
+local isActive = false --是否激活
+local handle = {}
+local M = {}
+local RECV_TASK = {}
+local AGENT_ID = 0
+function handle.connect(id)
+    print("ws connect from: " .. tostring(id))
+end
+
+function handle.handshake(id, header, url)
+    local addr = websocket.addrinfo(id)
+    print("ws handshake from: " .. tostring(id), "url", url, "addr:", addr)
+    print("----header-----")
+    for k,v in pairs(header) do
+        print(k,v)
+    end
+    print("--------------")
+end
+--工人已完成
+function  M.finish_task(id, msg)
+    skynet.error("工人已完成:",cjson.encode(msg['data']))
+    isRunTask = false --等待老板发送新任务
+end
+--工人未完成
+function  M.unfinish_task(id, msg)
+    skynet.error("工人未完成:",msg['data'].error_info)
+    isRunTask = false
+end
+--工人准备工作
+function  M.status_task(id, msg)
+    skynet.error("工人准备工作:",id,msg)
+    AGENT_ID = id
+    isActive = true
+
+    skynet.fork(function()
+        RECV_TASK.updateAppConfig()
+        -- skynet.sleep(200)
+        RECV_TASK.updateFilterConfig()
+        -- skynet.sleep(200)
+        RECV_TASK.updateMainConfig()
+        -- skynet.sleep(200)
+        RECV_TASK.updatePlatformConfig()
+        RECV_TASK.updateFqKeyList()
+        RECV_TASK.updateFqMfKeyList()
+        RECV_TASK.updateYwKeyList()
+        RECV_TASK.updateBlackBooks()
+        RECV_TASK.getPullDataConfig()
+    end)
+
+end
+
+function handle.message(id, msg, type)
+    if msg == "ping" then
+        websocket.write(id,"pong")
+        return
+    end
+    msg = cjson.decode(msg)
+    if M[msg.cmd] then
+        M[msg.cmd](id,msg)
+    else
+        skynet.error("no find:",msg)
+    end
+
+end
+
+function handle.ping(id)
+    print("ws ping from: " .. tostring(id) .. "\n")
+end
+
+function handle.pong(id)
+    print("ws pong from: " .. tostring(id))
+end
+
+function handle.close(id, code, reason)
+    print("ws close from: " .. tostring(id), code, reason)
+    AGENT_ID = 0
+    isRunTask = false
+    isActive = false
+    closing = true
+end
+
+function handle.error(id)
+    print("ws error from: " .. tostring(id))
+end
+
+local connect = function(fd, addr)
+    if closing then
+        return
+    end
+    local protocol = "ws"
+    local ok, err = websocket.accept(fd, handle, protocol, addr)
+    if not ok then
+        skynet.error(err)
+    else
+        print("websocket connect!")
+    end
+end
+
+function RECV_TASK.isActive()
+    return isActive
+end
+
+function RECV_TASK.isRunStak()
+    return isRunTask
+end
+
+function RECV_TASK.startOneTask(msg_body)
+    skynet.error(" 收到老板的任务:",msg_body,AGENT_ID)
+    local body = cjson.decode(msg_body)
+    if AGENT_ID~=0 then
+        isRunTask = true --工人进入工作状态
+        websocket.write(AGENT_ID, cjson.encode({cmd="find_book",dy_url=body.dy_url}))
+    end
+end
+
+function RECV_TASK.updatePullConig(msg_body)
+    if AGENT_ID~=0 then
+        isRunTask = true --工人进入工作状态
+        websocket.write(AGENT_ID, cjson.encode({cmd="updatePullConig"}))
+    end
+end
+
+function RECV_TASK.getPullDataConfig(msg_body)
+    if AGENT_ID~=0 then
+        isRunTask = true --工人进入工作状态
+        websocket.write(AGENT_ID, cjson.encode({cmd="getPullDataConfig"}))
+    end
+end
+
+function RECV_TASK.updateAppConfig(msg_body)
+    -- local body = cjson.decode(msg_body)
+    if AGENT_ID~=0 then
+        isRunTask = true --工人进入工作状态
+        websocket.write(AGENT_ID, cjson.encode({cmd="updateAppConfig"}))
+    end
+end
+
+function RECV_TASK.updatePlatformConfig(msg_body)
+    if AGENT_ID~=0 then
+        isRunTask = true --工人进入工作状态
+        websocket.write(AGENT_ID, cjson.encode({cmd="updatePlatformConfig"}))
+    end
+end
+
+function RECV_TASK.updateMainConfig(msg_body)
+    if AGENT_ID~=0 then
+        isRunTask = true --工人进入工作状态
+        websocket.write(AGENT_ID, cjson.encode({cmd="updateMainConfig"}))
+    end
+end
+
+function RECV_TASK.updateFilterConfig(msg_body)
+    if AGENT_ID~=0 then
+        isRunTask = true --工人进入工作状态
+        websocket.write(AGENT_ID, cjson.encode({cmd="updateFilterConfig"}))
+    end
+end
+
+function RECV_TASK.addMain(msg_body)
+    if AGENT_ID~=0 then
+        isRunTask = true --工人进入工作状态
+        websocket.write(AGENT_ID, cjson.encode({cmd="addMain",data=msg_body}))
+    end
+end
+
+function RECV_TASK.updateFqKeyList(msg_body)
+    if AGENT_ID~=0 then
+        isRunTask = true --工人进入工作状态
+        websocket.write(AGENT_ID, cjson.encode({cmd="updateFqKeyList",data=msg_body}))
+    end
+end
+
+function RECV_TASK.updateFqMfKeyList(msg_body)
+    if AGENT_ID~=0 then
+        isRunTask = true --工人进入工作状态
+        websocket.write(AGENT_ID, cjson.encode({cmd="updateFqMfKeyList",data=msg_body}))
+    end
+end
+
+function RECV_TASK.updateYwKeyList(msg_body)
+    if AGENT_ID~=0 then
+        isRunTask = true --工人进入工作状态
+        websocket.write(AGENT_ID, cjson.encode({cmd="updateYwKeyList",data=msg_body}))
+    end
+end
+
+function RECV_TASK.updateBlackBooks(msg_body)
+    if AGENT_ID~=0 then
+        isRunTask = true --工人进入工作状态
+        websocket.write(AGENT_ID, cjson.encode({cmd="updateBlackBooks",data=msg_body}))
+    end
+end
+
+function RECV_TASK.syncMain(msg_body)
+    if AGENT_ID~=0 then
+        isRunTask = true --工人进入工作状态
+        websocket.write(AGENT_ID, cjson.encode({cmd="syncMain",data=msg_body}))
+    end
+end
+
+local dispatch = function(session, address,id, addr,cmd,...)
+    if(cmd=="connect") then
+        connect(id,addr)
+    else
+        local f = assert(RECV_TASK[cmd], cmd .. " not found")
+        skynet.retpack(f(...))
+    end
+end
+skynet.start(function()
+    skynet.dispatch("lua", dispatch)
+end)
+
+

+ 171 - 0
service/agent_manager.lua

@@ -0,0 +1,171 @@
+local skynet = require "skynet"
+local sockethelper = require "http.sockethelper"
+local socket = require "skynet.socket"
+local runconfig = require "run_config"
+local tools = require "tools"
+local CMD = {}
+local agents = {}
+function traceback(err)
+	skynet.error(tostring(err))
+	skynet.error(debug.traceback())
+end
+local dispatch = function(session, address, cmd, ...)
+    local fun = CMD[cmd]
+	if not fun then
+		skynet.ret()
+		return
+	end
+    local ret = table.pack(xpcall(fun, traceback, address, ...))
+	local isok = ret[1]
+	if not isok then
+		skynet.ret()
+		return
+	end
+	skynet.retpack(table.unpack(ret,2))
+end
+
+function getOneAgent()
+    -- for i = 1, #agents, 1 do
+	-- 	local isActive =  skynet.call(agents[i],"lua",nil,nil,"isActive")
+	-- 	if isActive then
+	-- 		local isRunTask = skynet.call(agents[i],"lua",nil,nil,"isRunStak")
+	-- 		if(isRunTask==false) then
+	-- 			return agents[i]
+	-- 		end
+	-- 	end
+    -- end
+	local isActive =  skynet.call(agents[1],"lua",nil,nil,"isActive")
+	if isActive then
+		return agents[1]
+	end
+    return nil
+end
+--更新筛选配置
+function CMD.updateFilterConfig(_,msg_body) 
+    local agent = getOneAgent()
+    if agent~=nil then
+        skynet.call(agent,"lua",nil,nil,"updateFilterConfig",msg_body)
+    else
+        skynet.error("把任务放到队列")
+    end
+end
+
+--更新主体配置
+function CMD.updateMainConfig(_,msg_body) 
+    local agent = getOneAgent()
+    if agent~=nil then
+        skynet.call(agent,"lua",nil,nil,"updateMainConfig",msg_body)
+    else
+        skynet.error("把任务放到队列")
+    end
+end
+
+
+--更新App配置
+function CMD.updateAppConfig(_,msg_body) 
+    local agent = getOneAgent()
+    if agent~=nil then
+        skynet.call(agent,"lua",nil,nil,"updateAppConfig",msg_body)
+    else
+        skynet.error("把任务放到队列")
+    end
+end
+
+
+--更新平台配置
+function CMD.updatePlatformConfig(_,msg_body) 
+    local agent = getOneAgent()
+    if agent~=nil then
+        skynet.call(agent,"lua",nil,nil,"updatePlatformConfig",msg_body)
+    else
+        skynet.error("把任务放到队列")
+    end
+end
+
+
+--添加主体
+function CMD.addMain(_,msg_body) 
+    local agent = getOneAgent()
+    if agent~=nil then
+        skynet.call(agent,"lua",nil,nil,"addMain",msg_body)
+    else
+        skynet.error("把任务放到队列")
+    end
+end
+
+
+--更新番茄key列表
+function CMD.updateFqKeyList(_,msg_body) 
+    local agent = getOneAgent()
+    if agent~=nil then
+        skynet.call(agent,"lua",nil,nil,"updateFqKeyList",msg_body)
+    else
+        skynet.error("把任务放到队列")
+    end
+end
+
+function CMD.updateFqMfKeyList(_,msg_body)
+    local agent = getOneAgent()
+    if agent~=nil then
+        skynet.call(agent,"lua",nil,nil,"updateFqMfKeyList",msg_body)
+    else
+        skynet.error("把任务放到队列")
+    end
+end
+
+function CMD.updateYwKeyList(_,msg_body)
+    local agent = getOneAgent()
+    if agent~=nil then
+        skynet.call(agent,"lua",nil,nil,"updateYwKeyList",msg_body)
+    else
+        skynet.error("把任务放到队列")
+    end
+end
+
+--更新黑名单的书
+function CMD.updateBlackBooks(_,msg_body) 
+    local agent = getOneAgent()
+    if agent~=nil then
+        skynet.call(agent,"lua",nil,nil,"updateBlackBooks",msg_body)
+    else
+        skynet.error("把任务放到队列")
+    end
+end
+
+--更新拉取配置
+function CMD.updatePullConig(_,msg_body) 
+    local agent = getOneAgent()
+    if agent~=nil then
+        skynet.call(agent,"lua",nil,nil,"updatePullConig",msg_body)
+    else
+        skynet.error("把任务放到队列")
+    end
+end
+
+--同步主体
+function CMD.syncMain(_,msg_body) 
+    local agent = getOneAgent()
+    if agent~=nil then
+        skynet.call(agent,"lua",nil,nil,"syncMain",msg_body)
+    else
+        skynet.error("把任务放到队列")
+    end
+end
+
+skynet.start(function()
+	local protocol = "ws" 
+	-- for i= 1, 3 do --开启30个服务用来接收消息
+	-- 	agents[i] = skynet.newservice("agent", "agent", protocol)
+	-- end
+	agents[1] = skynet.newservice("agent", "agent", protocol)
+	local balance = 1
+	local id = socket.listen("0.0.0.0",runconfig.wsProt )
+	socket.start(id , function(id, addr)
+		skynet.send(agents[balance], "lua", id,addr,"connect")
+		balance = balance + 1
+		if balance > #agents then
+			balance = 1
+		end
+	end)
+    skynet.dispatch("lua", dispatch)
+end)

+ 45 - 0
service/backmgr/ad_convert_type.lua

@@ -0,0 +1,45 @@
+--广告转化类型
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+
+
+function M.add_ad_convert_type(msg_body)
+    local isok ,key =  tools.checkData({"type","name"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("INSERT INTO `ad_convert_type` (name,type)  VALUES ('%s',%d)",msg_body.name,msg_body.type)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+
+function M.modify_ad_convert_type(msg_body)
+    local isok ,key =  tools.checkData({"type","name","id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE  ad_convert_type SET type = %d , name = '%s' WHERE id = %d ",msg_body.type,msg_body.name,msg_body.id)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+function M.search_ad_convert_type(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    
+    local sql = "SELECT * FROM ad_convert_type "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldbx.query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM ad_convert_type "
+    local total = mysqldbx.query(sql)
+    return true,list,total[1].total
+end
+
+return M

+ 58 - 0
service/backmgr/aweme_auth_list.lua

@@ -0,0 +1,58 @@
+--抖音授权
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local md5 =	require	"md5"
+
+
+function M.add_aweme_auth_list(msg_body)
+    local isok ,key =  tools.checkData({"aweme_id","aweme_name"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local sql  = string.format("INSERT INTO `aweme_auth_list` (aweme_id,aweme_name)  VALUES ('%s','%s')",
+    msg_body.aweme_id,msg_body.aweme_name)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+function M.modify_aweme_auth_list(msg_body)
+    local isok ,key =  tools.checkData({"aweme_id","aweme_name"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE  `aweme_auth_list` SET aweme_id = '%s' ,aweme_name = '%s'  WHERE id = %d ",
+    msg_body.aweme_id,msg_body.aweme_name,msg_body.id)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+function M.search_aweme_auth_list(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    
+    -- local content_param = ""
+    -- if msg_body.content~="" then
+    --     content_param =  string.format(" AND  ( title LIKE CONCAT( '%%%s%%')) ",msg_body.content)
+    -- end
+
+    -- local create_date_param = ""
+    -- if msg_body.start_create_time~="" and msg_body.end_create_time~="" then
+    --     create_date_param = " AND DATE(create_time) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_create_time / 1000) .. ")) AND DATE(create_time) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_create_time / 1000) .. "))"
+    -- end
+
+    local sql = "SELECT * FROM aweme_auth_list WHERE 1=1 "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldbx.query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM aweme_auth_list  WHERE 1=1 "
+    local total = mysqldbx.query(sql)
+    return true,list,total[1].total
+end
+
+return M

+ 12 - 0
service/backmgr/back_response.lua

@@ -0,0 +1,12 @@
+local skynet = require "skynet"
+local cjson = require "cjson"
+local crypt = require "client.crypt"
+local tools = require "tools"
+local M = {
+
+}
+
+M.response = function()
+    
+end
+return M

+ 93 - 0
service/backmgr/book_black_list.lua

@@ -0,0 +1,93 @@
+--黑名单
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+function M.get_all_black_books()
+    local sql = "SELECT * FROM black_list "
+    local res = mysqldbx.query(sql)
+    return true,res
+end
+function M.add_book(msg_body)
+    local isok ,key =  tools.checkData({"product_id","product_name"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("SELECT * FROM black_list WHERE product_id = '%s' LIMIT 1", msg_body.product_id)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res > 0 then
+        return false ,"product_id :"..msg_body.product_id.." 已存在!"
+    end
+    sql = string.format("INSERT INTO `black_list` (product_id,product_name)  VALUES ('%s','%s')",msg_body.product_id,msg_body.product_name)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateBlackBooks"}))
+    return true, {}
+end
+
+function M.delete_book(msg_body)
+    local isok ,key =  tools.checkData({"product_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("DELETE FROM black_list WHERE product_id = '%s' ",msg_body.product_id)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateBlackBooks"}))
+    return true, {}
+end
+
+function M.is_black_book(msg_body)
+    local isok ,key =  tools.checkData({"product_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("SELECT * FROM black_list WHERE product_id = '%s' LIMIT 1", msg_body.product_id)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    return true, {is_black_book = #res > 0}
+end
+
+function M.search_book_list(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number","product_id","product_name"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    local isFirst = false
+    local product_param = ""
+
+    if msg_body.product_id~="" then
+        isFirst = true
+        product_param =string.format(" product_id = '%s' ",msg_body.product_id)
+    end
+    local product_name_param = ""
+    if msg_body.product_name~="" then
+        if isFirst ==true then
+            product_name_param = string.format("AND product_name = '%s' ",msg_body.product_name)
+        else
+            isFirst = true
+            product_name_param = string.format(" product_name = '%s' ",msg_body.product_name)
+        end
+    end
+
+    local param = product_param..product_name_param
+
+    if param ~= "" then
+        param = " WHERE "..param
+    end
+
+    local sql = "SELECT * FROM black_list "..param..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+   
+    local list = mysqldbx.query(sql)
+
+    sql = "SELECT   COUNT(*) AS total  FROM black_list "..param
+
+    local total = mysqldbx.query(sql)
+
+    return true,list,total[1].total
+end
+
+return M

+ 67 - 0
service/backmgr/checks.lua

@@ -0,0 +1,67 @@
+--检测配置
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local mysql = require "skynet.db.mysql"
+local config = require "run_config"
+local cjson = require "cjson"
+local db
+local mysqldtaskbx = {}
+-- SELECT * FROM products WHERE JSON_CONTAINS(main_id_info, '111') LIMIT 100
+function M.set_products_main_id(msg_body)
+    local isok ,key =  tools.checkData({"main_id_info","id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE  products SET main_id_info = '%s' WHERE id = %d ",cjson.encode(msg_body.main_id_info),msg_body.id)
+    mysqldtaskbx.Singleton().query(sql)
+    return true, {}
+end
+
+function M.search_products(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    local sql = "SELECT * FROM products "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldtaskbx.Singleton().query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM products "
+    local total = mysqldtaskbx.Singleton().query(sql)
+    return true,list,total[1].total
+end
+
+function mysqldtaskbx.start()
+    local function on_connect(db)
+        db:query("set charset utf8mb4");
+    end
+    local conf = config.db_cnf.book_server.mysqldb_checks_cnf
+    db = mysql.connect{
+        host=conf.ip,
+        port=conf.port,
+        database=conf.db,
+        user=conf.user,
+        password=conf.password,
+        charset="utf8mb4",
+        max_packet_size = 1024 * 1024,
+        on_connect = on_connect
+    }
+    if not db then
+       skynet.error("mysql connect fail")
+    end
+end
+
+function mysqldtaskbx.Singleton()
+    if db == nil then
+        mysqldtaskbx.start()
+    end
+    return mysqldtaskbx
+end
+function mysqldtaskbx.query(sql)
+    return db:query(sql)
+end
+
+return M

+ 64 - 0
service/backmgr/data_manager.lua

@@ -0,0 +1,64 @@
+local M = {}
+local redisdbx = require "redisdbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local mysqldbx = require "mysqldbx"
+local cjson = require "cjson"
+function M.set(msg_body)
+    local isok ,key =  tools.checkData({"key","value"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    -- local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    redisdbx.exec("set",nil,"xs-"..msg_body.key,msg_body.value)
+    return true, {}
+end
+
+
+function M.get(msg_body)
+    local isok ,key =  tools.checkData({"key"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local res = redisdbx.exec("get",nil,"xs-"..msg_body.key)
+    return true, res
+end
+
+
+
+function M.db_set(msg_body)
+    local isok ,key =  tools.checkData({"key","value"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local sql = string.format("SELECT * FROM data_manager WHERE db_key = '%s' LIMIT 1", msg_body.key)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    skynet.error("sql:",sql)
+    if #res > 0 then
+        sql = string.format("UPDATE  data_manager SET db_value = '%s' WHERE db_key = '%s' ",cjson.encode(msg_body.value),msg_body.key)
+    else
+        sql = string.format("INSERT INTO `data_manager` (db_key,db_value)  VALUES ('%s','%s')",msg_body.key,cjson.encode(msg_body.value))
+    end
+    skynet.error("sql:",sql)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+
+function M.db_get(msg_body)
+    local isok ,key =  tools.checkData({"key"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("SELECT * FROM data_manager WHERE db_key = '%s' LIMIT 1", msg_body.key)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res > 0 then
+        res = res[1]
+    end
+    return true, res
+end
+
+return M

+ 154 - 0
service/backmgr/filter_data.lua

@@ -0,0 +1,154 @@
+--筛选数据
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+function M.search_filter_data(msg_body)
+    local isok ,key =  tools.checkData({"material_sync_status","video_id","tg_platform_id","page_size","page_number",
+    "d_z","comment","collect","forward","product_id","source","start_publish_time","end_publish_time","start_create_time","end_create_time"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+    
+    local material_sync_status_param = ""
+    if msg_body.material_sync_status~="" then
+        material_sync_status_param =   " AND material_sync_status = ".. msg_body.material_sync_status
+    end
+
+
+    local tg_platform_id_param = ""
+    if msg_body.tg_platform_id~="" then
+        tg_platform_id_param =  " AND tg_platform_id = "..msg_body.tg_platform_id.." "
+    end
+
+
+    local product_param = ""
+    if msg_body.product_id~="" then
+        product_param =  string.format(" AND book_id = '%s' ",msg_body.product_id)
+    end
+
+    local video_id_param = ""
+    if msg_body.video_id~="" then
+        video_id_param =  string.format(" AND video_id = '%s' ",msg_body.video_id)
+    end
+
+    local source_param = ""
+    if msg_body.source~="" then
+        source_param =  string.format(" AND source = '%s' ",msg_body.source)
+    end
+
+    local date_param = ""
+    if msg_body.start_publish_time~="" and msg_body.end_publish_time~="" then
+        date_param = " AND DATE(publish_time) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_publish_time / 1000) .. ")) AND DATE(publish_time) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_publish_time / 1000) .. "))"
+    end
+
+
+    local create_date_param = ""
+    if msg_body.start_create_time~="" and msg_body.end_create_time~="" then
+        create_date_param = " AND create_day >= DATE(FROM_UNIXTIME(" .. (msg_body.start_create_time / 1000) .. ")) AND create_day <= DATE(FROM_UNIXTIME(" .. (msg_body.end_create_time / 1000) .. ")) "
+    end
+
+    local d_z_param = ""
+    if msg_body.d_z~="" then
+        if(msg_body.d_z == 0) then
+            d_z_param = " like_num ASC"
+        else
+            d_z_param = " like_num DESC"
+        end
+    end
+   
+    local comment_param = ""
+    if msg_body.comment~="" then
+        if(msg_body.comment == 0) then
+            comment_param = " comment_num ASC"
+        else
+            comment_param = " comment_num DESC"
+        end
+    end
+
+    local forward_param = ""
+    if msg_body.forward~="" then
+        if(msg_body.forward == 0) then
+            forward_param = " shared_num ASC"
+        else
+            forward_param = " shared_num DESC"
+        end
+    end
+    
+    local collect_param = ""
+    if msg_body.collect~="" then
+        if(msg_body.collect == 0) then
+            collect_param = " kepp_num ASC"
+        else
+            collect_param = " kepp_num DESC"
+        end
+    end
+    
+
+    local param = tg_platform_id_param..date_param..create_date_param..product_param..source_param..video_id_param..material_sync_status_param
+
+    local up_down_param = d_z_param..comment_param..forward_param..collect_param
+
+    if up_down_param ~= "" then
+        up_down_param = " ORDER BY " ..up_down_param
+    end
+
+    local sql = "SELECT * FROM filter_data WHERE status<2  "..param..up_down_param.." ORDER BY id DESC"..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+
+    local res =  mysqldbx.query(sql)
+
+    sql =  "SELECT  COUNT(*) AS total  FROM filter_data WHERE status!=2 "..param
+
+    local total = mysqldbx.query(sql)
+
+    return true,res,total[1].total
+end
+
+
+function M.set_material_sync_status(msg_body)
+    local isok ,key =  tools.checkData({"id_list","material_sync_status"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    for i = 1, #msg_body.id_list, 1 do
+        local res,sql,id;
+        id = msg_body.id_list[i]
+        sql = string.format("UPDATE  filter_data SET material_sync_status = %d , status = 1  WHERE id = %d ",msg_body.material_sync_status,id)
+        res = mysqldbx.query(sql)
+    end
+    return true,{}
+end
+
+--重置任务状态
+function M.set_status(msg_body)
+    local isok ,key =  tools.checkData({"id_list","status"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("UPDATE  filter_data SET status = %d    WHERE id IN (%s) ",msg_body.status,idString)
+    skynet.error("sql:",sql)
+    mysqldbx.query(sql)
+    return true,{}
+end
+
+--设置任务权重
+function M.set_weight(msg_body)
+    local isok ,key =  tools.checkData({"id_list","weight"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("UPDATE  filter_data SET weight = %d    WHERE id IN (%s) ",msg_body.weight,idString)
+    skynet.error("sql:",sql)
+    mysqldbx.query(sql)
+    return true,{}
+end
+
+return M

+ 425 - 0
service/backmgr/filter_task.lua

@@ -0,0 +1,425 @@
+--最大转化
+local M = {}
+local db
+local mysqldtaskbx = {}
+local mysqldbx = require "mysqldbx"
+require "skynet.manager"
+local mysql = require "skynet.db.mysql"
+local config = require "run_config"
+local tools = require "tools"
+local skynet = require "skynet"
+--获取原始数据总数
+function M.get_origin_total()
+    local sql = "SELECT COUNT(*) AS total FROM origin_data"
+    local res = mysqldbx.query(sql)
+    return true,res[1]
+end
+--获取原始数据
+function M.get_origin(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    local sql = string.format("SELECT * FROM origin_data ORDER BY id DESC LIMIT %d OFFSET %d",page_size, offset)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    return true,res
+end
+--获取筛选总数
+function M.get_filter_total()
+    local sql = "SELECT COUNT(*) AS total FROM filter_data"
+    local res = mysqldbx.query(sql)
+    return true,res[1]
+end
+
+
+--获取筛选数据
+function M.get_filter(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    local sql = string.format("SELECT * FROM filter_data ORDER BY id LIMIT %d OFFSET %d",page_size, offset)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    return true,res
+end
+
+
+
+--获取书籍总数
+function M.get_book_total()
+    local sql = "SELECT COUNT(*) AS total FROM video_product"
+    local res = mysqldtaskbx.Singleton().query(sql)
+    return true,res[1]
+end
+
+
+--获取书籍
+function M.get_book(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    local sql = string.format("SELECT * FROM video_product ORDER BY id DESC LIMIT %d OFFSET %d",page_size, offset)
+    local isok,res;
+    res = mysqldtaskbx.Singleton().query(sql)
+    return true,res
+end
+
+
+
+
+--获取小程序书籍总数
+function M.get_app_book_total()
+    local sql = "SELECT COUNT(*) AS total FROM video_applet_product"
+    local res = mysqldtaskbx.Singleton().query(sql)
+    return true,res[1]
+end
+
+
+--获取小程序书籍
+function M.get_app_book(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    local sql = string.format("SELECT * FROM video_applet_product ORDER BY id DESC LIMIT %d OFFSET %d ",page_size, offset)
+    local isok,res;
+    res = mysqldtaskbx.Singleton().query(sql)
+    return true,res
+end
+
+--设置小程序书籍状态
+function M.set_app_book_status(msg_body)
+    local isok ,key =  tools.checkData({"id_list","status"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    for i = 1, #msg_body.id_list, 1 do
+        local res,sql,id;
+        id = msg_body.id_list[i]
+        sql = string.format("UPDATE  video_applet_product SET status = %d WHERE id = %d ",msg_body.status,id)
+        res = mysqldtaskbx.Singleton().query(sql)
+    end
+    return true,{}
+end
+
+
+
+--获取推广数据总数
+function M.get_tui_guang_total()
+    local sql = "SELECT COUNT(*) AS total FROM video_material"
+    local res = mysqldbx.query(sql)
+    return true,res[1]
+end
+
+
+--获取推广数据
+function M.get_tui_guang(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    local sql = string.format("SELECT * FROM video_material ORDER BY id DESC LIMIT %d OFFSET %d ",page_size, offset)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    return true,res
+end
+
+
+--根据素材id搜索 material_id 
+function M.search_zeng_liang_by_material_id(msg_body)
+    local isok ,key =  tools.checkData({"oce_material_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("SELECT * FROM video_material  WHERE oce_material_id = %d  LIMIT 1 ", msg_body.oce_material_id)
+    local res;
+    res = mysqldbx.query(sql)
+    local info = {}
+    if #res>0 then
+        info = res[1]
+    end
+    return true,info
+end
+
+--推广增量
+function M.tui_guang_zeng_liang(msg_body)
+    local isok ,key =  tools.checkData({"ad_convert_type","advertiser_id","custom_budget","cpa_bid","main_id","quantity","bid_type","id_list","is_rise","is_new"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("SELECT * FROM video_material WHERE id IN (%s)",idString)
+    local isok,res;
+    res = mysqldbx.query(sql)
+
+    for i = 1, #res, 1 do
+        local id =   res[i].id
+        local material_id = id
+        sql = string.format("UPDATE  video_material SET bl_status = 1 WHERE id =%d ",id)
+        mysqldbx.query(sql)
+
+        sql = string.format("INSERT INTO `task_boost_material_queue` (ad_convert_type,advertiser_id,custom_budget,cpa_bid,material_id,main_id,quantity,bid_type,is_rise,is_new)  VALUES (%d,'%s',%d,%d,%d,%d,%d,%d,%d,%d)",
+        msg_body.ad_convert_type,msg_body.advertiser_id,msg_body.custom_budget,msg_body.cpa_bid,material_id,msg_body.main_id,msg_body.quantity,msg_body.bid_type,msg_body.is_rise,msg_body.is_new)
+        mysqldbx.query(sql)
+
+    end
+    return true,res
+end
+
+
+
+--获取爆量数据总数
+function M.get_bao_liang_total()
+    local sql = "SELECT COUNT(*) AS total FROM boost_material_history"
+    local res = mysqldbx.query(sql)
+    return true,res[1]
+end
+
+
+--获取爆量数据
+function M.get_bao_liang(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    local sql = string.format("SELECT * FROM boost_material_history ORDER BY id DESC LIMIT %d OFFSET %d  ",page_size, offset)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    return true,res
+end
+
+--设置爆量标题数量
+function M.set_bao_liang_title_count(msg_body)
+    local isok ,key =  tools.checkData({"title_count","id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE  boost_material_history SET title_count = %d WHERE id = %d ",msg_body.title_count,msg_body.id)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    return true,res
+end
+
+--搜索爆量
+--tg_main_id 主体
+--tg_platform_id 平台id
+--product_id 书id
+--product_name 书名
+--oce_material_id 巨量素材ID
+function M.search_bao_liang_data(msg_body)
+    local isok ,key =  tools.checkData({
+    "product_name",
+    "product_id",
+    "tg_platform_id",
+    "oce_material_id",
+    "tg_main_id",
+    "page_size",
+    "page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    local isFirst = false
+    local product_param = ""
+    if msg_body.product_id~="" then
+        isFirst = true
+        product_param = string.format(" product_id = %d ",tonumber(msg_body.product_id))
+    end
+    local main_param = ""
+    if msg_body.tg_main_id~="" then
+        if isFirst == true then
+            main_param = string.format("AND tg_main_id = %d ",tonumber(msg_body.tg_main_id))
+        else
+            isFirst = true
+            main_param = string.format(" tg_main_id = %d ",tonumber(msg_body.tg_main_id))
+        end
+    end
+
+    local oce_material_param = ""
+    if msg_body.oce_material_id~="" then
+        if isFirst == true then
+            oce_material_param = string.format("AND oce_material_id = %d ",tonumber(msg_body.oce_material_id))
+        else
+            isFirst = true
+            oce_material_param = string.format(" oce_material_id = %d ",tonumber(msg_body.oce_material_id))
+        end
+       
+    end
+    local tg_platform_param = ""
+    if msg_body.tg_platform_id~="" then
+        if isFirst == true then
+            tg_platform_param = " AND tg_platform_id = "..msg_body.tg_platform_id.." "
+        else
+            isFirst = true
+            tg_platform_param = " tg_platform_id = "..msg_body.tg_platform_id.." "
+        end
+    end
+
+
+    local param = product_param..oce_material_param..tg_platform_param..main_param;
+
+    if param ~= "" then
+        param = " WHERE "..param
+    end
+
+    local sql = "SELECT * FROM boost_material_history "..param.." ORDER BY id DESC ".. string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local res = mysqldbx.query(sql)
+    sql =  "SELECT   COUNT(*) AS total  FROM boost_material_history "..param .." ORDER BY id DESC "
+    local total = mysqldbx.query(sql)
+
+    return true,res,total[1].total
+end
+
+
+--添加书籍数据
+function M.add_book_data(msg_body)
+    local isok ,key =  tools.checkData({"fee_unit","default_price","default_pay_section","publish_time","status","product_parent_id","tg_platform_id","product_id","product_name"
+    ,"genre","is_store"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql ;
+    local isok,res;
+    local sql = string.format("SELECT * FROM video_product where product_id = '%s'  LIMIT 1 ",msg_body.product_id)
+    res = mysqldtaskbx.Singleton().query(sql)
+
+    if #res>0 then
+        return false,"书籍已存在!"
+    end
+
+    sql = string.format("INSERT INTO `video_product` (fee_unit,default_price,default_pay_section,publish_time,status,product_parent_id,book_platform,product_id, product_name, genre,is_store,is_auto)  VALUES (%d,%f,%d,'%s',%d,'%s',%d,'%s','%s',%d,%d,0)",
+    msg_body.fee_unit,
+    msg_body.default_price,
+    msg_body.default_pay_section,
+    msg_body.publish_time,
+    msg_body.status,
+    msg_body.product_parent_id,
+    msg_body.tg_platform_id,
+    msg_body.product_id,
+    msg_body.product_name,
+    msg_body.genre,msg_body.is_store)
+
+    res = mysqldtaskbx.Singleton().query(sql)
+    return true,{}
+end
+
+--发送书籍数据到主体
+function M.send_book_data(msg_body)
+    local isok ,key =  tools.checkData({"tg_platform_id","app_id","id_list","main_id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql ;
+    local isok,res;
+    local sql = string.format("SELECT * FROM video_product WHERE id IN (%s)",idString)
+    res = mysqldtaskbx.Singleton().query(sql)
+    for i = 1, #res, 1 do
+        local product_id =   res[i].product_id
+        local product_name = res[i].product_name
+        local product_parent_id = res[i].product_parent_id
+ 
+
+        for j = 1, #msg_body.main_id_list, 1 do
+            local main_id = msg_body.main_id_list[j]
+            local sql = string.format("SELECT * FROM video_applet_product where product_id = '%s' and book_platform  = %d and dy_small_applet_app_id = '%s' and main_id = %d ",product_id,msg_body.tg_platform_id,msg_body.app_id,main_id)
+            local result = mysqldtaskbx.Singleton().query(sql)
+            if #result<=0 then 
+                local butler_info = mysqldbx.query( "SELECT  butler_id  FROM tg_main WHERE id = "..main_id.." LIMIT 1")
+                sql = string.format("INSERT INTO `video_applet_product` (product_id,product_name,book_platform,dy_small_applet_app_id,main_id,wait_status,status,butler_id,product_parent_id)  VALUES ('%s','%s',%d,'%s',%d,%d,%d,%d,'%s')",
+                product_id,product_name,msg_body.tg_platform_id,msg_body.app_id,main_id,0,0, butler_info[1].butler_id,product_parent_id)
+                mysqldtaskbx.Singleton().query(sql)
+                skynet.error("sql:",sql)
+            end
+  
+        end
+    end
+    return true,{}
+end
+--删除书籍
+function M.delete_book_data(msg_body)
+    local isok ,key =  tools.checkData({"id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    for i = 1, #msg_body.id_list, 1 do
+        local id =   msg_body.id_list[i]
+        local sql = string.format("DELETE FROM video_product WHERE id = %d ",id)
+        local res = mysqldtaskbx.Singleton().query(sql)
+    end
+
+    return true,{}
+end
+
+--书籍入库
+function M.set_book_data_is_store(msg_body)
+    local isok ,key =  tools.checkData({"id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    for i = 1, #msg_body.id_list, 1 do
+        local id =   msg_body.id_list[i]
+        local sql = string.format("UPDATE  video_product SET is_store = %d WHERE id = %d ",1,id)
+        local res = mysqldtaskbx.Singleton().query(sql)
+    end
+    return true,{}
+end
+
+function mysqldtaskbx.start()
+    local function on_connect(db)
+        db:query("set charset utf8mb4");
+    end
+    local conf = config.db_cnf.book_server.mysqldb_task_cnf
+    db = mysql.connect{
+        host=conf.ip,
+        port=conf.port,
+        database=conf.db,
+        user=conf.user,
+        password=conf.password,
+        charset="utf8mb4",
+        max_packet_size = 1024 * 1024,
+        on_connect = on_connect
+    }
+    if not db then
+        error("mysql connect fail")
+    end
+end
+
+
+
+function mysqldtaskbx.Singleton()
+    if db == nil then
+        mysqldtaskbx.start()
+    end
+    return mysqldtaskbx
+end
+function mysqldtaskbx.query(sql)
+    return db:query(sql)
+end
+
+return M

+ 68 - 0
service/backmgr/fq_book.lua

@@ -0,0 +1,68 @@
+--番茄
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+function M.get_all_fq_key()
+    local sql = "SELECT * FROM fq_book_config "
+    local res = mysqldbx.query(sql)
+    return true,res
+end
+
+function M.add_fq_book_sid_tt(msg_body)
+    local isok ,key =  tools.checkData({"sid_tt","name"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("SELECT * FROM fq_book_config WHERE sid_tt = '%s' LIMIT 1", msg_body.sid_tt)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res > 0 then
+        return false ,"sid_tt :"..msg_body.sid_tt.." 已存在!"
+    end
+    sql = string.format("INSERT INTO `fq_book_config` (sid_tt,name)  VALUES ('%s','%s')",msg_body.sid_tt,msg_body.name)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateFqKeyList"}))
+    return true, {}
+end
+
+function M.delete_fq_book_sid_tt(msg_body)
+    local isok ,key =  tools.checkData({"sid_tt"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("DELETE FROM fq_book_config WHERE sid_tt = '%s' ",msg_body.sid_tt)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateFqKeyList"}))
+    return true, {}
+end
+
+
+function M.set_use_status(msg_body)
+    local isok ,key =  tools.checkData({"canUse","id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE  fq_book_config SET canUse = %d WHERE id =%d ",msg_body.canUse,msg_body.id)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateFqKeyList"}))
+    return true, {}
+end
+
+function M.fq_book_list(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    local sql = "SELECT * FROM fq_book_config "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldbx.query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM fq_book_config "
+    local total = mysqldbx.query(sql)
+    return true,list,total[1].total
+end
+return M

+ 68 - 0
service/backmgr/fq_mf_book.lua

@@ -0,0 +1,68 @@
+--番茄免费
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+function M.get_all_fq_mf_key()
+    local sql = "SELECT * FROM fq_mf_book_config "
+    local res = mysqldbx.query(sql)
+    return true,res
+end
+
+function M.add_fq_mf_book_sid_tt(msg_body)
+    local isok ,key =  tools.checkData({"sid_tt","name"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("SELECT * FROM fq_mf_book_config WHERE sid_tt = '%s' LIMIT 1", msg_body.sid_tt)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res > 0 then
+        return false ,"sid_tt :"..msg_body.sid_tt.." 已存在!"
+    end
+    sql = string.format("INSERT INTO `fq_mf_book_config` (sid_tt,name)  VALUES ('%s','%s')",msg_body.sid_tt,msg_body.name)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateFqMfKeyList"}))
+    return true, {}
+end
+
+function M.delete_fq_mf_book_sid_tt(msg_body)
+    local isok ,key =  tools.checkData({"sid_tt"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("DELETE FROM fq_mf_book_config WHERE sid_tt = '%s' ",msg_body.sid_tt)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateFqMfKeyList"}))
+    return true, {}
+end
+
+
+function M.set_use_status(msg_body)
+    local isok ,key =  tools.checkData({"canUse","id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE  fq_mf_book_config SET canUse = %d WHERE id =%d ",msg_body.canUse,msg_body.id)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateFqMfKeyList"}))
+    return true, {}
+end
+
+function M.fq_mf_book_list(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    local sql = "SELECT * FROM fq_mf_book_config "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldbx.query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM fq_mf_book_config "
+    local total = mysqldbx.query(sql)
+    return true,list,total[1].total
+end
+return M

+ 140 - 0
service/backmgr/init.lua

@@ -0,0 +1,140 @@
+local skynet = require "skynet"
+local s = require "service"
+local tools = require "tools"
+local cjson = require "cjson"
+local mysql = require "skynet.db.mysql"
+local back_response = require "back_response"
+local urllib = require "http.url"
+local crypt = require "skynet.crypt"
+local tg_temp_app   = require "tg_temp_app"
+local tg_platform   = require "tg_platform"
+local tg_zhanghu   = require "tg_zhanghu"
+local tg_max_zhuanhua   = require "tg_max_zhuanhua"
+local user   = require "user"
+local tg_app   = require "tg_app"
+local tg_main   = require "tg_main"
+local db_filter_config = require "db_filter_config"
+local push_msg = require "push_msg"
+local filter_task = require "filter_task"
+local fq_book = require "fq_book"
+local book_black_list = require "book_black_list"
+local video_titles = require "video_titles"
+local pull_data_config = require "pull_data_config"
+local pull_data_status = require "pull_data_status"
+local video_applet_product = require "video_applet_product"
+local filter_data = require "filter_data"
+local video_material = require "video_material"
+local no_filter_origin = require "no_filter_origin"
+local origin_video_titles = require "origin_video_titles"
+local promotion_audit_suggestions = require "promotion_audit_suggestions"
+local tg_butler = require "tg_butler"
+local tg_mini_program_platform = require "tg_mini_program_platform"
+local task_material_queue_queue = require "task_material_queue_queue"
+local video_product = require "video_product"
+local origin_data = require "origin_data"
+local video_product_material = require "video_product_material"
+local aweme_auth_list = require "aweme_auth_list"
+local checks = require "checks"
+local fq_mf_book = require "fq_mf_book"
+local tg_main_price_template = require "tg_main_price_template"
+local ad_convert_type = require "ad_convert_type"
+local other_book = require "other_book"
+local platform_shared = require "platform_shared"
+local material_review = require "material_review"
+local yw_book = require "yw_book"
+local wechat_miniapp_product = require "wechat_miniapp_product"
+local material_platform = require "material_platform"
+local data_manager = require "data_manager"
+local statistics_platform = require "statistics_platform"
+local review_user = require "review_user"
+local log = require "log"
+local status_200 = 200
+local CMD = {
+    
+}
+CMD["tg_temp_app"] = tg_temp_app;
+CMD["tg_platform"] = tg_platform;
+CMD["tg_zhanghu"] = tg_zhanghu;
+CMD["tg_max_zhuanhua"] = tg_max_zhuanhua;
+CMD["tg_app"] = tg_app;
+CMD["user"] = user;
+CMD["tg_main"] = tg_main;
+CMD["db_filter_config"] = db_filter_config;
+CMD["push_msg"] = push_msg;
+CMD["filter_task"] = filter_task;
+CMD["fq_book"] = fq_book;
+CMD["book_black_list"] = book_black_list;
+CMD["video_titles"] = video_titles;
+CMD["pull_data_config"] = pull_data_config;
+CMD["pull_data_status"] = pull_data_status;
+CMD["video_applet_product"] = video_applet_product;
+CMD["filter_data"] = filter_data;
+CMD["video_material"] = video_material;
+CMD["no_filter_origin"] = no_filter_origin;
+CMD["origin_video_titles"] = origin_video_titles;
+CMD["promotion_audit_suggestions"] = promotion_audit_suggestions;
+CMD["tg_butler"] = tg_butler;
+CMD["tg_mini_program_platform"] = tg_mini_program_platform;
+CMD["task_material_queue_queue"] = task_material_queue_queue;
+CMD["video_product"] = video_product;
+CMD["origin_data"] = origin_data;
+CMD["video_product_material"] = video_product_material;
+CMD["aweme_auth_list"] = aweme_auth_list;
+CMD["checks"] = checks;
+CMD["fq_mf_book"] = fq_mf_book;
+CMD["tg_main_price_template"] = tg_main_price_template;
+CMD["ad_convert_type"] = ad_convert_type;
+CMD["other_book"] = other_book;
+CMD["platform_shared"] = platform_shared;
+CMD["material_review"] = material_review;
+CMD["yw_book"] = yw_book;
+CMD["wechat_miniapp_product"] = wechat_miniapp_product;
+CMD["material_platform"] = material_platform;
+CMD["data_manager"] = data_manager;
+CMD["statistics_platform"] = statistics_platform;
+CMD["review_user"] = review_user;
+CMD["log"] = log;
+function run(target,fun,msg_body,fd)
+    if target~=nil and fun~=nil and target[fun]~=nil then
+        local isok,data,total = target[fun](msg_body)
+        if isok then
+            if data~=nil then
+                if total~=nil then
+                    tools.response(fd,status_200,cjson.encode({code=10000,data=data,total=total}))
+                else
+                    tools.response(fd,status_200,cjson.encode({code=10000,data=data}))
+                end
+               
+            else
+                tools.response(fd,status_200,cjson.encode({code=10000,msg="OK!"}))
+            end
+        else
+            tools.response(fd,status_200,cjson.encode({code=10001,msg=data}))
+        end
+    else
+        return tools.response(fd,status_200,{code=10002,msg="没找到方法!"})
+    end
+end
+
+CMD.api = function(msg_body,fd)
+    if msg_body~=nil and msg_body~="" then
+        if CMD[msg_body['cmd']] then
+            run(CMD[msg_body['cmd']],msg_body['fun'],msg_body['data'],fd)
+        end
+    end
+end
+
+CMD.ws_push_msg = function(msg_body)
+    CMD['push_msg'].push(msg_body.cmd,msg_body.data)
+end
+--接口end
+s.resp.on_recv = function (source, fd, msg_id, msg_body)
+    if CMD[msg_id]~=nil then
+        tools.dump(msg_body)
+        CMD[msg_id](cjson.decode(msg_body),fd)
+    end
+end
+s.init = function()
+  
+end
+s.start(...)

+ 158 - 0
service/backmgr/log.lua

@@ -0,0 +1,158 @@
+--日志
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+
+function M.add_column( msg_body)
+    local isok ,key =  tools.checkData({"column_name","column_type","default_value"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local default_param 
+    if type(msg_body.default_value) == "string" then
+        default_param =  string.format(" DEFAULT '%s' ",msg_body.default_value)
+    elseif type(msg_body.default_value) == "number" then
+        default_param =  string.format(" DEFAULT %d ",msg_body.default_value)
+    end
+    local sql = string.format("ALTER TABLE `%s` ADD COLUMN `%s` %s %s", 
+        'log', msg_body.column_name, msg_body.column_type,default_param)
+    skynet.error("sql:",sql)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+function M.add_log(msg_body)
+    local isok ,key =  tools.checkData({"opt_type","user_id","content"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    local sql 
+    sql = string.format("INSERT INTO `log` (opt_type,user_id,content,create_day)  VALUES (%d,%d,'%s','%s')",msg_body.opt_type,msg_body.user_id,cjson.encode(msg_body.content),current_time)
+    skynet.error("sql:",sql)
+    tools.dump(mysqldbx.query(sql)) 
+    return true, {}
+end
+
+
+function M.diy_add_log(msg_body)
+    local isok ,key =  tools.checkData({"data"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    local table_name = 'log'
+    local data = msg_body.data
+    local fields, values_str = {}, {}
+    -- 改用 table.index 判断替代 contains
+    local sql_functions = {
+        ["CURRENT_TIMESTAMP"] = true,
+        ["NOW()"] = true,
+        ["UUID()"] = true
+    }
+    table.insert(fields, "`" .. "create_day" .. "`")
+    table.insert(values_str,  "'" .. current_time .. "'" )
+    for field, value in pairs(data) do
+        -- 过滤字段名中的非法字符
+        field = field:gsub("[%s`'\"]", "")
+        table.insert(fields, "`" .. field .. "`")
+
+        -- 检查是否为 SQL 函数
+        if sql_functions[value] then
+            table.insert(values_str, value)
+        else
+            -- 处理普通值
+            if type(value) == "number" then
+                table.insert(values_str, tostring(value))
+            elseif type(value) == "string" then
+                table.insert(values_str, "'" .. value:gsub("'", "''") .. "'")  -- 转义单引号
+            elseif value == nil then
+                table.insert(values_str, "NULL")
+            elseif type(value) == "table" then
+                table.insert(values_str, "'"..cjson.encode(value).."'")
+            else
+                error("不支持的数据类型: " .. type(value))
+            end
+        end
+    end
+
+    local sql = "INSERT INTO `" .. table_name .. "` (" .. table.concat(fields, ", ") .. ") " ..
+                "VALUES (" .. table.concat(values_str, ", ") .. ")"
+    skynet.error("sql:",sql)
+    mysqldbx.query(sql)
+    return true, {}
+
+end
+
+
+function M.search(msg_body)
+    local isok ,key =  tools.checkData({"data","opt_type","user_id","page_size", "page_number","start_create_day","end_create_day"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+
+    local opt_type_param = ""
+    if msg_body.opt_type~="" then
+        opt_type_param = string.format(" AND opt_type = %d ",msg_body.opt_type)
+    end
+
+    local user_id_param = ""
+    if msg_body.user_id~="" then
+        user_id_param = string.format(" AND user_id = %d ",msg_body.user_id)
+    end
+
+    local create_day_param = ""
+    if msg_body.start_create_day~="" and msg_body.end_create_day~="" then
+        create_day_param = " AND DATE(create_day) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_create_day / 1000) .. ")) AND DATE(create_day) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_create_day / 1000) .. ")) "
+    end
+
+
+    local diy_param = ""
+    if msg_body.data~="" then
+        local data = msg_body.data
+        local fields, values_str = {}, {}
+        for field, value in pairs(data) do
+            -- 过滤字段名中的非法字符
+            field = field:gsub("[%s`'\"]", "")
+            table.insert(fields, "`" .. field .. "`")
+            local cur_param = ""
+            -- 处理普通值
+            if type(value) == "number" then
+                -- table.insert(values_str, tostring(value))
+                cur_param = " AND ".."`" .. field .. "`".." = "..value
+            elseif type(value) == "string" then
+                cur_param = " AND ".."`" .. field .. "`".." = ".."'" .. value:gsub("'", "''") .. "'"
+                -- table.insert(values_str, "'" .. value:gsub("'", "''") .. "'")  -- 转义单引号
+            else
+                error("不支持的数据类型: " .. type(value))
+            end
+
+            diy_param = diy_param..cur_param
+        end
+     
+    end
+ 
+
+    local param = diy_param..opt_type_param..user_id_param..create_day_param
+    
+    local sql = "SELECT * FROM log WHERE 1=1 "..param.."ORDER BY id DESC"..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    
+    skynet.error("sql:",sql)
+    -- 执行查询
+    local res = mysqldbx.query(sql)
+    -- 使用 COUNT(*) 优化总数查询
+    sql =  "SELECT  COUNT(*) AS total  FROM log WHERE 1=1 "..param
+
+    local total = mysqldbx.query(sql)
+
+    return true, res, total[1].total
+end
+
+return M

+ 45 - 0
service/backmgr/material_platform.lua

@@ -0,0 +1,45 @@
+--素材平台
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+
+
+function M.add_platform(msg_body)
+    local isok ,key =  tools.checkData({"name"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("INSERT INTO `material_platform` (name)  VALUES ('%s')",msg_body.name)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+
+function M.modify(msg_body)
+    local isok ,key =  tools.checkData({"name","id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE  material_platform SET  name = '%s' WHERE id = %d ",msg_body.name,msg_body.id)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+function M.search(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    
+    local sql = "SELECT * FROM material_platform "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldbx.query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM material_platform "
+    local total = mysqldbx.query(sql)
+    return true,list,total[1].total
+end
+
+return M

+ 88 - 0
service/backmgr/material_review.lua

@@ -0,0 +1,88 @@
+--素材审核表
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local mysql = require "skynet.db.mysql"
+local config = require "run_config"
+local cjson = require "cjson"
+local db
+local mysqldtaskbx = {}
+
+function M.search(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number","material_id","oce_material_id",
+    "is_sexual_inducement_content","is_bad_value_view","start_time_date","end_time_date"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+
+    local material_id_param = ""
+    if msg_body.material_id~="" then
+        material_id_param =  string.format(" AND material_id = %d ",tonumber(msg_body.material_id)) 
+    end
+
+    local oce_material_param = ""
+    if msg_body.oce_material_id~="" then
+        oce_material_param =string.format("AND oce_material_id =  %d ",tonumber(msg_body.oce_material_id))
+    end
+
+    local is_sexual_inducement_content_param = ""
+    if msg_body.is_sexual_inducement_content~="" then
+        is_sexual_inducement_content_param = "AND is_sexual_inducement_content = "..msg_body.is_sexual_inducement_content.." "
+    end
+
+    local is_bad_value_view_param = ""
+    if msg_body.is_bad_value_view~="" then
+        is_bad_value_view_param = "AND is_bad_value_view = "..msg_body.is_bad_value_view.." "
+    end
+
+    local date_param = ""
+    if msg_body.start_time_date~="" and msg_body.end_time_date~="" then
+        date_param = " AND DATE(create_at) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_time_date / 1000) .. ")) AND DATE(create_at) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_time_date / 1000) .. "))"
+    end
+
+    local param = material_id_param..oce_material_param..is_sexual_inducement_content_param..is_bad_value_view_param..date_param
+
+    local sql = "SELECT * FROM video_material_review where 1=1 "..param..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    skynet.error("sql:",sql)
+    local list = mysqldtaskbx.Singleton().query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM video_material_review where 1=1 "..param
+    local total = mysqldtaskbx.Singleton().query(sql)
+    return true,list,total[1].total
+end
+
+function mysqldtaskbx.start()
+    local function on_connect(db)
+        db:query("set charset utf8mb4");
+    end
+    local conf = config.db_cnf.book_server.mysqldb_material_review_cnf
+    db = mysql.connect{
+        host=conf.ip,
+        port=conf.port,
+        database=conf.db,
+        user=conf.user,
+        password=conf.password,
+        charset="utf8mb4",
+        max_packet_size = 1024 * 1024,
+        on_connect = on_connect
+    }
+    if not db then
+       skynet.error("mysql connect fail")
+    end
+end
+
+function mysqldtaskbx.Singleton()
+    if db == nil then
+        mysqldtaskbx.start()
+    end
+    return mysqldtaskbx
+end
+function mysqldtaskbx.query(sql)
+    return db:query(sql)
+end
+
+return M

+ 71 - 0
service/backmgr/no_filter_origin.lua

@@ -0,0 +1,71 @@
+--无筛选原始数据
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+function M.check_table_exists(table_name)
+    local sql = string.format("SHOW TABLES LIKE '%s'", table_name)
+    local res = mysqldbx.query(sql)
+    return res and #res > 0
+end
+
+function M.search_no_filter_origin_data(msg_body)
+    local isok ,key =  tools.checkData({"video_id","date","page_size","page_number","materialId"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local table_name = "pull_data_"..string.gsub(msg_body.date, "-", "")
+
+    if not M.check_table_exists(table_name) then
+        return false,string.format("不存在  %s 这个数据.", table_name)
+    end
+
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+    local video_id_param = ""
+    if msg_body.video_id~="" then
+        video_id_param =  " AND awemeId = "..msg_body.video_id
+    end
+
+    local materialId_param = ""
+    if msg_body.materialId~="" then
+        materialId_param =  string.format(" AND materialId = '%s' ",msg_body.materialId)
+    end
+
+    local param = video_id_param..materialId_param
+    local up_down_param = " ORDER BY " .." likeCount DESC "
+
+    local sql = "SELECT * FROM "..table_name.." WHERE 1=1 "..param..up_down_param..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+
+    skynet.error("sql1:",sql)
+
+    local res =  mysqldbx.query(sql)
+
+    sql =  "SELECT  COUNT(*) AS total  FROM "..table_name.." WHERE 1=1 "..param
+
+    skynet.error("sql2:",sql)
+
+    local total = mysqldbx.query(sql)
+
+    return true,res,total[1].total
+end
+
+function M.delete_no_filter_origin_data(msg_body)
+    local isok ,key =  tools.checkData({"date"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local table_name = "pull_data_"..string.gsub(msg_body.date, "-", "")
+    if not M.check_table_exists(table_name) then
+        return false,string.format("不存在  %s 这个数据.", table_name)
+    end
+    local sql = string.format("DROP TABLE %s", table_name)
+    mysqldbx.query(sql)
+    return true,{}
+end
+
+return M

+ 85 - 0
service/backmgr/origin_data.lua

@@ -0,0 +1,85 @@
+--原始数据
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+function M.delete_origin_data_by_time(msg_body)
+    local isok ,key =  tools.checkData({"start_create_time","end_create_time"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local delete_time_param = " AND DATE(created_at) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_create_time / 1000) .. ")) AND DATE(created_at) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_create_time / 1000) .. "))"
+end
+
+function M.reset_status(msg_body)
+    local isok ,key =  tools.checkData({"id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    for i = 1, #msg_body.id_list, 1 do
+        local res,sql,id;
+        id = msg_body.id_list[i]
+        sql = string.format("UPDATE  origin_data SET status = 0 WHERE id = %d ",id)
+        res = mysqldbx.query(sql)
+    end
+    return true,{}
+end
+
+function M.search_origin_data(msg_body)
+    local isok ,key =  tools.checkData({"is_wx_guajian","page_size","page_number","start_create_time","end_create_time","guajian_info","start_publish_time","end_publish_time","materialId"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+
+    local is_wx_guajian_param = ""
+    if msg_body.is_wx_guajian~="" then
+        is_wx_guajian_param = string.format(" AND is_wx_guajian = %d ",msg_body.is_wx_guajian)
+    end
+
+
+    local date_param = ""
+    if msg_body.start_publish_time~="" and msg_body.end_publish_time~="" then
+        date_param = " AND DATE(publish_time) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_publish_time / 1000) .. ")) AND DATE(publish_time) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_publish_time / 1000) .. ")) "
+    end
+
+
+    local create_date_param = ""
+    if msg_body.start_create_time~="" and msg_body.end_create_time~="" then
+        create_date_param = " AND create_day >= DATE(FROM_UNIXTIME(" .. (msg_body.start_create_time / 1000) .. ")) AND create_day <= DATE(FROM_UNIXTIME(" .. (msg_body.end_create_time / 1000) .. ")) "
+    end
+
+    local guajian_info_param = ""
+    -- 挂件信息条件
+    if msg_body.guajian_info ~= "" then
+        local searchTerm = string.gsub(msg_body.guajian_info, "%%", "\\%%")
+        guajian_info_param = string.format("  AND guajian_link LIKE CONCAT('%%', '%s', '%%')  ",searchTerm)
+    end
+
+    local materialId_param = ""
+    -- 材料ID条件
+    if msg_body.materialId ~= "" then
+        materialId_param =  string.format(" AND materialId = '%s' ",msg_body.materialId)
+    end
+
+    local param = date_param..create_date_param..guajian_info_param..materialId_param..is_wx_guajian_param
+    
+    local sql = "SELECT * FROM origin_data WHERE 1=1 "..param.."ORDER BY id DESC"..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    
+    skynet.error("sql:",sql)
+    -- 执行查询
+    local res = mysqldbx.query(sql)
+    -- 使用 COUNT(*) 优化总数查询
+    sql =  "SELECT  COUNT(*) AS total  FROM origin_data WHERE 1=1 "..param
+
+    local total = mysqldbx.query(sql)
+
+    return true, res, total[1].total
+end
+
+return M

+ 67 - 0
service/backmgr/origin_video_titles.lua

@@ -0,0 +1,67 @@
+--原始视频标题
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local md5 =	require	"md5"
+
+
+function M.delete_origin_video_titles(msg_body)
+    local isok ,key =  tools.checkData({"id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    for i = 1, #msg_body.id_list, 1 do
+        local id = msg_body.id_list[i]
+        local sql = string.format("DELETE FROM origin_video_titles WHERE id = %d ",id)
+        mysqldbx.query(sql)
+    end
+    return true, {}
+end
+
+function M.publish_origin_video_titles(msg_body)
+    local isok ,key =  tools.checkData({"title_list","pay_type","title_type_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local pay_type = msg_body.pay_type
+    local title_type_id = msg_body.title_type_id
+    for i = 1, #msg_body.title_list, 1 do
+        local title_tab = msg_body.title_list[i]
+        local sql  = string.format("INSERT INTO `video_titles` (title,md5_tag,pay_type,title_type_id)  VALUES ('%s','%s' ,%d,%d)",title_tab.title,title_tab.md5_tag,pay_type,title_type_id)
+        mysqldbx.query(sql)
+        skynet.error("sql:",sql)
+        sql = string.format("DELETE FROM origin_video_titles WHERE id = %d ",title_tab.id)
+        mysqldbx.query(sql)
+    end
+    return true, {}
+end
+
+function M.search_origin_video_titles(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number","content","start_create_time",
+    "end_create_time"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    
+    local content_param = ""
+    if msg_body.content~="" then
+        content_param =  string.format(" AND  ( title LIKE CONCAT( '%%%s%%')) ",msg_body.content)
+    end
+
+    local create_date_param = ""
+    if msg_body.start_create_time~="" and msg_body.end_create_time~="" then
+        create_date_param = " AND DATE(create_time) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_create_time / 1000) .. ")) AND DATE(create_time) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_create_time / 1000) .. "))"
+    end
+
+    local sql = "SELECT * FROM origin_video_titles WHERE 1=1 "..create_date_param..content_param..string.format("  AND (title LIKE CONCAT( '%%%s%%')) ",msg_body.content).." ORDER BY id DESC "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldbx.query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM origin_video_titles  WHERE 1=1 "..create_date_param..content_param..string.format(" AND  (title LIKE CONCAT( '%%%s%%')) ",msg_body.content)
+    local total = mysqldbx.query(sql)
+    return true,list,total[1].total
+end
+
+return M

+ 49 - 0
service/backmgr/other_book.lua

@@ -0,0 +1,49 @@
+--失败书籍
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+function M.delete_other_book(msg_body)
+    local isok ,key =  tools.checkData({"id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    for i = 1, #msg_body.id_list, 1 do
+        local id = msg_body.id_list[i]
+        local sql = string.format("DELETE FROM other_book WHERE id = %d ",id)
+        mysqldbx.query(sql)
+    end
+    return true, {}
+end
+
+
+function M.search_other_book(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number","tg_platform_id","product_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    
+    local product_id_param = ""
+    if msg_body.product_id~="" then
+        product_id_param = string.format(" AND product_id = '%s' " ,msg_body.product_id )
+    end
+    
+    local tg_platform_id_param = ""
+    if msg_body.tg_platform_id~="" then
+        tg_platform_id_param =  " AND tg_platform_id = "..msg_body.tg_platform_id.." "
+    end
+
+    local param = product_id_param..tg_platform_id_param
+    local sql = "SELECT * FROM other_book where 1=1 "..param..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldbx.query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM other_book  where 1=1 "..param
+    local total = mysqldbx.query(sql)
+    return true,list,total[1].total
+end
+
+return M

+ 63 - 0
service/backmgr/platform_shared.lua

@@ -0,0 +1,63 @@
+--共享平台
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+
+--获取所有平台
+function M.gePlatformSharedList()
+    local sql = string.format("select * from `platform_shared` ")
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res <= 0 then
+        return true , {}
+    end
+    return true, res
+end
+
+function M.addPlatformShared(msg_body)
+    local isok ,key =  tools.checkData({"name","info"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("INSERT INTO `platform_shared` (name,info)  VALUES ('%s','%s')",msg_body.name,cjson.encode(msg_body.info))
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updatePlatformConfig"}))
+    return true, {}
+end
+
+function M.modifyPlatformShared(msg_body)
+    local isok ,key =  tools.checkData({"name","info","id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE `platform_shared` SET name = '%s' , info = '%s'  WHERE id = %d ",
+    msg_body.name,
+    cjson.encode(msg_body.info),
+    msg_body.id)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updatePlatformConfig"}))
+    return true, {}
+end
+
+function M.search_platform_shared(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    
+
+    local param = ""
+    local sql = "SELECT * FROM platform_shared where 1=1 "..param..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldbx.query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM platform_shared  where 1=1 "..param
+    local total = mysqldbx.query(sql)
+    return true,list,total[1].total
+end
+
+return M

+ 14 - 0
service/backmgr/processlist.lua

@@ -0,0 +1,14 @@
+--链接数
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local md5 =	require	"md5"
+
+function M.search(msg_body)
+    local sql = "SELECT  COUNT(*) AS total  FROM information_schema.processlist WHERE HOST LIKE '192.168.1.49%'"
+    local total = mysqldbx.query(sql)
+    return true,{},total[1].total
+end
+
+return M

+ 97 - 0
service/backmgr/promotion_audit_suggestions.lua

@@ -0,0 +1,97 @@
+--审核建议列表
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+function M.set_status(msg_body)
+    local isok ,key =  tools.checkData({"id_list","status"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("SELECT * FROM promotion_audit_suggestions WHERE id IN (%s)",idString)
+    local isok,res;
+    res = mysqldbx.query(sql)
+
+    for i = 1, #res, 1 do
+        local id =   res[i].id
+        sql = string.format("UPDATE  promotion_audit_suggestions SET status = %d WHERE id =%d ",msg_body.status,id)
+        mysqldbx.query(sql)
+    end
+
+    return true,{}
+end
+
+function M.search_promotion_audit_suggestions(msg_body)
+    local isok ,key =  tools.checkData({"butler_id","page_size","page_number","start_create_time","end_create_time",
+    "advertiser_id","promotion_id","material_type","material_item","status"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+    
+    local butler_id_param = ""
+    if msg_body.butler_id~="" then
+        butler_id_param =  " AND butler_id = "..msg_body.butler_id
+    end
+
+    local advertiser_id_param = ""
+    if msg_body.advertiser_id~="" then
+        advertiser_id_param =  " AND advertiser_id = "..msg_body.advertiser_id
+    end
+
+    local promotion_id_param = ""
+    if msg_body.promotion_id~="" then
+        promotion_id_param =  " AND promotion_id = "..tonumber(msg_body.promotion_id)
+    end
+
+    local material_type_param = ""
+    if msg_body.material_type~="" then
+        material_type_param =  string.format( " AND material_type = '%s' ",msg_body.material_type)
+    end
+
+    local material_item_param = ""
+    if msg_body.material_item~="" then
+        material_item_param =  string.format(" AND  ( material_item LIKE CONCAT( '%%%s%%')) ",msg_body.material_item)
+    end
+
+    local status_param = ""
+    if msg_body.status~="" then
+        status_param = " AND status = "..msg_body.status
+    end
+
+    local product_id_param = ""
+    if msg_body.product_id~="" then
+        product_id_param = " AND product_id = "..tonumber(msg_body.product_id)
+    end
+
+    local product_library_id_param = ""
+    if msg_body.product_library_id~="" then
+        product_library_id_param = " AND product_library_id = "..tonumber(msg_body.product_library_id)
+    end
+
+    local create_date_param = ""
+    if msg_body.start_create_time~="" and msg_body.end_create_time~="" then
+        create_date_param = " AND DATE(created_at) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_create_time / 1000) .. ")) AND DATE(created_at) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_create_time / 1000) .. "))"
+    end
+
+    local param = create_date_param..advertiser_id_param..promotion_id_param..material_type_param..material_item_param..status_param..product_id_param..product_library_id_param..butler_id_param
+
+    local sql = "SELECT * FROM promotion_audit_suggestions WHERE 1=1 "..param.. " ORDER BY cost DESC "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+   
+    local list = mysqldbx.query(sql)
+
+    sql = "SELECT   COUNT(*) AS total  FROM promotion_audit_suggestions WHERE 1=1  "..param
+
+    local total = mysqldbx.query(sql)
+
+    return true,list,total[1].total
+end
+
+return M

+ 85 - 0
service/backmgr/pull_data_config.lua

@@ -0,0 +1,85 @@
+--拉取数据配置
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+function M.get_all_pull_data_list(msg_body)
+    local sql = "SELECT * FROM pull_data_config "
+    local list = mysqldbx.query(sql)
+    return true,list
+end
+
+
+function M.modify_pull_data_config(msg_body)
+    local isok ,key =  tools.checkData({"id","start","name","interval_minute","start_time","pull_day"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE `pull_data_config` SET  start = '%s' ,name ='%s' , interval_minute = %d , start_time = '%s' , pull_day = '%s' WHERE id = %d ",
+    msg_body.start,msg_body.name,msg_body.interval_minute,msg_body.start_time,msg_body.pull_day,msg_body.id)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+function M.add_pull_data_list_config(msg_body)
+    local isok ,key =  tools.checkData({"config_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    for i = 1, #msg_body.config_list, 1 do
+        local config_item = msg_body.config_list[i]
+        local start_time = config_item.start
+        if config_item.start_time~=nil then
+            start_time = config_item.start_time
+        end
+        local sql = string.format("INSERT INTO `pull_data_config` (start,name,interval_minute,start_time,pull_day)  VALUES ('%s','%s',%d,'%s','%s')",config_item.start,config_item.name,config_item.interval_minute,start_time,config_item.pull_day)
+        skynet.error(sql)
+        mysqldbx.query(sql)
+    end
+    return true, {}
+end
+
+function M.add_pull_data_config(msg_body)
+    local isok ,key =  tools.checkData({"start","name","interval_minute"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("INSERT INTO `pull_data_config` (start,name,interval_minute)  VALUES ('%s','%s',%d)",msg_body.start,msg_body.name,msg_body.interval_minute)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+function M.delete_pull_data_config(msg_body)
+    local isok ,key =  tools.checkData({"id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("DELETE FROM pull_data_config WHERE id = %d ",msg_body.id)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+function M.pull_data_list(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    local sql = "SELECT * FROM pull_data_config "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldbx.query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM pull_data_config "
+    local total = mysqldbx.query(sql)
+    return true,list,total[1].total
+end
+
+function M.sync_pull_data_config(msg_body)
+    local sql = "SELECT * FROM pull_data_config "
+    local list = mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updatePullConig",data=list}))
+    return true,{}
+end
+return M

+ 17 - 0
service/backmgr/pull_data_status.lua

@@ -0,0 +1,17 @@
+--拉取数据状态
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+function M.getRecord(msg_body)
+    local isok ,key =  tools.checkData({"record_date"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("SELECT * FROM daily_records WHERE record_date = '%s' ",msg_body.record_date)
+    local list = mysqldbx.query(sql)
+    return true,list[1]
+end
+
+return M

+ 17 - 0
service/backmgr/push_msg.lua

@@ -0,0 +1,17 @@
+--推送消息
+local M = {}
+local agent_manager = nil
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+
+function M.push(cmd,msg_body)
+    if not agent_manager then
+        agent_manager = skynet.queryservice("agent_manager")
+    end
+    skynet.fork(function()
+        skynet.sleep(200)
+        skynet.call(agent_manager,"lua",cmd,msg_body)
+    end)
+end
+return M

+ 113 - 0
service/backmgr/review_user.lua

@@ -0,0 +1,113 @@
+--审核员用户
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local mysql = require "skynet.db.mysql"
+local config = require "run_config"
+local mysqldtaskbx = {}
+local db
+function M.Register(msg_body)
+    local isok ,key =  tools.checkData({"name","account","password","Disable","permissions"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("SELECT * FROM review_user WHERE account = '%s' and password = '%s' ", msg_body.account, msg_body.password)
+    local isok,res;
+    res = mysqldtaskbx.Singleton().query(sql)
+    if #res > 0 then
+        return false ,"用户已存在"
+    end
+    sql = string.format("insert into review_user ( name, account,  password, Disable,permissions) values ('%s','%s','%s',%d,%d)",msg_body.name,msg_body.account,msg_body.password,msg_body.Disable,msg_body.permissions)
+    res = mysqldtaskbx.Singleton().query(sql)
+    tools.dump(res)
+    return true, {}
+end
+
+function M.Modify(msg_body)
+    local isok ,key =  tools.checkData({"id","name","password","Disable","permissions"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local sql = string.format("SELECT * FROM review_user WHERE id = %d ", msg_body.id)
+    local isok,res;
+    res = mysqldtaskbx.Singleton().query(sql)
+    if #res < 0 then
+        return false ,"用户不存在"
+    end
+
+    local sql = string.format("UPDATE review_user set name = '%s' , password = '%s' , Disable = %d , permissions = %d WHERE id = %d ", msg_body.name,msg_body.password,msg_body.Disable,msg_body.permissions,msg_body.id)
+    local isok,res;
+    res = mysqldtaskbx.Singleton().query(sql)
+    return true, {}
+end
+
+function M.Login(msg_body)
+    local isok ,key =  tools.checkData({"account","password"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("SELECT * FROM review_user WHERE account = '%s' and password = '%s' ", msg_body.account, msg_body.password)
+    local isok,res;
+    res = mysqldtaskbx.Singleton().query(sql)
+    if #res <= 0 then
+        return false ,"账号或密码错误!"
+    end
+    return true, res
+end
+
+
+function M.Search(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    
+    local sql = "SELECT * FROM review_user WHERE 1=1 "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldtaskbx.Singleton().query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM review_user "
+    local total = mysqldtaskbx.Singleton().query(sql)
+    return true,list,total[1].total
+end
+
+
+function mysqldtaskbx.start()
+    local function on_connect(db)
+        db:query("set charset utf8mb4");
+    end
+    local conf = {
+        ip = 'n8-mr-dsq824ev2pqxbr6rhw.rwlb.rds.aliyuncs.com',
+        port = 3306,
+        user = "zdroot",
+        password = "p0LTZh&CjMl2023",
+        db = "ml_oceanengine"
+    }
+    db = mysql.connect{
+        host=conf.ip,
+        port=conf.port,
+        database=conf.db,
+        user=conf.user,
+        password=conf.password,
+        charset="utf8mb4",
+        max_packet_size = 1024 * 1024,
+        on_connect = on_connect
+    }
+    if not db then
+       skynet.error("mysql connect fail")
+    end
+end
+
+function mysqldtaskbx.Singleton()
+    if db == nil then
+        mysqldtaskbx.start()
+    end
+    return mysqldtaskbx
+end
+function mysqldtaskbx.query(sql)
+    return db:query(sql)
+end
+return M

+ 45 - 0
service/backmgr/statistics_platform.lua

@@ -0,0 +1,45 @@
+--统计平台
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+
+
+function M.add_platform(msg_body)
+    local isok ,key =  tools.checkData({"tg_platform_name","tg_platform_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("INSERT INTO `statistics_platform` (tg_platform_name,tg_platform_id)  VALUES ('%s',%d)",msg_body.tg_platform_name,msg_body.tg_platform_id)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+
+function M.modify(msg_body)
+    local isok ,key =  tools.checkData({"tg_platform_name","id","tg_platform_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE  statistics_platform SET  tg_platform_name = '%s' , tg_platform_id = %d  WHERE id = %d ",msg_body.tg_platform_name, msg_body.tg_platform_id,msg_body.id)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+function M.search(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    
+    local sql = "SELECT * FROM statistics_platform "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldbx.query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM statistics_platform "
+    local total = mysqldbx.query(sql)
+    return true,list,total[1].total
+end
+
+return M

+ 132 - 0
service/backmgr/task_material_queue_queue.lua

@@ -0,0 +1,132 @@
+--计划队列
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+function M.set_sweight(msg_body)
+    local isok ,key =  tools.checkData({"id_list","sweight"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("SELECT * FROM task_material_queue_queue WHERE id IN (%s)",idString)
+    local isok,res;
+    res = mysqldbx.query(sql)
+
+    for i = 1, #res, 1 do
+        local id =   res[i].id
+        sql = string.format("UPDATE  task_material_queue_queue SET sweight = %d WHERE id =%d ",msg_body.sweight,id)
+        mysqldbx.query(sql)
+    end
+
+    return true,{}
+end
+
+function M.search_task_material_queue_queue(msg_body)
+    local isok ,key =  tools.checkData({  "is_copy", "start_publish_time",
+    "end_publish_time","id","butler_id","tg_main_id","page_size","page_number","start_create_time","end_create_time",
+    "tg_platform_id","advertiser_id","advertiser_name","product_id","product_name","material_id","status"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+
+    local date_param = ""
+    if msg_body.start_publish_time~="" and msg_body.end_publish_time~="" then
+        date_param = " AND DATE(publish_time) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_publish_time / 1000) .. ")) AND DATE(publish_time) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_publish_time / 1000) .. ")) "
+    end
+
+    local is_copy_param = ""
+    if msg_body.is_copy~="" then
+        is_copy_param =  " AND is_copy = "..msg_body.is_copy
+    end
+
+    local id_param = ""
+    if msg_body.id~="" then
+        id_param =  " AND id = "..msg_body.id
+    end
+
+    local butler_id_param = ""
+    if msg_body.butler_id~="" then
+        butler_id_param =  " AND butler_id = "..msg_body.butler_id
+    end
+
+    local tg_main_id_param = ""
+    if msg_body.tg_main_id~="" then
+        tg_main_id_param =  " AND tg_main_id = "..msg_body.tg_main_id
+    end
+
+    local tg_platform_id_param = ""
+    if msg_body.tg_platform_id~="" then
+        tg_platform_id_param =  " AND tg_platform_id = "..msg_body.tg_platform_id
+    end
+
+    local advertiser_id_param = ""
+    if msg_body.advertiser_id~="" then
+        advertiser_id_param =  " AND advertiser_id = "..msg_body.advertiser_id
+    end
+
+    local advertiser_name_param = ""
+    if msg_body.advertiser_name~="" then
+        advertiser_name_param =   string.format(" AND  ( advertiser_name LIKE CONCAT( '%%%s%%'))  ",msg_body.advertiser_name)
+    end
+    
+    local product_id_param = ""
+    if msg_body.product_id~="" then
+        product_id_param =  " AND product_id = "..msg_body.product_id
+    end
+
+    local product_name_param = ""
+    if msg_body.product_name~="" then
+        product_name_param =   string.format(" AND  ( product_name LIKE CONCAT( '%%%s%%')) ",msg_body.product_name)
+    end
+
+
+    local material_id_param = ""
+    if msg_body.material_id~="" then
+        material_id_param =   " AND material_id = "..msg_body.material_id
+    end
+
+
+    local status_param = ""
+    if msg_body.status~="" then
+        status_param = " AND status = "..msg_body.status
+    end
+
+    local create_date_param = ""
+    if msg_body.start_create_time~="" and msg_body.end_create_time~="" then
+        create_date_param = " AND DATE(created_at) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_create_time / 1000) .. ")) AND DATE(created_at) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_create_time / 1000) .. "))"
+    end
+
+    local param = date_param..is_copy_param..id_param..tg_main_id_param..butler_id_param..tg_platform_id_param..advertiser_id_param..advertiser_name_param..product_id_param..product_name_param..material_id_param..status_param..create_date_param
+
+    local sql = "SELECT * FROM task_material_queue_queue WHERE 1=1 "..param.." ORDER BY id DESC "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+   
+    local list = mysqldbx.query(sql)
+
+    sql = "SELECT   COUNT(*) AS total  FROM task_material_queue_queue WHERE 1=1  "..param
+
+    local total = mysqldbx.query(sql)
+
+    return true,list,total[1].total
+end
+
+function M.delete_task_material_queue_queue(msg_body)
+    local isok ,key =  tools.checkData({"id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    for i = 1, #msg_body.id_list, 1 do
+        local id = msg_body.id_list[i]
+        local sql = string.format("DELETE FROM task_material_queue_queue WHERE id = %d ",id)
+        mysqldbx.query(sql)
+    end
+    return true, {}
+end
+return M

+ 66 - 0
service/backmgr/tg_butler.lua

@@ -0,0 +1,66 @@
+--管家
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+-- function M.add_butler(msg_body)
+--     local isok ,key =  tools.checkData({"butler_name","butler_id","mail"},msg_body)
+--     if not isok then
+--         return false,string.format("缺少字段: %s.", key)
+--     end
+--     local sql = string.format("INSERT INTO `tg_butler` (butler_name,butler_id,mail)  VALUES ('%s',%d,'%s')",
+--     msg_body.butler_name, msg_body.butler_id, msg_body.mail)
+--     mysqldbx.query(sql)
+--     return true
+-- end
+
+function M.modify_butler(msg_body)
+    local isok ,key =  tools.checkData({"advertiser_ids","oce_product_id","oce_product_platform_id","advertiser_id","butler_name","cc_account_id","mail","id","tg_platform_ids"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE  `advertiser_butler` SET advertiser_ids = '%s' , advertiser_id = %d ,name = '%s', cc_account_id = %d ,email = '%s' , tg_platform_ids = '%s' ,oce_product_id = '%s' , oce_product_platform_id = '%s' WHERE id = %d ",
+    cjson.encode(msg_body.advertiser_ids),msg_body.advertiser_id,msg_body.butler_name,msg_body.cc_account_id,msg_body.mail,msg_body.tg_platform_ids,msg_body.oce_product_id,msg_body.oce_product_platform_id,msg_body.id)
+    skynet.error("sql:",sql)
+    mysqldbx.query(sql)
+    return true
+end
+
+function M.search_butler(msg_body)
+    local isok ,key =  tools.checkData({"name","id","page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+    local param = ""
+
+    local name_param = ""
+    if msg_body.name~="" then
+        name_param =    string.format(" AND  (name LIKE CONCAT( '%%%s%%')) ",msg_body.name)
+     
+    end
+    local id_param = ""
+    if msg_body.id~="" then
+        id_param = string.format(" AND id = %d ",msg_body.id) 
+    end
+
+    param = name_param..id_param
+
+    local sql = "SELECT * FROM advertiser_butler WHERE 1=1 "..param..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+   
+    local list = mysqldbx.query(sql)
+
+    sql = "SELECT   COUNT(*) AS total  FROM advertiser_butler WHERE 1=1  "..param
+
+    skynet.error(sql)
+    local total = mysqldbx.query(sql)
+
+    return true,list,total[1].total
+end
+
+return M

+ 87 - 0
service/backmgr/tg_main_price_template.lua

@@ -0,0 +1,87 @@
+--主体出价模版
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+local config = require "run_config"
+
+function M.add_tg_main_price_template(msg_body)
+    local isok ,key =  tools.checkData({"roi_goal","tf_end_time","name","tg_main_id","cpa_bid","custom_budget","no_bid_budget","tg_main_name","status"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql_param = "INSERT INTO `tg_main_price_template` (roi_goal,tf_end_time,name,tg_main_id,cpa_bid,custom_budget,no_bid_budget,tg_main_name,status) "
+    local  sql = sql_param..string.format("  VALUES (%d,%d,'%s',%d,%d,%d,%d,'%s',%d) ",
+    msg_body.roi_goal,msg_body.tf_end_time,msg_body.name,msg_body.tg_main_id,msg_body.cpa_bid,msg_body.custom_budget,msg_body.no_bid_budget,msg_body.tg_main_name,msg_body.status)
+    mysqldbx.query(sql)
+    return true
+end
+
+function M.modify_tg_main_price_template(msg_body)
+    local isok ,key =  tools.checkData({"roi_goal","tf_end_time","id","name","tg_main_id","cpa_bid","custom_budget","no_bid_budget","tg_main_name","status"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE  `tg_main_price_template` SET roi_goal = %d , tf_end_time = %d , name = '%s' ,tg_main_id = %d , cpa_bid = %d , custom_budget = %d , no_bid_budget = %d , tg_main_name = '%s' ,  status = %d  WHERE id = %d ",
+    msg_body.roi_goal,msg_body.tf_end_time,msg_body.name,msg_body.tg_main_id,msg_body.cpa_bid,msg_body.custom_budget,msg_body.no_bid_budget
+    ,msg_body.tg_main_name,msg_body.status,msg_body.id)
+    mysqldbx.query(sql)
+    return true
+end
+
+function M.search_tg_main_price_template(msg_body)
+    local isok ,key =  tools.checkData({"min_tf_end_time","max_tf_end_time","page_size","page_number","name","status","tg_main_name","cpa_bid","tg_main_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+    local tf_end_time_param = ""
+    if msg_body.min_tf_end_time~="" and msg_body.max_tf_end_time~="" then
+        tf_end_time_param = string.format(" AND  tf_end_time >=%d AND tf_end_time <=%d  ", msg_body.min_tf_end_time,msg_body.max_tf_end_time)
+    end
+
+    local name_param = ""
+    if msg_body.name~="" then
+        name_param = string.format(" AND (name LIKE '%%%s%%' ) ",msg_body.name)
+    end
+
+    local tg_main_name_param = ""
+    if msg_body.tg_main_name~="" then
+        tg_main_name_param = string.format(" AND (tg_main_name LIKE '%%%s%%' ) ",msg_body.tg_main_name)
+    end
+
+    local status_param = ""
+    if msg_body.status~="" then
+        status_param =  string.format(" AND status = %d ",msg_body.status)
+    end
+
+    local tg_main_id_param = ""
+    if msg_body.tg_main_id~="" then
+        tg_main_id_param =  string.format(" AND tg_main_id = %d ",msg_body.tg_main_id)
+    end
+
+    local cpa_bid_param = ""
+    if msg_body.cpa_bid~="" then
+        cpa_bid_param = string.format(" AND cpa_bid LIKE '%%%d%%' ", msg_body.cpa_bid)
+    end
+
+    local param = tf_end_time_param..name_param..tg_main_name_param..status_param..cpa_bid_param..tg_main_id_param
+
+    local sql = "SELECT * FROM tg_main_price_template WHERE 1=1 "..param..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+   
+    skynet.error("sql:",sql)
+    
+    local list = mysqldbx.query(sql)
+
+    sql = "SELECT   COUNT(*) AS total  FROM tg_main_price_template WHERE 1=1  "..param
+
+    local total = mysqldbx.query(sql)
+
+    return true,list,total[1].total
+end
+
+return M

+ 53 - 0
service/backmgr/tg_mini_program_platform.lua

@@ -0,0 +1,53 @@
+--小程序平台
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+function M.add_tg_mini_program_platform(msg_body)
+    local isok ,key =  tools.checkData({"mini_program_platform_name","mini_program_platform_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("INSERT INTO `tg_mini_program_platform` (mini_program_platform_name,mini_program_platform_id)  VALUES ('%s',%d)",
+    msg_body.mini_program_platform_name, msg_body.mini_program_platform_id)
+    mysqldbx.query(sql)
+    return true
+end
+
+function M.modify_tg_mini_program_platform(msg_body)
+    local isok ,key =  tools.checkData({"mini_program_platform_name","mini_program_platform_id","id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    msg_body.update_time = current_time
+    local sql = string.format("UPDATE  `tg_mini_program_platform` SET mini_program_platform_name = '%s' , mini_program_platform_id = %d  WHERE id = %d ",
+    msg_body.mini_program_platform_name,msg_body.mini_program_platform_id,msg_body.id)
+    mysqldbx.query(sql)
+    return true
+end
+
+function M.search_tg_mini_program_platform(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+
+    local sql = "SELECT * FROM tg_mini_program_platform WHERE 1=1 "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+   
+    local list = mysqldbx.query(sql)
+
+    sql = "SELECT   COUNT(*) AS total  FROM tg_mini_program_platform WHERE 1=1  "
+
+    local total = mysqldbx.query(sql)
+
+    return true,list,total[1].total
+end
+
+return M

+ 24 - 0
service/backmgr/user.lua

@@ -0,0 +1,24 @@
+--用户
+local M = {}
+
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+
+
+function M.Login(msg_body)
+    local isok ,key =  tools.checkData({"account","password"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("SELECT * FROM admin_user WHERE account = '%s' and password = '%s' ", msg_body.account, msg_body.password)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res <= 0 then
+        return false ,"账号或密码错误!"
+    end
+    return true, {}
+end
+
+
+return M

+ 289 - 0
service/backmgr/video_applet_product.lua

@@ -0,0 +1,289 @@
+--小程序书籍
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+local config = require "run_config"
+local mysql = require "skynet.db.mysql"
+local db
+local mysqldtaskbx = {}
+
+function M.check_table_exists(table_name)
+    local sql = string.format("SHOW TABLES LIKE '%s'", table_name)
+    local res =  mysqldtaskbx.Singleton().query(sql)
+    return res and #res > 0
+end
+
+function M.add_applet_product(msg_body)
+
+    local isok ,key =  tools.checkData({"butler_id","product_name","product_id","book_platform","dy_small_program_start","dy_small_program_start_data","dy_small_applet_app_id","check_url","main_id","status"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local table_name = "video_applet_product_"..msg_body.butler_id
+
+    if msg_body.isOrigin == 1  then
+        table_name = "video_applet_product"
+    else
+        if not M.check_table_exists(table_name) then
+            return false,string.format("不存在  %s 这个数据.", table_name)
+        end
+    end
+
+    local sql = string.format("INSERT INTO `%s` (product_name,product_id,book_platform,dy_small_program_start,dy_small_program_start_data,dy_small_applet_app_id,check_url,main_id,status,wait_status)  VALUES ('%s','%s',%d,'%s','%s','%s','%s',%d,%d,%d)",
+    table_name,msg_body.product_name,msg_body.product_id,msg_body.book_platform,msg_body.dy_small_program_start,msg_body.dy_small_program_start_data,msg_body.dy_small_applet_app_id,msg_body.check_url,msg_body.main_id,msg_body.status,2)
+    mysqldtaskbx.Singleton().query(sql)
+    return true, {}
+end
+
+--开启小程序书籍任务
+function M.open_app_book_task(msg_body)
+    local isok ,key =  tools.checkData({"butler_id","id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local table_name = "video_applet_product_"..msg_body.butler_id
+
+    if msg_body.isOrigin == 1  then
+        table_name = "video_applet_product"
+    else
+        if not M.check_table_exists(table_name) then
+            return false,string.format("不存在  %s 这个数据.", table_name)
+        end
+    end
+
+    for i = 1, #msg_body.id_list, 1 do
+        local res,sql,id;
+        id = msg_body.id_list[i]
+        sql = string.format("UPDATE  %s SET status = 0 ,  wait_status = 0 ,is_close_execution = 1  WHERE id = %d ",table_name,id)
+        res = mysqldtaskbx.Singleton().query(sql)
+    end
+    return true,{}
+end
+
+
+--开启小程序书籍任务
+function M.open_app_book_task(msg_body)
+    local isok ,key =  tools.checkData({"butler_id","id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local table_name = "video_applet_product_"..msg_body.butler_id
+
+    if msg_body.isOrigin == 1  then
+        table_name = "video_applet_product"
+    else
+        if not M.check_table_exists(table_name) then
+            return false,string.format("不存在  %s 这个数据.", table_name)
+        end
+    end
+
+    for i = 1, #msg_body.id_list, 1 do
+        local res,sql,id;
+        id = msg_body.id_list[i]
+        sql = string.format("UPDATE  %s SET status = 0 ,  wait_status = 0 ,is_close_execution = 1  WHERE id = %d ",table_name,id)
+        res = mysqldtaskbx.Singleton().query(sql)
+    end
+    return true,{}
+end
+
+--开启检测链接任务
+function M.open_check_url_task(msg_body)
+    local isok ,key =  tools.checkData({"butler_id","id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local table_name = "video_applet_product_"..msg_body.butler_id
+
+    if msg_body.isOrigin == 1  then
+        table_name = "video_applet_product"
+    else
+        if not M.check_table_exists(table_name) then
+            return false,string.format("不存在  %s 这个数据.", table_name)
+        end
+    end
+
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("UPDATE  %s SET status = 0 ,  wait_status = 1   WHERE id IN (%s) ",table_name,idString)
+    skynet.error("sql:",sql)
+    mysqldtaskbx.Singleton().query(sql)
+    return true,{}
+end
+
+--设置任务权重
+function M.set_task_weight(msg_body)
+    local isok ,key =  tools.checkData({"butler_id","id_list","weight"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local table_name = "video_applet_product_"..msg_body.butler_id
+
+    if msg_body.isOrigin == 1  then
+        table_name = "video_applet_product"
+    else
+        if not M.check_table_exists(table_name) then
+            return false,string.format("不存在  %s 这个数据.", table_name)
+        end
+    end
+
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("UPDATE  %s SET weight = %d    WHERE id IN (%s) ",table_name,msg_body.weight,idString)
+    skynet.error("sql:",sql)
+    mysqldtaskbx.Singleton().query(sql)
+    return true,{}
+end
+
+function  M.delete(msg_body)
+    local isok ,key =  tools.checkData({"butler_id","id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local table_name = "video_applet_product_"..msg_body.butler_id
+
+    if msg_body.isOrigin == 1  then
+        table_name = "video_applet_product"
+    else
+        if not M.check_table_exists(table_name) then
+            return false,string.format("不存在  %s 这个数据.", table_name)
+        end
+    end
+
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("DELETE FROM %s  WHERE id IN (%s) ",table_name,idString)
+    skynet.error("sql:",sql)
+    mysqldtaskbx.Singleton().query(sql)
+    return true,{}
+end
+
+--搜索小程序书
+--tg_platform_id 平台id
+--product_id 书id
+--product_name 书名
+--main_id 主体ID
+--dy_small_applet_app_id 小程序ID
+function M.search_app_book_data(msg_body)
+    local isok ,key =  tools.checkData({
+    "error_type",
+    "start_first_time",
+    "end_first_time",
+    "error_info",
+    "status",
+    "product_name",
+    "product_id",
+    "tg_platform_id",
+    "main_id",
+    "app_id",
+    "page_size",
+    "page_number","butler_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local table_name = "video_applet_product_"..msg_body.butler_id
+
+    if msg_body.isOrigin == 1  then
+        table_name = "video_applet_product"
+    else
+        if not M.check_table_exists(table_name) then
+            return false,string.format("不存在  %s 这个数据.", table_name)
+        end
+    end
+
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+    local error_type_param = ""
+    if msg_body.error_type~="" then
+        error_type_param = string.format(" AND error_type = %d ",msg_body.error_type)
+    end
+
+    local date_param = ""
+    if msg_body.start_first_time~="" and msg_body.end_first_time~="" then
+        date_param = " AND DATE(first_time) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_first_time / 1000) .. ")) AND DATE(first_time) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_first_time / 1000) .. ")) "
+    end
+
+    local error_info_param = ""
+    if msg_body.error_info~="" then
+        local searchTerm = string.gsub(msg_body.error_info, "%%", "\\%%")
+        error_info_param = string.format("  AND error_info LIKE CONCAT('%%', '%s', '%%')  ",searchTerm)
+    end
+
+    local product_param = ""
+    if msg_body.product_id~="" then
+        product_param =string.format(" AND product_id = '%s' ",msg_body.product_id)
+    end
+    local product_name_param = ""
+    if msg_body.product_name~="" then
+        product_name_param = string.format("AND product_name = '%s' ",msg_body.product_name)
+    end
+    local tg_platform_param = ""
+    if msg_body.tg_platform_id~="" then
+        tg_platform_param = "AND book_platform = "..msg_body.tg_platform_id.." "
+    end
+    local main_param = ""
+    if msg_body.main_id~="" then
+        main_param = "AND main_id = "..msg_body.main_id.." "
+    end
+    local app_param = ""
+    if msg_body.app_id~="" then
+        app_param = string.format("AND dy_small_applet_app_id = '%s' ",msg_body.app_id) 
+    end
+
+    local status_param = ""
+
+    if msg_body.status~="" then
+        status_param = " AND status = "..msg_body.status.." "
+    end
+
+    local param = error_type_param..date_param..error_info_param..product_param..product_name_param..tg_platform_param..main_param..app_param..status_param;
+
+
+    local sql = "SELECT * FROM "..table_name.." WHERE 1=1 "..param.." ORDER BY id DESC "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldtaskbx.Singleton().query(sql)
+
+    sql = "SELECT   COUNT(*) AS total  FROM "..table_name.."  WHERE 1=1 "..param.." ORDER BY id DESC "
+
+    local total = mysqldtaskbx.Singleton().query(sql)
+
+    return true,list,total[1].total
+end
+
+function mysqldtaskbx.start()
+    local function on_connect(db)
+        db:query("set charset utf8mb4");
+    end
+    local conf = config.db_cnf.book_server.mysqldb_task_cnf
+    db = mysql.connect{
+        host=conf.ip,
+        port=conf.port,
+        database=conf.db,
+        user=conf.user,
+        password=conf.password,
+        charset="utf8mb4",
+        max_packet_size = 1024 * 1024,
+        on_connect = on_connect
+    }
+    if not db then
+       skynet.error("mysql connect fail")
+    end
+end
+
+function mysqldtaskbx.Singleton()
+    if db == nil then
+        mysqldtaskbx.start()
+    end
+    return mysqldtaskbx
+end
+function mysqldtaskbx.query(sql)
+    return db:query(sql)
+end
+
+return M

+ 331 - 0
service/backmgr/video_material.lua

@@ -0,0 +1,331 @@
+--推广
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+local config = require "run_config"
+local db
+--设置推广状态
+function M.set_tui_guang_status(msg_body)
+    local isok ,key =  tools.checkData({"id_list","status"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("SELECT * FROM video_material WHERE id IN (%s)",idString)
+    local isok,res;
+    res = mysqldbx.query(sql)
+
+    for i = 1, #res, 1 do
+        local id =   res[i].id
+        local material_id = res[i].material_id
+        sql = string.format("UPDATE  video_material SET status = %d WHERE id =%d ",msg_body.status,id)
+        mysqldbx.query(sql)
+    end
+    
+    return true,{}
+end
+
+--设置审核状态
+function M.set_artificial_status(msg_body)
+    local isok ,key =  tools.checkData({"id_list","artificial_status","user_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("SELECT * FROM video_material WHERE id IN (%s)",idString)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    for i = 1, #res, 1 do
+        local id =   res[i].id
+        sql = string.format("UPDATE  video_material SET opt_time = '%s' ,artificial_status = %d , exe_review_person_id = %d WHERE id =%d ",current_time,msg_body.artificial_status,msg_body.user_id,id)
+        mysqldbx.query(sql)
+    end
+    
+    return true,{}
+end
+
+--搜索推广数据
+--oce_material_id 推广素材id
+--book_platform 平台id
+--product_id 书id
+--sync_status 状态
+function M.search(msg_body)
+    local isok ,key =  tools.checkData({
+    "start_publish_time",
+    "end_publish_time",
+    "start_yun_fabu_time",
+    "end_yun_fabu_time",
+    "start_opt_time",
+    "end_opt_time",
+    "exe_review_person_id","min_book_word","max_book_word","genre","end_time_date",
+    "start_time_date",
+    "sync_status",
+    "product_id",
+    "tg_platform_id",
+    "oce_material_id",
+    "product_name",
+    "material_id",
+    "page_size",
+    "page_number",
+    "dy_id",
+    "d_z",
+    "comment",
+    "collect",
+    "forward",
+    "status",
+    "signature",
+    "dy_id_1","artificial_status","machine_review_status","is_sexual_inducement_content","is_bad_value_view","user_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+
+    local publish_time_param = ""
+    if msg_body.start_publish_time~="" and msg_body.end_publish_time~="" then
+        publish_time_param = " AND DATE(publish_time) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_publish_time / 1000) .. ")) AND DATE(publish_time) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_publish_time / 1000) .. ")) "
+    end
+
+    local yun_fabu_time_param = ""
+    if msg_body.start_yun_fabu_time~="" and msg_body.end_yun_fabu_time~="" then
+        yun_fabu_time_param = " AND DATE(yun_fabu_time) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_yun_fabu_time / 1000) .. ")) AND DATE(yun_fabu_time) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_yun_fabu_time / 1000) .. "))"
+    end
+
+    local opt_time_param = ""
+    if msg_body.start_opt_time~="" and msg_body.end_opt_time~="" then
+        opt_time_param = " AND DATE(opt_time) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_opt_time / 1000) .. ")) AND DATE(opt_time) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_opt_time / 1000) .. "))"
+    end
+
+    local exe_review_person_id_param = ""
+    if msg_body.exe_review_person_id~="" then
+        exe_review_person_id_param = string.format(" AND exe_review_person_id = %d ",tonumber(msg_body.exe_review_person_id)) 
+    end
+
+
+    local user_id_param = ""
+    if msg_body.user_id~="" then
+        user_id_param = string.format(" AND user_id = %d ",tonumber(msg_body.user_id)) 
+    end
+
+    local word_param = ""
+    if msg_body.min_book_word~="" and msg_body.max_book_word~="" then
+        word_param =  string.format(" AND CAST(words AS UNSIGNED) >= %f  AND CAST(words AS UNSIGNED) <= %f ",msg_body.min_book_word,msg_body.max_book_word)
+    end
+
+    local product_param = ""
+    if msg_body.product_id~="" then
+        product_param =  string.format(" AND product_id = %d ",tonumber(msg_body.product_id))
+    end
+
+
+    local product_name_param = ""
+    if msg_body.product_name~="" then
+        product_name_param = string.format("AND product_name = '%s' ",msg_body.product_name) 
+    end
+
+    local is_auto_param = ""
+    if msg_body.dy_id~="" then
+        if msg_body.dy_id~=0 then
+            is_auto_param = " AND dy_id != 0"
+        else
+            is_auto_param = " AND dy_id = 0"
+        end
+    end
+
+
+    local genre_param = ""
+    if msg_body.genre~="" then
+        genre_param =  string.format(" AND genre = %d ",tonumber(msg_body.genre)) 
+    end
+
+
+    local material_id_param = ""
+    if msg_body.material_id~="" then
+        material_id_param =  string.format(" AND id = %d ",tonumber(msg_body.material_id)) 
+    end
+
+    local oce_material_param = ""
+    if msg_body.oce_material_id~="" then
+        oce_material_param =string.format("AND oce_material_id =  %d ",tonumber(msg_body.oce_material_id))
+    end
+    local tg_platform_param = ""
+    if msg_body.tg_platform_id~="" then
+        tg_platform_param = " AND book_platform = "..msg_body.tg_platform_id.." "
+    end
+
+    local date_param = ""
+    if msg_body.start_time_date~="" and msg_body.end_time_date~="" then
+        date_param = " AND DATE(create_at) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_time_date / 1000) .. ")) AND DATE(create_at) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_time_date / 1000) .. "))"
+    end
+
+    local sync_status_param = ""
+
+    if msg_body.sync_status~="" then
+        sync_status_param = " AND sync_status = "..msg_body.sync_status.." "
+    end
+
+
+    local status_param = ""
+
+    if msg_body.status~="" then
+        status_param = " AND status = "..msg_body.status.." "
+    end
+
+    local artificial_status_param = ""
+    if msg_body.artificial_status~="" then
+        artificial_status_param = " AND artificial_status = "..msg_body.artificial_status.." "
+    end
+
+    local machine_review_status_param = ""
+    if msg_body.machine_review_status~="" then
+        machine_review_status_param = " AND machine_review_status = "..msg_body.machine_review_status.." "
+    end
+
+    local is_sexual_inducement_content_param = ""
+    if msg_body.is_sexual_inducement_content~="" then
+        is_sexual_inducement_content_param = " AND is_sexual_inducement_content = "..msg_body.is_sexual_inducement_content.." "
+    end
+
+    local is_bad_value_view_param = ""
+    if msg_body.is_bad_value_view~="" then
+        is_bad_value_view_param = " AND is_bad_value_view = "..msg_body.is_bad_value_view.." "
+    end
+
+    local signature_param = ""
+    if msg_body.signature~="" then
+        signature_param = string.format("AND signature = '%s' ",msg_body.signature)
+    end
+
+    local dy_id_1_param = ""
+    if msg_body.dy_id_1~="" then
+        dy_id_1_param = " AND dy_id =  "..tonumber(msg_body.dy_id_1)
+    end
+
+    local d_z_param = ""
+    if msg_body.d_z~="" then
+        if(msg_body.d_z == 0) then
+            d_z_param = " d_z_number ASC"
+        else
+            d_z_param = " d_z_number DESC"
+        end
+    end
+   
+    local comment_param = ""
+    if msg_body.comment~="" then
+        if(msg_body.comment == 0) then
+            comment_param = " comment_number ASC"
+        else
+            comment_param = " comment_number DESC"
+        end
+    end
+
+    local forward_param = ""
+    if msg_body.forward~="" then
+        if(msg_body.forward == 0) then
+            forward_param = " forward_number ASC"
+        else
+            forward_param = " forward_number DESC"
+        end
+    end
+    
+    local collect_param = ""
+    if msg_body.collect~="" then
+        if(msg_body.collect == 0) then
+            collect_param = " collect_number ASC"
+        else
+            collect_param = " collect_number DESC"
+        end
+    end
+    
+
+
+    -----
+    local stat_cost_param = ""
+    if msg_body.stat_cost~="" then
+        if(msg_body.stat_cost == 0) then
+            stat_cost_param = " stat_cost ASC"
+        else
+            stat_cost_param = " stat_cost DESC"
+        end
+    end
+   
+    local show_cnt_param = ""
+    if msg_body.show_cnt~="" then
+        if(msg_body.show_cnt == 0) then
+            show_cnt_param = " comment_number ASC"
+        else
+            show_cnt_param = " comment_number DESC"
+        end
+    end
+
+    local click_cnt_param = ""
+    if msg_body.click_cnt~="" then
+        if(msg_body.click_cnt == 0) then
+            click_cnt_param = " click_cnt ASC"
+        else
+            click_cnt_param = " click_cnt DESC"
+        end
+    end
+    
+    local convert_cnt_param = ""
+    if msg_body.convert_cnt~="" then
+        if(msg_body.convert_cnt == 0) then
+            convert_cnt_param = " convert_cnt ASC"
+        else
+            convert_cnt_param = " convert_cnt DESC"
+        end
+    end
+
+
+    local cvr_param = ""
+    if msg_body.cvr~="" then
+        if(msg_body.cvr == 0) then
+            cvr_param = " cvr ASC"
+        else
+            cvr_param = " cvr DESC"
+        end
+    end
+    
+    local ctr_param = ""
+    if msg_body.ctr~="" then
+        if(msg_body.ctr == 0) then
+            ctr_param = " ctr ASC"
+        else
+            ctr_param = " ctr DESC"
+        end
+    end
+
+    local new_param = stat_cost_param..show_cnt_param..click_cnt_param..convert_cnt_param..cvr_param..ctr_param
+    -----
+    local param = publish_time_param..yun_fabu_time_param..opt_time_param..exe_review_person_id_param..word_param..genre_param..date_param..product_param..oce_material_param..status_param..tg_platform_param..sync_status_param..product_name_param..is_auto_param..material_id_param..signature_param..dy_id_1_param..artificial_status_param..machine_review_status_param..is_sexual_inducement_content_param..is_bad_value_view_param..user_id_param
+
+    local up_down_param = d_z_param..comment_param..forward_param..collect_param..new_param
+
+    if up_down_param ~= "" then
+        up_down_param = " ORDER BY " ..up_down_param
+    else
+        up_down_param = " ORDER BY id DESC "
+    end
+
+    local sql = "SELECT * FROM video_material  WHERE  1=1 "..param..up_down_param..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+   
+    local res = mysqldbx.query(sql)
+
+    skynet.error("sql:",sql)
+
+    sql =  "SELECT COUNT(*) AS total FROM video_material  WHERE  1=1 "..param.." ORDER BY id DESC "
+    
+    local total = mysqldbx.query(sql)
+
+    return true,res,total[1].total
+end
+
+return M

+ 375 - 0
service/backmgr/video_product.lua

@@ -0,0 +1,375 @@
+--书库
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+local config = require "run_config"
+local mysql = require "skynet.db.mysql"
+local db
+local mysqldtaskbx = {}
+
+--搜索书
+--tg_platform_id 平台id
+--product_id 书id
+--product_name 书名
+function M.search_book_data(msg_body)
+    local isok ,key =  tools.checkData({
+    "start_create_at",
+    "end_create_at",
+    "product_parent_id",
+    "is_top",
+    "status",
+    "start_publish_time",
+    "end_publish_time",
+    "up_or_down_publish_time",
+    "min_book_word",
+    "max_book_word",
+    "alias_name",
+    "product_name",
+    "product_id",
+    "tg_platform_id",
+    "oce_material_id",
+    "page_size",
+    "page_number",
+    "is_auto",
+    "stat_cost","min_totalChapterNum","max_totalChapterNum"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+    local product_parent_id_param = ""
+    if msg_body.product_parent_id~="" then
+        product_parent_id_param = string.format(" AND product_parent_id = '%s' ",msg_body.product_parent_id)
+    end
+
+    local is_top_param = ""
+    if msg_body.is_top~="" then
+        is_top_param = string.format(" AND is_top = %d ",msg_body.is_top)
+    end
+
+    local status_param = ""
+    if msg_body.status~="" then
+        status_param = string.format(" AND status = %d ",msg_body.status)
+    end
+
+    local date_param = ""
+    if msg_body.start_publish_time~="" and msg_body.end_publish_time~="" then
+        date_param = " AND DATE(publish_time) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_publish_time / 1000) .. ")) AND DATE(publish_time) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_publish_time / 1000) .. ")) "
+    end
+
+    local create_date_param = ""
+    if msg_body.start_create_at~="" and msg_body.end_create_at~="" then
+        create_date_param = " AND DATE(create_at) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_create_at / 1000) .. ")) AND DATE(create_at) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_create_at / 1000) .. ")) "
+    end
+
+    local up_or_down_publish_time_param = ""
+    if msg_body.up_or_down_publish_time~="" then
+        if(msg_body.up_or_down_publish_time == 0) then
+            up_or_down_publish_time_param = " publish_time ASC"
+        else
+            up_or_down_publish_time_param = " publish_time DESC"
+        end
+    end
+
+    local word_param = ""
+    if msg_body.min_book_word~="" and msg_body.max_book_word~="" then
+        word_param =  string.format(" AND CAST(words AS UNSIGNED) >= %f  AND CAST(words AS UNSIGNED) <= %f ",msg_body.min_book_word,msg_body.max_book_word)
+    end
+
+    local stat_cost_param = ""
+    if msg_body.stat_cost~="" then
+        if(msg_body.stat_cost == 0) then
+            stat_cost_param = " stat_cost ASC"
+        else
+            stat_cost_param = " stat_cost DESC"
+        end
+    end
+
+    local totalChapterNum_param = ""
+    if msg_body.min_totalChapterNum~="" and msg_body.max_totalChapterNum~="" then
+        totalChapterNum_param =  string.format(" AND totalChapterNum >= %d  AND totalChapterNum <= %d ",msg_body.min_totalChapterNum,msg_body.max_totalChapterNum)
+    end
+
+
+    local product_param = ""
+    if msg_body.product_id~="" then
+        product_param = string.format(" AND product_id = '%s' ",msg_body.product_id)
+    end
+
+    local product_name_param = ""
+    if msg_body.product_name~="" then
+        product_name_param = string.format(" AND  ( product_name LIKE CONCAT( '%%%s%%')) ",msg_body.product_name)
+    end
+    local tg_platform_param = ""
+    if msg_body.tg_platform_id~="" then
+        tg_platform_param = string.format(" AND book_platform = %d ",msg_body.tg_platform_id) 
+    end
+    local is_auto_param = ""
+    if msg_body.is_auto~="" then
+        is_auto_param = " AND is_auto = "..msg_body.is_auto.." "
+    end
+
+    local is_store_param = ""
+    if msg_body.is_store~="" then
+        is_store_param = " AND is_store = "..msg_body.is_store.." "
+    end
+
+    local genre_param = ""
+    if msg_body.genre~="" then
+        genre_param = " AND genre = "..msg_body.genre.." "
+    end
+
+    local alias_name_param = ""
+    if msg_body.alias_name~="" then
+        alias_name_param = string.format(" AND  ( alias_name LIKE CONCAT( '%%%s%%')) ",msg_body.alias_name)
+    end
+
+    local param = create_date_param..product_parent_id_param..is_top_param..status_param..date_param..totalChapterNum_param..product_param..product_name_param..tg_platform_param..is_auto_param..is_store_param..genre_param..alias_name_param..word_param;
+
+    if stat_cost_param~="" and up_or_down_publish_time_param ~="" then
+        up_or_down_publish_time_param = " , "..up_or_down_publish_time_param
+    end
+    local up_down_param = stat_cost_param..up_or_down_publish_time_param
+
+    if up_down_param ~= "" then
+        up_down_param = " ORDER BY " ..up_down_param
+    else
+        up_down_param =  "ORDER BY id DESC"
+    end
+    local sql = "SELECT * FROM video_product where 1=1 "..param..up_down_param..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    
+
+    local res = mysqldtaskbx.Singleton().query(sql)
+
+    sql =  "SELECT  COUNT(*) AS total  FROM video_product where 1=1 "..param.."ORDER BY id DESC"
+
+    local total = mysqldtaskbx.Singleton().query(sql)
+
+    return true,res,total[1].total
+end
+
+--一键发布搜索
+function M.search_book_data_on_main(msg_body)
+    local isok ,key =  tools.checkData({
+    "start_publish_time",
+    "end_publish_time",
+    "alias_name",
+    "product_name",
+    "product_id",
+    "tg_platform_id",
+    "oce_material_id",
+    "page_size",
+    "page_number",
+    "is_auto",
+    "stat_cost",
+    "min_book_word",
+    "max_book_word",
+    "min_stat_cost",
+    "max_stat_cost"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+    local status_param = string.format(" AND status = %d ",1)
+
+    local date_param = ""
+    if msg_body.start_publish_time~="" and msg_body.end_publish_time~="" then
+        date_param = " AND DATE(publish_time) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_publish_time / 1000) .. ")) AND DATE(publish_time) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_publish_time / 1000) .. ")) "
+    end
+
+    local word_param = ""
+    if msg_body.min_book_word~="" and msg_body.max_book_word~="" then
+        word_param =  string.format(" AND CAST(words AS UNSIGNED) >= %d  AND CAST(words AS UNSIGNED) <= %d ",msg_body.min_book_word,msg_body.max_book_word)
+    end
+
+    local stat_cost_param = ""
+    if msg_body.min_stat_cost~="" and msg_body.max_stat_cost~="" then
+        stat_cost_param =  string.format(" AND stat_cost >= %f  AND stat_cost <= %f ",msg_body.min_stat_cost,msg_body.max_stat_cost)
+    end
+
+    local product_param = ""
+    if msg_body.product_id~="" then
+        product_param = string.format(" AND product_id = '%s' ",msg_body.product_id)
+    end
+    local product_name_param = ""
+    if msg_body.product_name~="" then
+        product_name_param = string.format(" AND  ( product_name LIKE CONCAT( '%%%s%%')) ",msg_body.product_name)
+    end
+    local tg_platform_param = ""
+    if msg_body.tg_platform_id~="" then
+        tg_platform_param = string.format(" AND book_platform = %d ",msg_body.tg_platform_id) 
+    end
+    local is_auto_param = ""
+    if msg_body.is_auto~="" then
+        is_auto_param = " AND is_auto = "..msg_body.is_auto.." "
+    end
+
+    local is_store_param = ""
+    if msg_body.is_store~="" then
+        is_store_param = " AND is_store = "..msg_body.is_store.." "
+    end
+
+    local genre_param = ""
+    if msg_body.genre~="" then
+        genre_param = " AND genre = "..msg_body.genre.." "
+    end
+
+    local alias_name_param = ""
+    if msg_body.alias_name~="" then
+        alias_name_param = string.format(" AND  ( alias_name LIKE CONCAT( '%%%s%%')) ",msg_body.alias_name)
+    end
+
+    local param = status_param..date_param..stat_cost_param..word_param..product_param..product_name_param..tg_platform_param..is_auto_param..is_store_param..genre_param..alias_name_param;
+
+    local sql =  string.format("SELECT v.* FROM video_product v JOIN ( SELECT id FROM video_product WHERE  1=1 %s ORDER BY is_top DESC , id ASC LIMIT %d OFFSET %d ) AS tmp ON v.id = tmp.id",param,page_size,offset)
+    
+    skynet.error("sql:",sql)
+    local res = mysqldtaskbx.Singleton().query(sql)
+
+    sql =  "SELECT  COUNT(*) AS total  FROM video_product where 1=1 "..param
+
+    local total = mysqldtaskbx.Singleton().query(sql)
+
+    return true,res,total[1].total
+end
+
+--设置书别名
+function M.set_video_product_alias_name(msg_body)
+    local isok ,key =  tools.checkData({"id","alias_name"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local sql = string.format("UPDATE  `video_product` SET alias_name = '%s'  WHERE id = %d ",
+    msg_body.alias_name,msg_body.id)
+    local res = mysqldtaskbx.Singleton().query(sql)
+    return true,{}
+end
+
+--设置书类型(长篇,短片)
+function M.set_video_product_genre(msg_body)
+    local isok ,key =  tools.checkData({"genre","id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("UPDATE  video_product SET genre = %d WHERE id IN (%s) ",msg_body.genre,idString)
+    mysqldtaskbx.Singleton().query(sql)
+    return true, {}
+end
+
+--设置书状态
+function M.set_status(msg_body)
+    local isok ,key =  tools.checkData({"status","id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("UPDATE  video_product SET status = %d WHERE id IN (%s) ",msg_body.status,idString)
+    mysqldtaskbx.Singleton().query(sql)
+    return true, {}
+end
+
+--设置书优先级
+function M.set_top(msg_body)
+    local isok ,key =  tools.checkData({"expired_time","id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    -- local current_time = os.date("%Y-%m-%d %H:%M:%S")
+    local sql  = ""
+    local isok,res;
+    for i = 1, #msg_body.id_list, 1 do
+        local id = msg_body.id_list[i]
+        sql = string.format("SELECT * FROM video_product where id = %d ", id)
+        res = mysqldtaskbx.Singleton().query(sql)
+        if #res >0 then
+            local publish_time = res[1].publish_time
+            local y_publish_time = res[1].y_publish_time
+            if y_publish_time~=nil then
+                publish_time = y_publish_time
+            end
+            sql = string.format("UPDATE  video_product SET is_top = 1 , expired_time = '%s' , y_publish_time = '%s' WHERE id = %d ",msg_body.expired_time,publish_time,id)
+            mysqldtaskbx.Singleton().query(sql)
+        end
+     end
+    -- local idString = table.concat(msg_body.id_list, ",")
+    -- local sql = string.format("UPDATE  video_product SET is_top = 1 , expired_time = '%s' WHERE id IN (%s) ",msg_body.expired_time,idString)
+    -- mysqldtaskbx.Singleton().query(sql)
+    return true, {}
+end
+
+--设置默认付费章节
+function M.set_default_pay_section(msg_body)
+    local isok ,key =  tools.checkData({"default_pay_section","id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("UPDATE  video_product SET default_pay_section = %d WHERE id IN (%s) ",msg_body.default_pay_section,idString)
+    mysqldtaskbx.Singleton().query(sql)
+    return true, {}
+end
+
+--设置价格
+function M.set_default_default_price(msg_body)
+    local isok ,key =  tools.checkData({"default_price","id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("UPDATE  video_product SET default_price = %f WHERE id IN (%s) ",msg_body.default_price,idString)
+    mysqldtaskbx.Singleton().query(sql)
+    return true, {}
+end
+
+--设置书籍定价方式
+function M.set_fee_unit(msg_body)
+    local isok ,key =  tools.checkData({"fee_unit","id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("UPDATE  video_product SET fee_unit = %d WHERE id IN (%s) ",msg_body.fee_unit,idString)
+    mysqldtaskbx.Singleton().query(sql)
+    return true, {}
+end
+
+function mysqldtaskbx.start()
+    local function on_connect(db)
+        db:query("set charset utf8mb4");
+    end
+    local conf = config.db_cnf.book_server.mysqldb_task_cnf
+    db = mysql.connect{
+        host=conf.ip,
+        port=conf.port,
+        database=conf.db,
+        user=conf.user,
+        password=conf.password,
+        charset="utf8mb4",
+        max_packet_size = 1024 * 1024,
+        on_connect = on_connect
+    }
+    if not db then
+       skynet.error("mysql connect fail")
+    end
+end
+
+function mysqldtaskbx.Singleton()
+    if db == nil then
+        mysqldtaskbx.start()
+    end
+    return mysqldtaskbx
+end
+function mysqldtaskbx.query(sql)
+    return db:query(sql)
+end
+
+return M

+ 182 - 0
service/backmgr/video_product_material.lua

@@ -0,0 +1,182 @@
+--下载队列
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+local mysql = require "skynet.db.mysql"
+local config = require "run_config"
+local db
+local mysqldtaskbx = {}
+function M.set_status(msg_body)
+    local isok ,key =  tools.checkData({"id_list","is_download"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("SELECT * FROM video_product_material WHERE id IN (%s)",idString)
+    local isok,res;
+    res = mysqldtaskbx.Singleton().query(sql)
+
+    for i = 1, #res, 1 do
+        local id =   res[i].id
+        sql = string.format("UPDATE  video_product_material SET is_download = %d  WHERE id =%d ",msg_body.is_download,id)
+        mysqldtaskbx.Singleton().query(sql)
+    end
+
+    return true,{}
+end
+
+function M.set_d_z_number(msg_body)
+    local isok ,key =  tools.checkData({"id_list","d_z_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("SELECT * FROM video_product_material WHERE id IN (%s)",idString)
+    local isok,res;
+    res = mysqldtaskbx.Singleton().query(sql)
+
+    for i = 1, #res, 1 do
+        local id =   res[i].id
+        sql = string.format("UPDATE  video_product_material SET  d_z_number = %d WHERE id =%d ",msg_body.d_z_number,id)
+        mysqldtaskbx.Singleton().query(sql)
+    end
+
+    return true,{}
+end
+
+function M.search_video_product_material(msg_body)
+    local isok ,key =  tools.checkData({"page_size",
+    "page_number",
+    "start_create_time",
+    "end_create_time",
+    "dy_id",
+    "product_id",
+    "product_name",
+    "book_platform",
+    "title",
+    "is_download",
+    "signature",
+    "cleaning_status"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+    local dy_id_param = ""
+    if msg_body.dy_id~="" then
+        dy_id_param =  " AND dy_id = "..msg_body.dy_id
+    end
+
+    local product_id_param = ""
+    if msg_body.product_id~="" then
+        product_id_param =  " AND product_id = "..msg_body.product_id
+    end
+
+    local product_name_param = ""
+    if msg_body.product_name~="" then
+        product_name_param =   string.format(" AND  ( product_name LIKE CONCAT( '%%%s%%'))  ",msg_body.product_name)
+    end
+    
+    local book_platform_param = ""
+    if msg_body.book_platform~="" then
+        book_platform_param =  " AND book_platform = "..msg_body.book_platform
+    end
+
+    local title_param = ""
+    if msg_body.title~="" then
+        title_param =    string.format(" AND  ( product_name LIKE CONCAT( '%%%s%%'))  ",msg_body.title)
+    end
+
+    local is_download_param = ""
+    if msg_body.is_download~="" then
+        is_download_param =   " AND is_download = "..msg_body.is_download
+    end
+
+
+    local status_param = ""
+    -- if msg_body.status~="" then
+    --     status_param = " AND status = "..msg_body.status
+    -- end
+
+    local signature_param = ""
+    if msg_body.signature~="" then
+        signature_param = string.format(" AND signature = '%s' ",msg_body.signature) 
+    end
+
+    local cleaning_status_param = ""
+    if msg_body.cleaning_status~="" then
+        cleaning_status_param = " AND cleaning_status = "..msg_body.cleaning_status
+    end
+
+
+    local create_date_param = ""
+    if msg_body.start_create_time~="" and msg_body.end_create_time~="" then
+        create_date_param = " AND create_day >= DATE(FROM_UNIXTIME(" .. (msg_body.start_create_time / 1000) .. ")) AND create_day <= DATE(FROM_UNIXTIME(" .. (msg_body.end_create_time / 1000) .. ")) "
+    end
+
+    local param = dy_id_param..product_id_param..product_name_param..book_platform_param..title_param..is_download_param..status_param..create_date_param..cleaning_status_param
+
+    local sql = "SELECT * FROM video_product_material WHERE dy_id!=0  "..param..  " ORDER BY update_time DESC "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+   
+    skynet.error("sql:",sql)
+    
+    local list =  mysqldtaskbx.Singleton().query(sql)
+
+    sql = "SELECT   COUNT(*) AS total  FROM video_product_material  WHERE dy_id!=0  "..param
+
+    local total = mysqldtaskbx.Singleton().query(sql)
+
+    return true,list,total[1].total
+end
+
+function M.delete_video_product_material(msg_body)
+    local isok ,key =  tools.checkData({"id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    for i = 1, #msg_body.id_list, 1 do
+        local id = msg_body.id_list[i]
+        local sql = string.format("DELETE FROM video_product_material WHERE id = %d ",id)
+        mysqldtaskbx.Singleton().query(sql)
+    end
+    return true, {}
+end
+
+
+function mysqldtaskbx.start()
+    local function on_connect(db)
+        db:query("set charset utf8mb4");
+    end
+    local conf = config.db_cnf.book_server.mysqldb_task_cnf
+    db = mysql.connect{
+        host=conf.ip,
+        port=conf.port,
+        database=conf.db,
+        user=conf.user,
+        password=conf.password,
+        charset="utf8mb4",
+        max_packet_size = 1024 * 1024,
+        on_connect = on_connect
+    }
+    if not db then
+       skynet.error("mysql connect fail")
+    end
+end
+
+function mysqldtaskbx.Singleton()
+    if db == nil then
+        mysqldtaskbx.start()
+    end
+    return mysqldtaskbx
+end
+function mysqldtaskbx.query(sql)
+    return db:query(sql)
+end
+
+return M

+ 124 - 0
service/backmgr/video_titles.lua

@@ -0,0 +1,124 @@
+--视频标题
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local md5 =	require	"md5"
+
+
+function M.add_video_title(msg_body)
+    local isok ,key =  tools.checkData({"title_list","pay_type","title_type_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local pay_type = msg_body.pay_type
+    local title_type_id = msg_body.title_type_id
+    for i = 1, #msg_body.title_list, 1 do
+        local title = msg_body.title_list[i].title
+        local md5_tag = msg_body.title_list[i].md5_tag
+        local sql = string.format("SELECT * FROM video_titles WHERE md5_tag = '%s' LIMIT 1", md5_tag)
+        local isok,res;
+        res = mysqldbx.query(sql)
+        if #res > 0 then
+
+        else
+            sql = string.format("INSERT INTO `video_titles` (title,md5_tag,pay_type,title_type_id)  VALUES ('%s','%s',%d,%d)",title,md5_tag,pay_type,title_type_id)
+            mysqldbx.query(sql)
+        end
+
+    end
+    return true, {}
+end
+
+function M.delete_video_title(msg_body)
+    local isok ,key =  tools.checkData({"id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    for i = 1, #msg_body.id_list, 1 do
+        local id = msg_body.id_list[i]
+        local sql = string.format("DELETE FROM video_titles WHERE id = %d ",id)
+        mysqldbx.query(sql)
+    end
+    return true, {}
+end
+
+function M.modify_video_title(msg_body)
+    local isok ,key =  tools.checkData({"title","md5_tag","id","pay_type","title_type_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE  video_titles SET title_type_id = %d , pay_type = %d , title = '%s' , md5_tag = '%s' WHERE id = %d ",msg_body.title_type_id,msg_body.pay_type,msg_body.title,msg_body.md5_tag,msg_body.id)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+function M.modify_pay_type(msg_body)
+    local isok ,key =  tools.checkData({"id_list","pay_type"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local idString = table.concat(msg_body.id_list, ",")
+    sql = string.format("UPDATE `video_titles` SET pay_type = %d WHERE id IN (%s) ",msg_body.pay_type,idString)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+function M.modify_title_type_id(msg_body)
+    local isok ,key =  tools.checkData({"id_list","title_type_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local idString = table.concat(msg_body.id_list, ",")
+    sql = string.format("UPDATE `video_titles` SET title_type_id = %d WHERE id IN (%s) ",msg_body.title_type_id,idString)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+function M.search_video_title(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number","content","pay_type","title_type_id"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+    local content_param = ""
+    if msg_body.content~=""then
+        content_param = string.format(" AND  (title LIKE CONCAT( '%%%s%%')) ",msg_body.content)
+    end
+
+    local pay_type_param = ""
+    if msg_body.pay_type~=""then
+        pay_type_param = string.format(" AND  pay_type = %d ",msg_body.pay_type)
+    end
+
+    local title_type_id_param = ""
+    if msg_body.title_type_id~=""then
+        title_type_id_param = string.format(" AND  title_type_id = %d ",msg_body.title_type_id)
+    end
+
+    local param = content_param..pay_type_param..title_type_id_param
+    local sql = "SELECT * FROM video_titles WHERE 1=1 "..param.." ORDER BY id DESC".. string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldbx.query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM video_titles  WHERE 1=1 "..param
+    local total = mysqldbx.query(sql)
+    return true,list,total[1].total
+end
+
+function M.initAll()
+    local sql = "SELECT * FROM video_titles "
+    local list = mysqldbx.query(sql)
+    for i = 1, #list, 1 do
+        if (list[i].md5_tag==nil) then
+            local id = list[i].id
+            local md5_tag =md5.sumhexa(list[i].title)
+            skynet.error("md5_tag:",md5_tag)
+            sql = string.format("UPDATE  video_titles SET md5_tag = '%s' WHERE id = %d ",md5_tag,id)
+            mysqldbx.query(sql)
+        end
+    end
+    return true,{}
+end
+return M

+ 112 - 0
service/backmgr/wechat_miniapp_product.lua

@@ -0,0 +1,112 @@
+--微信小程序产品表
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+function M.set_sweight(msg_body)
+    local isok ,key =  tools.checkData({"sweight","id_list"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local idString = table.concat(msg_body.id_list, ",")
+    local sql = string.format("UPDATE  wechat_miniapp_product SET sweight = %d WHERE id IN (%s) ",msg_body.sweight,idString)
+    mysqldbx.query(sql)
+    return true, {}
+end
+
+function M.search(msg_body)
+    local isok ,key =  tools.checkData({
+        "start_publish_time",
+        "end_publish_time",
+        "main_id",
+        "start_create_time",
+        "end_create_time",
+        "audit_status",
+        "ldy_audit_status",
+        "product_name",
+        "product_id",
+        "create_status",
+        "share_status",
+        "ldy_create_status",
+        "ldy_share_status",
+        "page_size",
+        "page_number"
+    },msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+
+    local date_param = ""
+    if msg_body.start_publish_time~="" and msg_body.end_publish_time~="" then
+        date_param = " AND DATE(publish_time) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_publish_time / 1000) .. ")) AND DATE(publish_time) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_publish_time / 1000) .. ")) "
+    end
+
+    local main_param = ""
+    if msg_body.main_id~="" then
+        main_param = string.format(" AND main_id = %d ",tonumber(msg_body.main_id))
+    end
+
+    local create_date_param = ""
+    if msg_body.start_create_time~="" and msg_body.end_create_time~="" then
+        create_date_param = " AND DATE(create_time) >= DATE(FROM_UNIXTIME(" .. (msg_body.start_create_time / 1000) .. ")) AND DATE(create_time) <= DATE(FROM_UNIXTIME(" .. (msg_body.end_create_time / 1000) .. "))"
+    end
+
+    local audit_status_param = ""
+    if msg_body.audit_status~="" then
+        audit_status_param = string.format(" AND audit_status = %d ",tonumber(msg_body.audit_status))
+    end
+
+    local ldy_audit_status_param = ""
+    if msg_body.ldy_audit_status~="" then
+        ldy_audit_status_param = string.format(" AND ldy_audit_status = %d ",tonumber(msg_body.ldy_audit_status))
+    end
+
+    local product_param = ""
+    if msg_body.product_id~="" then
+        product_param = string.format(" AND product_id = '%s' ",msg_body.product_id)
+    end
+
+    local product_name_param = ""
+    if msg_body.product_name~="" then
+        product_name_param = string.format(" AND  ( product_name LIKE CONCAT( '%%%s%%')) ",msg_body.product_name)
+    end
+
+    local create_status_param = ""
+    if msg_body.create_status~="" then
+        create_status_param = string.format(" AND create_status = %d ",msg_body.create_status)
+    end
+
+    local share_status_param = ""
+    if msg_body.share_status~="" then
+        share_status_param = string.format(" AND share_status = %d ",msg_body.share_status)
+    end
+
+    local ldy_create_status_param = ""
+    if msg_body.ldy_create_status~="" then
+        ldy_create_status_param = string.format(" AND ldy_create_status = %d ",msg_body.ldy_create_status)
+    end
+
+    local ldy_share_status_param = ""
+    if msg_body.ldy_share_status~="" then
+        ldy_share_status_param = string.format(" AND ldy_share_status = %d ",msg_body.ldy_share_status)
+    end
+
+    local param = date_param..product_param..product_name_param..ldy_share_status_param..ldy_create_status_param..share_status_param..create_status_param..ldy_audit_status_param..audit_status_param..create_date_param..main_param
+
+    local sql = "SELECT * FROM wechat_miniapp_product WHERE 1=1 "..param.."ORDER BY sweight DESC"..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+   
+    local list = mysqldbx.query(sql)
+
+    sql = "SELECT   COUNT(*) AS total  FROM wechat_miniapp_product WHERE 1=1  "..param
+
+    local total = mysqldbx.query(sql)
+
+    return true,list,total[1].total
+end
+
+return M

+ 58 - 0
service/backmgr/yw_book.lua

@@ -0,0 +1,58 @@
+--阅文
+local M = {}
+local mysqldbx = require "mysqldbx"
+local tools = require "tools"
+local skynet = require "skynet"
+local cjson = require "cjson"
+
+function M.get_all_yw_key()
+    local sql = "SELECT * FROM yw_book_config "
+    local res = mysqldbx.query(sql)
+    return true,res
+end
+
+function M.add_yw_book_open_sessid(msg_body)
+    local isok ,key =  tools.checkData({"open_sessid","name"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("SELECT * FROM yw_book_config WHERE open_sessid = '%s' LIMIT 1", msg_body.open_sessid)
+    local isok,res;
+    res = mysqldbx.query(sql)
+    if #res > 0 then
+        return false ,"open_sessid :"..msg_body.open_sessid.." 已存在!"
+    end
+    sql = string.format("INSERT INTO `yw_book_config` (open_sessid,name)  VALUES ('%s','%s')",msg_body.open_sessid,msg_body.name)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateYwKeyList"}))
+    return true, {}
+end
+
+function M.modify_yw_book_open_sessid(msg_body)
+    local isok ,key =  tools.checkData({"open_sessid","id","name"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local sql = string.format("UPDATE  yw_book_config SET open_sessid = '%s' ,  name = '%s' WHERE id =%d ",msg_body.open_sessid,msg_body.name,msg_body.id)
+    mysqldbx.query(sql)
+    skynet.send("backmgr","lua","on_recv",nil,"ws_push_msg",cjson.encode({cmd="updateYwKeyList"}))
+    return true, {}
+end
+
+
+
+function M.get_list(msg_body)
+    local isok ,key =  tools.checkData({"page_size","page_number"},msg_body)
+    if not isok then
+        return false,string.format("缺少字段: %s.", key)
+    end
+    local page_size = msg_body.page_size
+    local page_number = msg_body.page_number
+    local offset = (page_number - 1) * page_size
+    local sql = "SELECT * FROM yw_book_config "..string.format(" LIMIT %d OFFSET %d ",page_size, offset)
+    local list = mysqldbx.query(sql)
+    sql = "SELECT   COUNT(*) AS total  FROM yw_book_config "
+    local total = mysqldbx.query(sql)
+    return true,list,total[1].total
+end
+return M

+ 223 - 0
service/doc/cmd_sql.sql

@@ -0,0 +1,223 @@
+create table novel_tab (  
+	id int not null auto_increment COMMENT '唯一id',
+	book_name  varchar(1024) not null COMMENT '小说名字',
+	book_id  int DEFAULT 0 COMMENT '书id',	
+	appid int DEFAULT 0 COMMENT '小程序id',	
+	create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+	info JSON COMMENT '详情',
+	primary key (id));
+
+create table account_tab (  
+	id int not null auto_increment COMMENT '唯一id',
+	account_id   int DEFAULT 0 COMMENT '账号id',	
+	account_type   int DEFAULT 0 COMMENT '账号类型',	
+	is_open   int DEFAULT 0 COMMENT '是否开启',	
+	create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+	info JSON COMMENT '详情',
+	primary key (id));
+	create table classification_list_tab (  
+	id int not null auto_increment COMMENT '唯一id',
+	create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+	info JSON  COMMENT  '详情',
+	self_id int not NULL,
+	primary key (id));
+
+create table fan_qie_book_tab (
+	id int not null auto_increment COMMENT '唯一id',
+	book_name  varchar(1024) not null COMMENT '小说名字',
+	book_id   varchar(1024) not null COMMENT '书id',	
+	author varchar(1024) not null COMMENT '作者',
+	category varchar(1024) not null COMMENT '分类',
+	chapter_amount int not NULL COMMENT '章节数',
+	latest_update_time varchar(1024) not null COMMENT '更新时间',
+	creation_status int not null COMMENT '书本完结状态,0为已完结,1为连载中',
+	genre int not null COMMENT '体裁(设置定价时,请关注该字段)- 0:长篇网文- 8:短故事- 202:付费短剧',
+	length_type int not null COMMENT '短故事类型(设置定价时,请关注该字段)- 0:多章- 2:整本',
+	info JSON  COMMENT  '详情',
+primary key (id));
+
+
+create table auto_book_link (
+	id int not null auto_increment COMMENT '唯一id',
+	book_name  varchar(1024) DEFAULT "" COMMENT '小说名字',
+	book_id   varchar(1024) DEFAULT "" COMMENT '书id',
+	type   varchar(1024) DEFAULT "" COMMENT '类型',	
+	info JSON  COMMENT  '详情',
+primary key (id));
+
+
+create table tg_platform (
+	id int not null auto_increment COMMENT '唯一id',
+	tg_platform_id int,
+primary key (id));
+
+
+create table admin_user (  
+	id int not null auto_increment COMMENT '唯一id',
+	account   varchar(1024) DEFAULT "" COMMENT '账号',	
+	password   varchar(1024) DEFAULT "" COMMENT '密码',	
+	primary key (id));
+
+create table tg_app (  
+	id int not null auto_increment COMMENT '唯一id',
+	tg_platform_id int not null  COMMENT '平台id',	
+	app_id   varchar(1024) not null COMMENT '小程序ID',	
+	advertiser_id   varchar(1024) not null COMMENT '所属账户ID',	
+	instance_id   varchar(1024) not null COMMENT '资产ID',	
+	name   varchar(1024) not null COMMENT '小程序名称',	
+	create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+	update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+	primary key (id));
+
+create table tg_main (  
+	id int not null auto_increment COMMENT '唯一id',
+	tg_platform_id int not null  COMMENT '平台id',	
+	app_id   varchar(1024) not null COMMENT '小程序ID',	
+	main_name   varchar(1024) not null COMMENT '主体名称',	
+	create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+	update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+	primary key (id));
+
+create table db_filter_config (  
+	id int not null auto_increment COMMENT '唯一id',
+	config_id int   COMMENT '配置id',	
+	config JSON  COMMENT  '配置',
+	primary key (id));
+
+--原始数据
+create table origin_data (  
+	id int not null auto_increment COMMENT '唯一id',
+	video_id  varchar(100)  COMMENT '视频id',	
+	video_link  varchar(300)  COMMENT '视频链接',	
+	title varchar(300)  COMMENT '标题',
+	publish_time TIMESTAMP  COMMENT '发布时间',
+	kepp_num int  COMMENT '收藏数',
+	comment_num int  COMMENT '评论数',
+	like_num int  COMMENT '点赞数',
+	shared_num int  COMMENT '分享数',
+	is_guajian int  COMMENT '是否挂件',
+	guajian_link varchar(1024)  COMMENT '挂件地址',
+	primary key (id));
+
+--筛选数据
+create table filter_data (  
+	id int not null auto_increment COMMENT '唯一id',
+	info JSON  COMMENT  '详情',
+	primary key (id));
+--书籍数据
+create table book_data (  
+	id int not null auto_increment COMMENT '唯一id',
+	info JSON  COMMENT  '详情',
+	primary key (id));
+
+--收集后的数据
+create table collect_data (  
+	id int not null auto_increment COMMENT '唯一id',
+	info JSON  COMMENT  '详情',
+	primary key (id));
+
+CREATE TABLE `filter_data` (
+    `id` int NOT NULL AUTO_INCREMENT COMMENT '唯一id',
+    `video_id` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '视频id',
+    `video_link` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '视频链接',
+    `title` varchar(300) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '标题',
+    `publish_time` timestamp NULL DEFAULT NULL COMMENT '发布时间',
+    `kepp_num` int DEFAULT NULL COMMENT '收藏数',
+    `comment_num` int DEFAULT NULL COMMENT '评论数',
+    `like_num` int DEFAULT NULL COMMENT '点赞数',
+    `shared_num` int DEFAULT NULL COMMENT '分享数',
+    `is_guajian` int DEFAULT NULL COMMENT '是否挂件',
+	`book_id` varchar(300) DEFAULT NULL COMMENT '书id',
+	`book_name` varchar(300)  DEFAULT NULL COMMENT '书名字',
+	`genre`  int   DEFAULT 0 COMMENT '长中短分类',
+	`words`  varchar(300)   DEFAULT '0' COMMENT '字数',
+    `guajian_link` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '挂件地址',
+    `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
+    PRIMARY KEY (`id`)
+) ENGINE = InnoDB AUTO_INCREMENT = 6470 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci
+
+
+
+create table get_fq_book_tab (  
+	id int not null auto_increment COMMENT '唯一id',
+	book_key  varchar(100)  COMMENT 'key',	
+	book_id  varchar(100)  COMMENT 'book_id',	
+	info JSON  COMMENT  '详情',
+	primary key (id));
+
+create table fq_book_config (  
+	id int not null auto_increment COMMENT '唯一id',
+	sid_tt  varchar(100)  COMMENT 'sid_tt',	
+	create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+	primary key (id));
+
+create table black_list (  
+	id int not null auto_increment COMMENT '唯一id',
+	product_id  varchar(64),	
+	product_name  varchar(64),
+	create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+	primary key (id));
+
+create table pull_log (  
+id int not null auto_increment COMMENT '唯一id',
+create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+primary key (id));
+
+create table pull_data_config (  
+id int not null auto_increment COMMENT '唯一id',
+name  varchar(100)  COMMENT '名称',	
+start  varchar(100)  COMMENT '开始拉取数据的事件的时间',	
+interval_minute  int  COMMENT '从开始时间向前间隔多少分钟',	
+create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+primary key (id));
+
+
+
+create table other_book (  
+	id int not null auto_increment COMMENT '唯一id',
+	product_id  varchar(64),	
+	product_name  varchar(64),
+	tg_platform_id int not null  COMMENT '平台id',	
+	create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+primary key (id));
+
+create table tg_butler (  
+	id int not null auto_increment COMMENT '唯一id',
+	butler_name  varchar(64),	
+	butler_id  int,	
+	mail varchar(500),	
+	create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+primary key (id));
+
+
+create table tg_mini_program_platform (  
+	id int not null auto_increment COMMENT '唯一id',
+	mini_program_platform_name  varchar(64),	
+	mini_program_platform_id  int,	
+	create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+primary key (id));
+
+
+create table ad_convert_type (  
+	id int not null auto_increment COMMENT '唯一id',
+	name  varchar(64),	
+	ad_convert_type  int,	
+	create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+primary key (id));
+
+
+create table platform_shared (  
+	id int not null auto_increment COMMENT '唯一id',
+	name  varchar(64),	
+	info JSON  COMMENT  '共享体',
+	create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+primary key (id));
+
+
+create table yw_book_config (  
+	id int not null auto_increment COMMENT '唯一id',
+	name  varchar(64),	
+	open_sessid  varchar(255),	
+	`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
+primary key (id));
+

+ 48 - 0
service/http_work/init.lua

@@ -0,0 +1,48 @@
+local skynet = require "skynet"
+-- local httpc = require "http.httpc"
+-- local httpurl = require "http.url"
+-- local dns = require "skynet.dns"
+local httpd = require "http.httpd"
+local sockethelper = require "http.sockethelper"
+local socket = require "skynet.socket"
+local cjson = require "cjson"
+local tools = require "tools"
+
+local function handle_options(fd, header)
+    local response_header = {
+        ['Access-Control-Allow-Origin'] = '*',
+        ['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS, PUT, DELETE',
+        ['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization',
+        ['Access-Control-Allow-Credentials'] = 'true',
+        ['Content-Length'] = '0'
+    }
+    
+    local content = ""
+    local ok, err = httpd.write_response(sockethelper.writefunc(fd), 200, response_header, content)
+    return ok
+end
+local dispatch = function(session, address,id, addr,...)
+    socket.start(id)
+    local req= tools.read_request(id)
+    if req.url == nil or #req.url==0 or req.code~=200 or #req.body==0 then
+        skynet.error(req.url)
+        skynet.error("错误访问:")
+        tools.dump({address=address,id=id,addr=addr,other=...})
+        return  tools.response(id, req.code, "error!")
+    end
+      -- 处理 OPTIONS 请求
+    -- if req.method == "OPTIONS" then
+    --     handle_options(id,req.header)
+    --     socket.close(id)
+    --     return tools.response(id, req.code, "error!")
+    -- end
+
+    if string.find(req.url, "tg/back/") then
+        local func_list = string.split(req.url ,"/")
+        skynet.send("backmgr","lua","on_recv",id,func_list[#func_list],req.body)
+        return
+    end
+end
+skynet.start(function()
+    skynet.dispatch("lua", dispatch)
+end)

+ 78 - 0
service/main.lua

@@ -0,0 +1,78 @@
+local skynet = require "skynet"
+
+local httpc = require "http.httpc"
+local httpurl = require "http.url"
+local dns = require "skynet.dns"
+local runconfig = require "run_config"
+local socket = require "skynet.socket"
+local httpd = require "http.httpd"
+local sockethelper = require "http.sockethelper"
+local cjson = require "cjson"
+local skynet_manager = require "skynet.manager"
+local function http_test(protocol)
+	--httpc.dns()	-- set dns server
+	httpc.timeout = 100	-- set timeout 1 second
+	print("GET baidu.com")
+	protocol = protocol or "http"
+	local respheader = {}
+	local host = string.format("%s://baidu.com", protocol)
+	print("geting... ".. host)
+	local status, body = httpc.get(host, "/", respheader)
+	print("[header] =====>")
+	for k,v in pairs(respheader) do
+		print(k,v)
+	end
+	print("[body] =====>", status)
+	print(body)
+
+	local respheader = {}
+	local ip = dns.resolve "baidu.com"
+	print(string.format("GET %s (baidu.com)", ip))
+	local status, body = httpc.get(host, "/", respheader, { host = "baidu.com" })
+	print(status)
+end
+
+local function response(id, ...)
+    local ok, err = httpd.write_response(sockethelper.writefunc(id), ...)
+    if not ok then
+        -- if err == sockethelper.socket_error , that means socket closed.
+        skynet.error(string.format("fd = %d, %s", id, err))
+    end
+end
+
+function json_test()
+    local myTable = {name = "John", age = 30, city = "New York"}
+    local jsonStr = cjson.encode(myTable)
+    print(jsonStr)
+    jsonStr = '{"name":"John","age":30,"city":"New York"}'
+    local decodedTable = cjson.decode(jsonStr)
+    print(decodedTable.name)
+    print(decodedTable.age)
+    print(decodedTable.city)
+
+end
+
+skynet.start(function()
+	skynet.uniqueservice("dbproxy", "book_server")
+
+	skynet.uniqueservice("agent_manager", "agent_manager")
+
+	local back_srv = skynet.newservice("backmgr", "backmgr", 0)
+	skynet.name("backmgr", back_srv)
+
+	--接收消息的服务
+	local httpworks = {}
+	local protocol = "http" 
+	for i= 1, 30 do --开启30个服务用来接收消息
+		httpworks[i] = skynet.newservice("http_work", "http_work", protocol)
+	end
+	local http_balance = 1
+	local id = socket.listen("0.0.0.0",runconfig.httpProt )
+	socket.start(id , function(id, addr)
+		skynet.send(httpworks[http_balance], "lua", id,addr)
+		http_balance = http_balance + 1
+		if http_balance > #httpworks then
+			http_balance = 1
+		end
+	end)
+end)

+ 20 - 0
service/tools_work/init.lua

@@ -0,0 +1,20 @@
+local skynet = require "skynet"
+local s = require "service"
+local tools = require "tools"
+local cjson = require "cjson"
+local httpc = require "http.httpc"
+local runconfig = require "run_config"
+
+
+s.resp.on_recv = function (source, fd, msg_id, msg_body)
+    skynet.error("接收一条工具消息 ",msg_id)
+    local func = string.gsub(msg_id, "/tools/", "")
+    if s.resp[func] ~=nil then
+        return s.resp[func](fd,msg_body)
+    end
+    return tools.response(fd,200,string.format("接口 %s 不存在",func))
+end
+
+
+
+s.start(...)

+ 62 - 0
service/userlog.lua

@@ -0,0 +1,62 @@
+local skynet = require "skynet"
+require "skynet.manager"
+local fd=nil
+local fname=nil
+local logfolder =nil
+
+skynet.register_protocol {
+    name = "text",
+    id = skynet.PTYPE_TEXT,
+    unpack = skynet.tostring,
+    dispatch = function(_, address, msg)
+        if not logfolder then
+            return
+        end
+        local now=os.date("*t",os.time())
+        local s=""..now.year..now.month..now.day
+        local foldername = string.format("%d_%02d_%02d.log",now.year,now.month,now.day)
+
+        local logpath=logfolder..foldername
+        if (not fname) or logpath~=fname then
+            if fd then
+                fd:close()
+                fd=nil
+            end
+            fname = logpath
+        end
+
+        if not fd then
+            fd=io.open(logpath,"a+")
+        end
+
+        if fd then
+            local content = string.format("%s:%08x(%.2f): %s",os.date("%y/%m/%d %H:%M:%S"), address, skynet.time(), msg..'\r\n')
+            print(content)
+            fd:write(content)
+            fd:flush()
+        else
+            --print(fname)
+        end
+    end
+
+}
+
+skynet.register_protocol {
+    name = "SYSTEM",
+    id = skynet.PTYPE_SYSTEM,
+    unpack = function(...) return ... end,
+    dispatch = function()
+        if not fd then
+            fd:close()
+            fname=nil
+        end
+    end
+
+}
+
+skynet.start(function()
+    skynet.error("PROJ_ROOT::",PROJ_ROOT)
+    logfolder ="../".."/log/"
+    local err=os.execute("mkdir "..logfolder)
+    skynet.register ".logger"
+end)