diff --git a/.gitignore b/.gitignore
index a673aae09..f4c3accfa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -188,7 +188,6 @@ plugins/tidb
plugins/goedge-admin
plugins/goedge-node
plugins/goedge-happy
-plugins/dztasks
/logs
/data
diff --git a/plugins/dztasks/LICENSE b/plugins/dztasks/LICENSE
new file mode 100644
index 000000000..72eb80c30
--- /dev/null
+++ b/plugins/dztasks/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 mw-plugin
+
+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.
diff --git a/plugins/dztasks/README.md b/plugins/dztasks/README.md
new file mode 100644
index 000000000..b76c36c0f
--- /dev/null
+++ b/plugins/dztasks/README.md
@@ -0,0 +1,8 @@
+# dztasks
+任务调度
+
+
+### 安装
+```
+rm -rf /www/server/mdserver-web/plugins/dztasks && cd /www/server/mdserver-web/plugins && rm -rf dztasks && git clone https://github.com/mw-plugin/dztasks && cd dztasks && rm -rf .git && cd /www/server/mdserver-web/plugins/dztasks && bash install.sh install 1.1
+```
diff --git a/plugins/dztasks/config/dztasks.conf b/plugins/dztasks/config/dztasks.conf
new file mode 100644
index 000000000..6e1763b51
--- /dev/null
+++ b/plugins/dztasks/config/dztasks.conf
@@ -0,0 +1,19 @@
+app_name = dztasks
+run_mode = prod
+
+[web]
+http_port = 11011
+
+[session]
+provider = file
+
+[admin]
+user = {$ADMIN_NAME}
+pass = {$ADMIN_PASS}
+
+[plugins]
+path = {$SERVER_APP}/plugins
+
+[security]
+install_lock = true
+secret_key = VQOXEKGNIAIDXQI
diff --git a/plugins/dztasks/ico.png b/plugins/dztasks/ico.png
new file mode 100644
index 000000000..5aafecd96
Binary files /dev/null and b/plugins/dztasks/ico.png differ
diff --git a/plugins/dztasks/index.html b/plugins/dztasks/index.html
new file mode 100755
index 000000000..2c720f057
--- /dev/null
+++ b/plugins/dztasks/index.html
@@ -0,0 +1,32 @@
+
+
+
+
\ No newline at end of file
diff --git a/plugins/dztasks/index.py b/plugins/dztasks/index.py
new file mode 100755
index 000000000..81e52dbf4
--- /dev/null
+++ b/plugins/dztasks/index.py
@@ -0,0 +1,318 @@
+# coding:utf-8
+
+import sys
+import io
+import os
+import time
+import re
+
+web_dir = os.getcwd() + "/web"
+if os.path.exists(web_dir):
+ sys.path.append(web_dir)
+ os.chdir(web_dir)
+
+import core.mw as mw
+
+app_debug = False
+if mw.isAppleSystem():
+ app_debug = True
+
+
+def getPluginName():
+ return 'dztasks'
+
+
+def getPluginDir():
+ return mw.getPluginDir() + '/' + getPluginName()
+
+
+def getServerDir():
+ return mw.getServerDir() + '/' + getPluginName()
+
+
+def getInitDFile():
+ current_os = mw.getOs()
+ if current_os == 'darwin':
+ return '/tmp/' + getPluginName()
+
+ if current_os.startswith('freebsd'):
+ return '/etc/rc.d/' + getPluginName()
+
+ return '/etc/init.d/' + getPluginName()
+
+
+def getConf():
+ path = getServerDir() + "/custom/conf/app.conf"
+ return path
+
+
+def getConfTpl():
+ path = getPluginDir() + "/config/dztasks.conf"
+ return path
+
+
+def getInitDTpl():
+ path = getPluginDir() + "/init.d/" + getPluginName() + ".tpl"
+ return path
+
+
+def getArgs():
+ args = sys.argv[3:]
+ tmp = {}
+ args_len = len(args)
+
+ if args_len == 1:
+ t = args[0].strip('{').strip('}')
+ if t.strip() == '':
+ tmp = []
+ else:
+ t = t.split(':')
+ tmp[t[0]] = t[1]
+ tmp[t[0]] = t[1]
+ elif args_len > 1:
+ for i in range(len(args)):
+ t = args[i].split(':')
+ tmp[t[0]] = t[1]
+ return tmp
+
+def checkArgs(data, ck=[]):
+ for i in range(len(ck)):
+ if not ck[i] in data:
+ return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
+ return (True, mw.returnJson(True, 'ok'))
+
+def configTpl():
+ # path = getPluginDir() + '/tpl'
+ # pathFile = os.listdir(path)
+ tmp = []
+ return mw.getJson(tmp)
+
+
+def readConfigTpl():
+ args = getArgs()
+ data = checkArgs(args, ['file'])
+ if not data[0]:
+ return data[1]
+
+ content = mw.readFile(args['file'])
+ content = contentReplace(content)
+ return mw.returnJson(True, 'ok', content)
+
+def getPidFile():
+ file = getConf()
+ content = mw.readFile(file)
+ rep = r'pidfile\s*(.*)'
+ tmp = re.search(rep, content)
+ return tmp.groups()[0].strip()
+
+def status():
+ cmd = "ps aux|grep dztasks|grep -v grep|grep -v python|grep -v mdserver-web|awk '{print $2}'"
+ data = mw.execShell(cmd)
+ if data[0] == '':
+ return 'stop'
+ return 'start'
+
+def contentReplace(content):
+ service_path = mw.getServerDir()
+ content = content.replace('{$ROOT_PATH}', mw.getFatherDir())
+ content = content.replace('{$SERVER_PATH}', service_path)
+ content = content.replace('{$SERVER_APP}', service_path + '/dztasks')
+ content = content.replace('{$ADMIN_NAME}', mw.getRandomString(6))
+ content = content.replace('{$ADMIN_PASS}', mw.getRandomString(10))
+ return content
+
+
+
+def initDreplace():
+
+ file_tpl = getInitDTpl()
+ service_path = mw.getServerDir()
+
+ initD_path = getServerDir() + '/init.d'
+ if not os.path.exists(initD_path):
+ os.mkdir(initD_path)
+ file_bin = initD_path + '/' + getPluginName()
+
+ # initd replace
+ if not os.path.exists(file_bin):
+ content = mw.readFile(file_tpl)
+ content = contentReplace(content)
+ mw.writeFile(file_bin, content)
+ mw.execShell('chmod +x ' + file_bin)
+
+ # log
+ dataLog = getServerDir() + '/data'
+ if not os.path.exists(dataLog):
+ mw.execShell('chmod +x ' + file_bin)
+
+ app_dir = getServerDir() + '/custom/conf'
+ if not os.path.exists(app_dir):
+ mw.execShell('mkdir -p ' + app_dir)
+
+ # config replace
+ dst_conf = getServerDir() + '/custom/conf/app.conf'
+ dst_conf_init = getServerDir() + '/init.pl'
+ if not os.path.exists(dst_conf_init):
+ content = mw.readFile(getConfTpl())
+ # print(content)
+ content = contentReplace(content)
+ mw.writeFile(dst_conf, content)
+ mw.writeFile(dst_conf_init, 'ok')
+
+ # systemd
+ systemDir = mw.systemdCfgDir()
+ systemService = systemDir + '/' + getPluginName() + '.service'
+ if os.path.exists(systemDir) and not os.path.exists(systemService):
+ systemServiceTpl = getPluginDir() + '/init.d/' + getPluginName() + '.service.tpl'
+ content = mw.readFile(systemServiceTpl)
+ content = contentReplace(content)
+ mw.writeFile(systemService, content)
+ mw.execShell('systemctl daemon-reload')
+
+ return file_bin
+
+
+def dzOp(method):
+ file = initDreplace()
+
+ current_os = mw.getOs()
+ if current_os == "darwin":
+ data = mw.execShell(file + ' ' + method)
+ if data[1] == '':
+ return 'ok'
+ return data[1]
+
+ if current_os.startswith("freebsd"):
+ data = mw.execShell('service ' + getPluginName() + ' ' + method)
+ if data[1] == '':
+ return 'ok'
+ return data[1]
+
+ data = mw.execShell('systemctl ' + method + ' ' + getPluginName())
+ if data[1] == '':
+ return 'ok'
+ return data[1]
+
+
+def start():
+ return dzOp('start')
+
+
+def stop():
+ return dzOp('stop')
+
+
+def restart():
+ status = dzOp('restart')
+
+ log_file = runLog()
+ mw.execShell("echo '' > " + log_file)
+ return status
+
+def reload():
+ return dzOp('reload')
+
+def initdStatus():
+ current_os = mw.getOs()
+ if current_os == 'darwin':
+ return "Apple Computer does not support"
+
+ if current_os.startswith('freebsd'):
+ initd_bin = getInitDFile()
+ if os.path.exists(initd_bin):
+ return 'ok'
+
+ shell_cmd = 'systemctl status ' + \
+ getPluginName() + ' | grep loaded | grep "enabled;"'
+ data = mw.execShell(shell_cmd)
+ if data[0] == '':
+ return 'fail'
+ return 'ok'
+
+
+def initdInstall():
+ current_os = mw.getOs()
+ if current_os == 'darwin':
+ return "Apple Computer does not support"
+
+ # freebsd initd install
+ if current_os.startswith('freebsd'):
+ import shutil
+ source_bin = initDreplace()
+ initd_bin = getInitDFile()
+ shutil.copyfile(source_bin, initd_bin)
+ mw.execShell('chmod +x ' + initd_bin)
+ mw.execShell('sysrc ' + getPluginName() + '_enable="YES"')
+ return 'ok'
+
+ mw.execShell('systemctl enable ' + getPluginName())
+ return 'ok'
+
+
+def initdUinstall():
+ current_os = mw.getOs()
+ if current_os == 'darwin':
+ return "Apple Computer does not support"
+
+ if current_os.startswith('freebsd'):
+ initd_bin = getInitDFile()
+ os.remove(initd_bin)
+ mw.execShell('sysrc ' + getPluginName() + '_enable="NO"')
+ return 'ok'
+
+ mw.execShell('systemctl disable ' + getPluginName())
+ return 'ok'
+
+
+def runLog():
+ return getServerDir() + '/logs.pl'
+
+
+def getDzPort():
+ file = getConf()
+ content = mw.readFile(file)
+ rep = r'port\s*=\s*(.*)'
+ tmp = re.search(rep, content)
+ return tmp.groups()[0].strip()
+
+def homePage():
+ http_port = getDzPort()
+ ip = mw.getLocalIp()
+ if mw.isAppleSystem():
+ ip = '127.0.0.1'
+ url = 'http://'+ip+":"+str(http_port)
+ # print(url)
+ return mw.returnJson(True, 'ok!', url)
+
+if __name__ == "__main__":
+ func = sys.argv[1]
+ if func == 'status':
+ print(status())
+ elif func == 'start':
+ print(start())
+ elif func == 'stop':
+ print(stop())
+ elif func == 'restart':
+ print(restart())
+ elif func == 'reload':
+ print(reload())
+ elif func == 'initd_status':
+ print(initdStatus())
+ elif func == 'initd_install':
+ print(initdInstall())
+ elif func == 'initd_uninstall':
+ print(initdUinstall())
+ elif func == 'run_info':
+ print(runInfo())
+ elif func == 'conf':
+ print(getConf())
+ elif func == 'run_log':
+ print(runLog())
+ elif func == 'config_tpl':
+ print(configTpl())
+ elif func == 'read_config_tpl':
+ print(readConfigTpl())
+ elif func == 'home_page':
+ print(homePage())
+ else:
+ print('error')
diff --git a/plugins/dztasks/info.json b/plugins/dztasks/info.json
new file mode 100755
index 000000000..93bfbd1fc
--- /dev/null
+++ b/plugins/dztasks/info.json
@@ -0,0 +1,17 @@
+{
+ "sort": 7,
+ "ps": "任务调度管理",
+ "name": "dztasks",
+ "title": "dztasks",
+ "shell": "install.sh",
+ "versions":["1.1"],
+ "tip": "soft",
+ "checks": "server/dztasks",
+ "path": "server/dztasks",
+ "display": 1,
+ "author": "dztasks",
+ "date": "2024-10-06",
+ "home": "",
+ "type": 0,
+ "pid": "5"
+}
diff --git a/plugins/dztasks/init.d/dztasks.service.tpl b/plugins/dztasks/init.d/dztasks.service.tpl
new file mode 100644
index 000000000..fd57a35ec
--- /dev/null
+++ b/plugins/dztasks/init.d/dztasks.service.tpl
@@ -0,0 +1,21 @@
+[Unit]
+Description=dztasks server
+After=network.service
+After=syslog.target
+
+[Service]
+User=root
+Group=root
+Type=simple
+WorkingDirectory={$SERVER_PATH}/dztasks
+ExecStart={$SERVER_PATH}/dztasks/dztasks web
+ExecReload=/bin/kill -USR2 $MAINPID
+PermissionsStartOnly=true
+LimitNOFILE=5000
+Restart=on-failure
+RestartSec=10
+RestartPreventExitStatus=1
+PrivateTmp=false
+
+[Install]
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/plugins/dztasks/init.d/dztasks.tpl b/plugins/dztasks/init.d/dztasks.tpl
new file mode 100644
index 000000000..dff29eb38
--- /dev/null
+++ b/plugins/dztasks/init.d/dztasks.tpl
@@ -0,0 +1,64 @@
+#!/bin/sh
+# chkconfig: 2345 55 25
+# description: dztasks Service
+
+### BEGIN INIT INFO
+# Provides: dztasks
+# Required-Start: $all
+# Required-Stop: $all
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: starts dztasks
+# Description: starts the MDW-Web
+### END INIT INFO
+
+# Simple dztasks init.d script conceived to work on Linux systems
+# as it does use of the /proc filesystem.
+
+RED='\033[31m'
+GREEN='\033[32m'
+YELLOW='\033[33m'
+BLUE='\033[34m'
+PLAIN='\033[0m'
+BOLD='\033[1m'
+SUCCESS='[\033[32mOK\033[0m]'
+COMPLETE='[\033[32mDONE\033[0m]'
+WARN='[\033[33mWARN\033[0m]'
+ERROR='[\033[31mERROR\033[0m]'
+WORKING='[\033[34m*\033[0m]'
+
+app_start(){
+ echo "Starting dztasks server..."
+ cd {$SERVER_PATH}/dztasks
+ ./dztasks web >> {$SERVER_PATH}/dztasks/logs.pl 2>&1 &
+}
+
+app_stop(){
+ echo "dztasks stopp start"
+ pids=`ps -ef| grep dztasks | grep -v grep | grep -v python | grep -v sh | awk '{print $2}'`
+ arr=($pids)
+ for p in ${arr[@]}
+ do
+ kill -9 $p > /dev/null 2>&1
+ done
+ echo "dztasks stopp end"
+}
+
+
+case "$1" in
+ start)
+ app_start
+ ;;
+ stop)
+ app_stop
+ ;;
+ restart|reload)
+ app_stop
+ sleep 0.3
+ app_start
+ ;;
+ *)
+ echo "Please use start or stop as first argument"
+ ;;
+esac
+
diff --git a/plugins/dztasks/install.sh b/plugins/dztasks/install.sh
new file mode 100755
index 000000000..de3a6941f
--- /dev/null
+++ b/plugins/dztasks/install.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
+export PATH
+
+curPath=`pwd`
+rootPath=$(dirname "$curPath")
+rootPath=$(dirname "$rootPath")
+serverPath=$(dirname "$rootPath")
+
+# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/dztasks && bash install.sh install 1.0
+# cd /wwww/server/mdserver-web/plugins/dztasks && bash install.sh install 1.0
+VERSION=$2
+sysArch=`arch`
+sysName=`uname`
+
+DZ_ARCH_NAME=amd64
+if [ "$sysArch" == "arm64" ];then
+ DZ_ARCH_NAME=arm64
+elif [ "$sysArch" == "x86_64" ]; then
+ DZ_ARCH_NAME=amd64
+elif [ "$sysArch" == "aarch64" ]; then
+ DZ_ARCH_NAME=aarch64
+fi
+
+DZ_NAME=linux
+if [ "$sysName" == "Darwin" ];then
+ DZ_NAME=darwin
+fi
+Install_App()
+{
+ echo '正在安装脚本文件...'
+ mkdir -p $serverPath/source
+ mkdir -p $serverPath/source/dztasks
+ mkdir -p $serverPath/dztasks
+
+ FILE_TGZ=dztasks_v${VERSION}_${DZ_NAME}_${DZ_ARCH_NAME}.tar.gz
+ DZ_DIR=$serverPath/source/dztasks
+
+ echo $FILE_TGZ
+ # https://github.com/midoks/dztasks/releases/download/1.0/dztasks_v1.0_darwin_amd64.tar.gz
+ if [ ! -f $DZ_DIR/${FILE_TGZ} ];then
+ wget --no-check-certificate -O $DZ_DIR/${FILE_TGZ} https://github.com/midoks/dztasks/releases/download/${VERSION}/${FILE_TGZ}
+ fi
+
+ cd $DZ_DIR && tar -zxvf ${FILE_TGZ} -C $serverPath/dztasks
+ echo "${VERSION}" > $serverPath/dztasks/version.pl
+ cd ${rootPath} && python3 ${rootPath}/plugins/dztasks/index.py start
+ cd ${rootPath} && python3 ${rootPath}/plugins/dztasks/index.py initd_install
+
+ echo '安装dztasks成功!'
+}
+
+Uninstall_App()
+{
+ if [ -f /usr/lib/systemd/system/dztasks.service ];then
+ systemctl stop dztasks
+ systemctl disable dztasks
+ rm -rf /usr/lib/systemd/system/dztasks.service
+ systemctl daemon-reload
+ fi
+
+ if [ -f /lib/systemd/system/dztasks.service ];then
+ systemctl stop dztasks
+ systemctl disable dztasks
+ rm -rf /lib/systemd/system/dztasks.service
+ systemctl daemon-reload
+ fi
+
+ if [ -f $serverPath/dztasks/initd/dztasks ];then
+ $serverPath/dztasks/initd/dztasks stop
+ fi
+
+ if [ -d $serverPath/dztasks ];then
+ rm -rf $serverPath/dztasks
+ fi
+
+ echo "卸载dztasks成功"
+}
+
+action=$1
+if [ "${1}" == 'install' ];then
+ Install_App
+else
+ Uninstall_App
+fi
diff --git a/plugins/dztasks/js/dztasks.js b/plugins/dztasks/js/dztasks.js
new file mode 100755
index 000000000..ea812deac
--- /dev/null
+++ b/plugins/dztasks/js/dztasks.js
@@ -0,0 +1,78 @@
+function zdPost(method, version, args,callback){
+ var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
+
+ var req_data = {};
+ req_data['name'] = 'dztasks';
+ req_data['func'] = method;
+ req_data['version'] = version;
+
+ if (typeof(args) == 'string'){
+ req_data['args'] = JSON.stringify(toArrayObject(args));
+ } else {
+ req_data['args'] = JSON.stringify(args);
+ }
+
+ $.post('/plugins/run', req_data, function(data) {
+ layer.close(loadT);
+ if (!data.status){
+ //错误展示10S
+ layer.msg(data.msg,{icon:0,time:2000,shade: [10, '#000']});
+ return;
+ }
+
+ if(typeof(callback) == 'function'){
+ callback(data);
+ }
+ },'json');
+}
+
+function zdPostCallbak(method, version, args,callback){
+ var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
+
+ var req_data = {};
+ req_data['name'] = 'dztasks';
+ req_data['func'] = method;
+ args['version'] = version;
+
+ if (typeof(args) == 'string'){
+ req_data['args'] = JSON.stringify(toArrayObject(args));
+ } else {
+ req_data['args'] = JSON.stringify(args);
+ }
+
+ $.post('/plugins/callback', req_data, function(data) {
+ layer.close(loadT);
+ if (!data.status){
+ layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
+ return;
+ }
+
+ if(typeof(callback) == 'function'){
+ callback(data);
+ }
+ },'json');
+}
+
+function commonHomePage(){
+ zdPost('home_page', '', {}, function(data){
+ var rdata = $.parseJSON(data.data);
+ window.open(rdata.data);
+ });
+}
+
+function dzCommonFunc(){
+ var con = '';
+ con += '\
+ 主页 \
+
';
+ $(".soft-man-con").html(con);
+}
+
+function zdReadme(){
+ var readme = '';
+ readme += '自己修改配置 ';
+ readme += ' ';
+
+ $('.soft-man-con').html(readme);
+}
+