diff --git a/applications/luci-app-kodexplorer/Makefile b/applications/luci-app-kodexplorer/Makefile
index 13d0c4c..763b17d 100644
--- a/applications/luci-app-kodexplorer/Makefile
+++ b/applications/luci-app-kodexplorer/Makefile
@@ -2,12 +2,12 @@
 
 include $(TOPDIR)/rules.mk
 
-PKG_VERSION:=1.1.2
-PKG_RELEASE:=20220829
+PKG_VERSION:=1.2.0-20220830
+PKG_RELEASE:=
 
 LUCI_TITLE:=LuCI support for kodexplorer
 LUCI_PKGARCH:=all
-LUCI_DEPENDS:=+docker +luci-lib-iform
+LUCI_DEPENDS:=+docker +luci-lib-taskd
 
 define Package/luci-app-kodexplorer/conffiles
 /etc/config/kodexplorer
@@ -16,4 +16,3 @@ endef
 include $(TOPDIR)/feeds/luci/luci.mk
 
 # call BuildPackage - OpenWrt buildroot signature
-
diff --git a/applications/luci-app-kodexplorer/luasrc/controller/kodexplorer.lua b/applications/luci-app-kodexplorer/luasrc/controller/kodexplorer.lua
index 9391c86..a1c6183 100755
--- a/applications/luci-app-kodexplorer/luasrc/controller/kodexplorer.lua
+++ b/applications/luci-app-kodexplorer/luasrc/controller/kodexplorer.lua
@@ -1,276 +1,7 @@
-local util  = require "luci.util"
-local http = require "luci.http"
-local iform = require "luci.iform"
-local jsonc = require "luci.jsonc"
 
 module("luci.controller.kodexplorer", package.seeall)
 
 function index()
-
-  entry({"admin", "services", "kodexplorer"}, call("redirect_index"), _("KodExplorer"), 30).dependent = true
-  entry({"admin", "services", "kodexplorer", "pages"}, call("kodexplorer_index")).leaf = true
-  entry({"admin", "services", "kodexplorer", "form"}, call("kodexplorer_form"))
-  entry({"admin", "services", "kodexplorer", "submit"}, call("kodexplorer_submit"))
-  entry({"admin", "services", "kodexplorer", "log"}, call("kodexplorer_log"))
-
-end
-
-local const_log_end = "XU6J03M6"
-local appname = "kodexplorer"
-local page_index = {"admin", "services", "kodexplorer", "pages"}
-
-function redirect_index()
-    http.redirect(luci.dispatcher.build_url(unpack(page_index)))
-end
-
-function kodexplorer_index()
-    luci.template.render("kodexplorer/main", {prefix=luci.dispatcher.build_url(unpack(page_index))})
-end
-
-function kodexplorer_form()
-    local error = ""
-    local scope = ""
-    local success = 0
-
-    local data = get_data()
-    local result = {
-        data = data,
-        schema = get_schema(data)
-    } 
-    local response = {
-            error = error,
-            scope = scope,
-            success = success,
-            result = result,
-    }
-    http.prepare_content("application/json")
-    http.write_json(response)
-end
-
-function get_schema(data)
-  local actions
-  if data.container_install then
-    actions = {
-      {
-          name = "restart",
-          text = "重启",
-          type = "apply",
-      },
-      {
-          name = "upgrade",
-          text = "更新",
-          type = "apply",
-      },
-      {
-          name = "remove",
-          text = "删除",
-          type = "apply",
-      },
-    } 
-  else
-    actions = {
-      {
-          name = "install",
-          text = "安装",
-          type = "apply",
-      },
-    }
-  end
-  local _ = luci.i18n.translate
-  local access = _('access homepage: ')
-  local homepage = '<a href=\"https://kodcloud.com/\" target=\"_blank\">https://kodcloud.com/</a>'
-  local schema = {
-    actions = actions,
-    containers = get_containers(data),
-    description = _("Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts.")..access..homepage,
-    title = _("KodExplorer")
-  }
-  return schema
-end
-
-function get_containers(data) 
-    local containers = {
-      status_container(data),
-      main_container(data)
-    }
-    return containers
-end
-
-function status_container(data)
-  local status_value
-
-  if data.container_install then
-    status_value = "KodExplorer 运行中"
-  else
-    status_value = "KodExplorer 未运行"
-  end
-
-  local status_c1 = {
-    labels = {
-      {
-        key = "状态:",
-        value = status_value
-      },
-      {
-        key = "访问:",
-        value = ""
-      }
-
-    },
-    description = "KodExplorer 的状态信息如下:",
-    title = "服务状态"
-  }
-  return status_c1
-end
-
-function main_container(data)
-  local main_c2 = {
-      properties = {
-        {
-          name = "port",
-          required = true,
-          title = "端口",
-          type = "string"
-        },
-        {
-          name = "cache_path",
-          required = true,
-          title = "存储位置:",
-          type = "string",
-          enum = dup_to_enums(data.blocks),
-          enumNames = dup_to_enums(data.blocks)
-        },
-      },
-      description = "请选择合适的存储位置进行安装:",
-      title = "服务操作"
-    }
-    return main_c2
-end
-
-function get_data() 
-  local uci = require "luci.model.uci".cursor()
-  local default_path = ""
-  local blks = blocks()
-  if #blks > 0 then
-    default_path = blks[1] .. "/kodexplorer"
-  end
-  local blk1 = {}
-  for _, val in pairs(blks) do
-    table.insert(blk1, val .. "/kodexplorer")
-  end
-  local docker_path = util.exec("which docker")
-  local docker_install = (string.len(docker_path) > 0)
-  local container_id = util.trim(util.exec("docker ps -qf 'name="..appname.."'"))
-  local container_install = (string.len(container_id) > 0)
-  local port = tonumber(uci:get_first(appname, appname, "port", "8081"))
-  local data = {
-    port = port,
-    cache_path = uci:get_first(appname, appname, "cache_path", ""),
-    blocks = blk1,
-    container_install = container_install
-  }
-  return data
-end
-
-function kodexplorer_submit()
-    local error = ""
-    local scope = ""
-    local success = 0
-    local result
-    
-    local json_parse = jsonc.parse
-    local content = http.content()
-    local req = json_parse(content)
-    if req["$apply"] == "upgrade" then
-      result = install_upgrade_kodexplorer(req)
-    elseif req["$apply"] == "install" then 
-      result = install_upgrade_kodexplorer(req)
-    elseif req["$apply"] == "restart" then 
-      result = restart_kodexplorer(req)
-    else
-      result = delete_kodexplorer()
-    end
-    http.prepare_content("application/json")
-    local resp = {
-        error = error,
-        scope = scope,
-        success = success,
-        result = result,
-    }
-    http.write_json(resp)
-end
-
-function kodexplorer_log()
-  iform.response_log("/var/log/"..appname..".log")
-end
-
-function install_upgrade_kodexplorer(req)
-  local port = req["port"]
-  local cache_path = req["cache_path"]
-
-  -- save config
-  local uci = require "luci.model.uci".cursor()
-  uci:tset(appname, "@"..appname.."[0]", {
-    cache_path = cache_path,
-    port = port or "8081",
-  })
-  uci:save(appname)
-  uci:commit(appname)
-
-  local exec_cmd = string.format("/usr/share/kodexplorer/install.sh %s", req["$apply"])
-  iform.fork_exec(exec_cmd)
-
-  local result = {
-    async = true,
-    exec = exec_cmd,
-    async_state = req["$apply"]
-  }
-  return result
-end
-
-function delete_kodexplorer()
-  local log = iform.exec_to_log("docker rm -f kodexplorer")
-  local result = {
-    async = false,
-    log = log
-  }
-  return result
-end
-
-function restart_kodexplorer()
-  local log = iform.exec_to_log("docker restart kodexplorer")
-  local result = {
-    async = false,
-    log = log
-  }
-  return result
-end
-
-function blocks()
-  local f = io.popen("lsblk -s -f -b -o NAME,FSSIZE,MOUNTPOINT --json", "r")
-  local vals = {}
-  if f then
-    local ret = f:read("*all")
-    f:close()
-    local obj = jsonc.parse(ret)
-    for _, val in pairs(obj["blockdevices"]) do
-      local fsize = val["fssize"]
-      if fsize ~= nil and string.len(fsize) > 10 and val["mountpoint"] then
-        -- fsize > 1G
-        vals[#vals+1] = val["mountpoint"]
-      end
-    end
-  end
-  return vals
-end
-
-function dup_to_enums(a)
-  if #a == 0 then
-    return nil
-  end
-  local a2 = {}
-  for _, val in pairs(a) do
-    table.insert(a2, val)
-  end
-  return a2
+  entry({"admin", "services", "kodexplorer"}, alias("admin", "services", "kodexplorer", "config"), _("KodExplorer"), 30).dependent = true
+  entry({"admin", "services", "kodexplorer", "config"}, cbi("kodexplorer"))
 end
diff --git a/applications/luci-app-kodexplorer/luasrc/model/cbi/kodexplorer.lua b/applications/luci-app-kodexplorer/luasrc/model/cbi/kodexplorer.lua
new file mode 100644
index 0000000..7d6e92f
--- /dev/null
+++ b/applications/luci-app-kodexplorer/luasrc/model/cbi/kodexplorer.lua
@@ -0,0 +1,30 @@
+--[[
+LuCI - Lua Configuration Interface
+]]--
+
+local taskd = require "luci.model.tasks"
+local m, s, o
+
+m = taskd.docker_map("kodexplorer", "kodexplorer", "/usr/libexec/istorec/kodexplorer.sh",
+	translate("KodExplorer"),
+	translate("Private cloud online document management solution based on web technology.")
+		.. translate("Official website:") .. ' <a href=\"https://kodcloud.com/\" target=\"_blank\">https://kodcloud.com/</a>')
+
+s = m:section(SimpleSection, translate("Service Status"), translate("KodExplorer status:"))
+s:append(Template("kodexplorer/status"))
+
+s = m:section(TypedSection, "kodexplorer", translate("Setup"), translate("The following parameters will only take effect during installation or upgrade:"))
+s.addremove=false
+s.anonymous=true
+
+o = s:option(Value, "port", translate("Port").."<b>*</b>")
+o.rmempty = false
+o.default = "8081"
+o.datatype = "port"
+
+o = s:option(Value, "cache_path", translate("Config path").."<b>*</b>")
+o.rmempty = false
+o.default = "/mnt/sda1/kodexplorer"
+o.datatype = "string"
+
+return m
diff --git a/applications/luci-app-kodexplorer/luasrc/view/kodexplorer/main.htm b/applications/luci-app-kodexplorer/luasrc/view/kodexplorer/main.htm
deleted file mode 100644
index 7ccf602..0000000
--- a/applications/luci-app-kodexplorer/luasrc/view/kodexplorer/main.htm
+++ /dev/null
@@ -1,34 +0,0 @@
-<%+header%>
-
-<script>
-    (function(){
-    })();
-</script>
-<div id="app">
-</div>
-
-<script>
-  window.IstoreosFormConfig = {
-    getApi:"/cgi-bin/luci/admin/services/kodexplorer/form/",
-    logApi:"/cgi-bin/luci/admin/services/kodexplorer/log",
-    submitApi:"/cgi-bin/luci/admin/services/kodexplorer/submit",
-    getHook:function(resp){
-      var c1 = resp.result.schema.containers[0];
-      var idx = 1;
-      if  (resp.result.data.container_install) {
-        c1.labels[idx].value = '<a href="http://'+location.host+':'+resp.result.data.port+'" target="_blank">KodExplorer 链接</a>';
-      } else {
-        c1.labels[idx].value = "安装并运行之后,才能用网页访问";
-      }
-      // console.log("resp=", data);
-      return resp;
-    },
-    submitHook:function(params){
-      return params;
-    }
-  }
-</script>
-<script type="module" crossorigin src="/luci-static/iform/1.0/index.js?v=<%=math.random(1,100000)%>"></script>
-<link rel="stylesheet" href="/luci-static/iform/1.0/style.css?v=<%=math.random(1,100000)%>">
-
-<%+footer%>
diff --git a/applications/luci-app-kodexplorer/luasrc/view/kodexplorer/status.htm b/applications/luci-app-kodexplorer/luasrc/view/kodexplorer/status.htm
new file mode 100644
index 0000000..0a88625
--- /dev/null
+++ b/applications/luci-app-kodexplorer/luasrc/view/kodexplorer/status.htm
@@ -0,0 +1,31 @@
+<%
+local util  = require "luci.util"
+local container_status = util.trim(util.exec("/usr/libexec/istorec/kodexplorer.sh status"))
+local container_install = (string.len(container_status) > 0)
+local container_running = container_status == "running"
+-%>
+<div class="cbi-value">
+    <label class="cbi-value-title"><%:Status%></label>
+    <div class="cbi-value-field">
+        <% if container_running then %>
+        <button class="cbi-button cbi-button-success" disabled="true"><%:KodExplorer is running%></button>
+        <% else %>
+        <button class="cbi-button cbi-button-negative" disabled="true"><%:KodExplorer is not running%></button>
+        <% end %>
+    </div>
+</div>
+<%
+if container_running then
+    local port=util.trim(util.exec("/usr/libexec/istorec/kodexplorer.sh port"))
+    if port == "" then
+        port="8081"
+    end
+-%>
+<div class="cbi-value cbi-value-last">
+    <label class="cbi-value-title">&nbsp;</label>
+    <div class="cbi-value-field">
+
+    <input type="button" class="btn cbi-button cbi-button-apply" name="start" value="<%:Open KodExplorer%>" onclick="window.open('http://'+location.hostname+':<%=port%>/', '_blank')">
+    </div>
+</div>
+<% end %>
\ No newline at end of file
diff --git a/applications/luci-app-kodexplorer/po/zh-cn/kodexplorer.po b/applications/luci-app-kodexplorer/po/zh-cn/kodexplorer.po
index 86f04b3..23f4ec7 100644
--- a/applications/luci-app-kodexplorer/po/zh-cn/kodexplorer.po
+++ b/applications/luci-app-kodexplorer/po/zh-cn/kodexplorer.po
@@ -1,35 +1,41 @@
-msgid "kodexplorer"
+msgid ""
+msgstr "Content-Type: text/plain; charset=UTF-8"
+
+msgid "KodExplorer"
 msgstr "可道云"
 
-msgid "The kodexplorer service is running."
-msgstr "可道云已启动"
+msgid "Official website:"
+msgstr "官方网站:"
 
-msgid "The kodexplorer service is not running."
-msgstr "可道云服务未启动"
+msgid "Private cloud online document management solution based on web technology."
+msgstr "基于Web技术的私有云在线文档管理解决方案。"
 
-msgid "The kodexplorer service is not installed."
-msgstr "可道云服务未安装"
+msgid "Config path"
+msgstr "配置文件路径"
 
-msgid "open kodexplorer"
+msgid "Port"
+msgstr "端口"
+
+msgid "Service Status"
+msgstr "服务状态"
+
+msgid "KodExplorer status:"
+msgstr "可道云的状态信息如下:"
+
+msgid "Setup"
+msgstr "安装配置"
+
+msgid "The following parameters will only take effect during installation or upgrade:"
+msgstr "以下参数只在安装或者升级时才会生效:"
+
+msgid "Status"
+msgstr "状态"
+
+msgid "KodExplorer is running"
+msgstr "可道云运行中"
+
+msgid "KodExplorer is not running"
+msgstr "可道云未运行"
+
+msgid "Open KodExplorer"
 msgstr "打开可道云"
-
-msgid "stop kodexplorer"
-msgstr "停止可道云"
-
-msgid "run kodexplorer"
-msgstr "启动可道云"
-
-msgid "uninstall kodexplorer"
-msgstr "删除可道云"
-
-msgid "install kodexplorer"
-msgstr "安装可道云"
-
-msgid "Collecting data..."
-msgstr "收集数据..."
-
-msgid "storage path"
-msgstr "存储路径(建议插入U盘或硬盘,然后输入路径。例如:/mnt/sda1/kodexplorer)"
-
-msgid "Storage path could not be empty!"
-msgstr "存储路径不能为空!"
diff --git a/applications/luci-app-kodexplorer/root/etc/config/kodexplorer b/applications/luci-app-kodexplorer/root/etc/config/kodexplorer
index a6662c3..867efd2 100644
--- a/applications/luci-app-kodexplorer/root/etc/config/kodexplorer
+++ b/applications/luci-app-kodexplorer/root/etc/config/kodexplorer
@@ -1,4 +1,3 @@
 config kodexplorer
-	option 'image' 'kodcloud/kodbox:latest'
 	option 'cache_path' '/mnt/sda1/kodexplorer'
 	option 'port' '8081'
diff --git a/applications/luci-app-kodexplorer/root/usr/libexec/istorec/kodexplorer.sh b/applications/luci-app-kodexplorer/root/usr/libexec/istorec/kodexplorer.sh
new file mode 100755
index 0000000..a334a3a
--- /dev/null
+++ b/applications/luci-app-kodexplorer/root/usr/libexec/istorec/kodexplorer.sh
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+ACTION=${1}
+shift 1
+
+get_image() {
+  IMAGE_NAME="kodcloud/kodbox:latest"
+}
+
+do_install() {
+  get_image
+  echo "docker pull ${IMAGE_NAME}"
+  docker pull ${IMAGE_NAME}
+  docker rm -f kodexplorer
+
+  do_install_detail
+}
+
+do_install_detail() {
+  local config=`uci get kodexplorer.@kodexplorer[0].cache_path 2>/dev/null`
+  local port=`uci get kodexplorer.@kodexplorer[0].port 2>/dev/null`
+
+  if [ -z "$config" ]; then
+      echo "config path is empty!"
+      exit 1
+  fi
+
+  [ -z "$port" ] && port=8081
+
+  local cmd="docker run --restart=unless-stopped -d \
+    -v \"$config:/var/www/html\" \
+    --dns=172.17.0.1 \
+    -p $port:80 "
+
+  cmd="$cmd -v /mnt:/mnt"
+  mountpoint -q /mnt && cmd="$cmd:rslave"
+
+  local tz="`cat /tmp/TZ`"
+  [ -z "$tz" ] || cmd="$cmd -e TZ=$tz"
+
+  cmd="$cmd --name kodexplorer \"$IMAGE_NAME\""
+
+  echo "$cmd"
+  eval "$cmd"
+
+}
+
+usage() {
+  echo "usage: $0 sub-command"
+  echo "where sub-command is one of:"
+  echo "      install                Install the kodexplorer"
+  echo "      upgrade                Upgrade the kodexplorer"
+  echo "      rm/start/stop/restart  Remove/Start/Stop/Restart the kodexplorer"
+  echo "      status                 KodExplorer status"
+  echo "      port                   KodExplorer port"
+}
+
+case ${ACTION} in
+  "install")
+    do_install
+  ;;
+  "upgrade")
+    do_install
+  ;;
+  "rm")
+    docker rm -f kodexplorer
+  ;;
+  "start" | "stop" | "restart")
+    docker ${ACTION} kodexplorer
+  ;;
+  "status")
+    docker ps --all -f 'name=kodexplorer' --format '{{.State}}'
+  ;;
+  "port")
+    docker ps --all -f 'name=kodexplorer' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
+  ;;
+  *)
+    usage
+    exit 1
+  ;;
+esac
diff --git a/applications/luci-app-kodexplorer/root/usr/share/kodexplorer/install.sh b/applications/luci-app-kodexplorer/root/usr/share/kodexplorer/install.sh
deleted file mode 100755
index df25a67..0000000
--- a/applications/luci-app-kodexplorer/root/usr/share/kodexplorer/install.sh
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/bin/sh
-# Author Xiaobao(xiaobao@linkease.com)
-
-ACTION=${1}
-WRLOCK=/var/lock/kodexplorer.lock
-LOGFILE=/var/log/kodexplorer.log
-LOGEND="XU6J03M6"
-shift 1
-
-IMAGE_NAME='kodcloud/kodbox:latest'
-
-check_params() {
-
-  if [ -z "${WRLOCK}" ]; then
-    echo "lock file not found"
-    exit 1
-  fi
-
-  if [ -z "${LOGFILE}" ]; then
-    echo "logger file not found"
-    exit 1
-  fi
-
-}
-
-lock_run() {
-  local lock="$WRLOCK"
-  exec 300>$lock
-  flock -n 300 || return
-  do_run
-  flock -u 300
-  return
-}
-
-run_action() {
-  if check_params; then
-    lock_run
-  fi
-}
-
-do_install() {
-  local CACHE=`uci get kodexplorer.@kodexplorer[0].cache_path 2>/dev/null`
-  local PORT=`uci get kodexplorer.@kodexplorer[0].port 2>/dev/null`
-  if [ -z "${CACHE}" ]; then
-      echo "cache path is empty!" >${LOGFILE}
-      exit 1
-  fi
-  echo "docker pull ${IMAGE_NAME}" >${LOGFILE}
-  docker pull ${IMAGE_NAME} >>${LOGFILE} 2>&1
-  docker rm -f kodexplorer
-  local mntv="/mnt:/mnt"
-  mountpoint -q /mnt && mntv="$mntv:rslave"
-  docker run -d --name kodexplorer \
-    --dns=172.17.0.1 \
-    --restart=unless-stopped \
-    -p ${PORT}:80 \
-    -v ${CACHE}:/var/www/html -v ${mntv} \
-    $IMAGE_NAME >>${LOGFILE} 2>&1
-
-  RET=$?
-  if [ "${RET}" = "0" ]; then
-    # mark END, remove the log file
-    echo ${LOGEND} >> ${LOGFILE}
-    sleep 5
-    rm -f ${LOGFILE}
-  else
-    # reserve the log
-    echo "docker run ${IMAGE_NAME} failed" >>${LOGFILE}
-    echo ${LOGEND} >> ${LOGFILE}
-  fi
-  exit ${RET}
-}
-
-# run in lock
-do_run() {
-  case ${ACTION} in
-    "install")
-      do_install
-    ;;
-    "upgrade")
-      do_install
-    ;;
-  esac
-}
-
-usage() {
-  echo "usage: wxedge sub-command"
-  echo "where sub-command is one of:"
-  echo "      install                Install the kodexplorer"
-  echo "      upgrade                Upgrade the kodexplorer"
-  echo "      remove                 Remove the kodexplorer"
-}
-
-case ${ACTION} in
-  "install")
-    run_action
-  ;;
-  "upgrade")
-    run_action
-  ;;
-  "remove")
-    docker rm -f kodexplorer
-  ;;
-  *)
-    usage
-  ;;
-esac
-