diff --git a/application/admin/controller/auth/Adminlog.php b/application/admin/controller/auth/Adminlog.php
index 1d8cc81..03c213f 100644
--- a/application/admin/controller/auth/Adminlog.php
+++ b/application/admin/controller/auth/Adminlog.php
@@ -2,6 +2,7 @@
 
 namespace app\admin\controller\auth;
 
+use addons\csmtable\library\xcore\xcore\utils\XcAdminSessionUtils;
 use app\admin\model\AuthGroup;
 use app\common\controller\Backend;
 
@@ -33,6 +34,8 @@ class Adminlog extends Backend
             ->column('id,name');
 
         $this->view->assign('groupdata', $groupName);
+
+//        var_dump(XcAdminSessionUtils::getManystoreToken());die;
     }
 
     /**
diff --git a/application/admin/controller/school/Message.php b/application/admin/controller/school/Message.php
index b0a03b6..d1d9ac8 100644
--- a/application/admin/controller/school/Message.php
+++ b/application/admin/controller/school/Message.php
@@ -3,6 +3,11 @@
 namespace app\admin\controller\school;
 
 use app\common\controller\Backend;
+use think\Db;
+use think\Exception;
+use think\exception\DbException;
+use think\exception\PDOException;
+use think\exception\ValidateException;
 
 /**
  * 夜校站内信
@@ -82,4 +87,96 @@ class Message extends Backend
         return $this->view->fetch();
     }
 
+
+
+    /**
+     * 添加
+     *
+     * @return string
+     * @throws \think\Exception
+     */
+    public function add()
+    {
+        if (false === $this->request->isPost()) {
+            return $this->view->fetch();
+        }
+        $params = $this->request->post('row/a');
+        if (empty($params)) {
+            $this->error(__('Parameter %s can not be empty', ''));
+        }
+        $params = $this->preExcludeFields($params);
+
+        if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
+            $params[$this->dataLimitField] = $this->auth->id;
+        }
+        $result = false;
+        Db::startTrans();
+        try {
+            //是否采用模型验证
+            if ($this->modelValidate) {
+                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
+                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
+                $this->model->validateFailException()->validate($validate);
+            }
+            $params["event"] = "system";
+            $result = $this->model->allowField(true)->save($params);
+            Db::commit();
+        } catch (ValidateException|PDOException|Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if ($result === false) {
+            $this->error(__('No rows were inserted'));
+        }
+        $this->success();
+    }
+
+    /**
+     * 编辑
+     *
+     * @param $ids
+     * @return string
+     * @throws DbException
+     * @throws \think\Exception
+     */
+    public function edit($ids = null)
+    {
+        $row = $this->model->get($ids);
+        if (!$row) {
+            $this->error(__('No Results were found'));
+        }
+        $adminIds = $this->getDataLimitAdminIds();
+        if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) {
+            $this->error(__('You have no permission'));
+        }
+        if (false === $this->request->isPost()) {
+            $this->view->assign('row', $row);
+            return $this->view->fetch();
+        }
+        $params = $this->request->post('row/a');
+        if (empty($params)) {
+            $this->error(__('Parameter %s can not be empty', ''));
+        }
+        $params = $this->preExcludeFields($params);
+        $result = false;
+        Db::startTrans();
+        try {
+            //是否采用模型验证
+            if ($this->modelValidate) {
+                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
+                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
+                $row->validateFailException()->validate($validate);
+            }
+            $result = $row->allowField(true)->save($params);
+            Db::commit();
+        } catch (ValidateException|PDOException|Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if (false === $result) {
+            $this->error(__('No rows were updated'));
+        }
+        $this->success();
+    }
+
 }
diff --git a/application/admin/controller/school/classes/ClassesLib.php b/application/admin/controller/school/classes/ClassesLib.php
index b3ca495..71c6601 100644
--- a/application/admin/controller/school/classes/ClassesLib.php
+++ b/application/admin/controller/school/classes/ClassesLib.php
@@ -43,7 +43,7 @@ class ClassesLib extends Backend
     protected $model = null;
 
     //不用审核允许修改的字段
-    protected $no_auth_fields = ["user_id","teacher_id","classes_type","classes_cate_ids","classes_label_ids","self_label_tag",'headimage','images','notice','content',"virtual_num","virtual_collect","underline_price"];
+    protected $no_auth_fields = ["title","user_id","teacher_id","classes_type","classes_cate_ids","classes_label_ids","self_label_tag",'headimage','images','notice','content',"virtual_num","virtual_collect","underline_price"];
 
     //更新数据是否需要触发审核开关
     protected $need_auth = false;
diff --git a/application/admin/controller/school/classes/hourorder/Order.php b/application/admin/controller/school/classes/hourorder/Order.php
index 5584a6e..7391389 100644
--- a/application/admin/controller/school/classes/hourorder/Order.php
+++ b/application/admin/controller/school/classes/hourorder/Order.php
@@ -35,6 +35,7 @@ class Order extends Backend
         $this->view->assign("statusList", $this->model->getStatusList());
         $this->view->assign("authStatusList", $this->model->getAuthStatusList());
         $this->getAuthMsg();
+//        $this->setUrlLock();
     }
 
 
diff --git a/application/admin/validate/school/classes/ClassesLib.php b/application/admin/validate/school/classes/ClassesLib.php
index 93d0a60..30f763f 100644
--- a/application/admin/validate/school/classes/ClassesLib.php
+++ b/application/admin/validate/school/classes/ClassesLib.php
@@ -10,7 +10,8 @@ class ClassesLib extends Validate
      * 验证规则
      */
     protected $rule = [
-        'title' => 'require|length:1,50|alphaNum',
+//        'title' => 'require|length:1,50|alphaNum',
+        'title' => 'require|length:1,50',
         // 'alphaNum' 是自定义的规则,用于过滤中文、数字和拼音字符
     ];
     /**
@@ -19,7 +20,7 @@ class ClassesLib extends Validate
     protected $message = [
         'title.require' => '课程名不能为空',
         'title.length'  => '课程名长度必须在1到50之间',
-        'title.alphaNum' =>'课程名只允许中文、数字和拼音字符'
+//        'title.alphaNum' =>'课程名只允许中文、数字和拼音字符'
     ];
     /**
      * 验证场景
diff --git a/application/api/controller/school/Activity.php b/application/api/controller/school/Activity.php
index d3ba849..a8dd27a 100644
--- a/application/api/controller/school/Activity.php
+++ b/application/api/controller/school/Activity.php
@@ -10,7 +10,7 @@ use app\common\model\school\classes\Teacher as Teachermodel;
  */
 class Activity extends Base
 {
-    protected $noNeedLogin = ["demo_detail","demo_list"];
+    protected $noNeedLogin = '*';
     protected $noNeedRight = '*';
 
     protected $model = null;
diff --git a/application/api/controller/school/Classes.php b/application/api/controller/school/Classes.php
index 25dc3a5..4dac4ae 100644
--- a/application/api/controller/school/Classes.php
+++ b/application/api/controller/school/Classes.php
@@ -31,6 +31,7 @@ class Classes extends Base
         parent::_initialize();
 
         //判断登录用户是否是员工
+        $this->setUrlLock();
     }
 
 
diff --git a/application/api/controller/school/Evaluate.php b/application/api/controller/school/Evaluate.php
index 783da12..1de52de 100644
--- a/application/api/controller/school/Evaluate.php
+++ b/application/api/controller/school/Evaluate.php
@@ -25,7 +25,7 @@ class Evaluate extends Base
         $this->model = new \app\common\model\school\classes\Evaluate;
         parent::_initialize();
 
-        //判断登录用户是否是员工
+        $this->setUrlLock();
     }
 
 
diff --git a/application/api/controller/school/HourOrder.php b/application/api/controller/school/HourOrder.php
index 67ab88f..4e2684f 100644
--- a/application/api/controller/school/HourOrder.php
+++ b/application/api/controller/school/HourOrder.php
@@ -87,6 +87,7 @@ class HourOrder extends Base
         $order_no =  $this->request->post('order_no/s', ''); //订单号
         $remark =  $this->request->post('remark/s', ''); //下单备注
 //        repeat_filter("appointment\order\create".$user_id, 2);
+        $this->setUrlLock("only");
         try{
             //当前申请状态
             $res = $this->model->cacheCreateOrder($order_no, $user_id,$remark, true);
diff --git a/application/api/controller/school/Order.php b/application/api/controller/school/Order.php
index 52cf78a..1ba6b2e 100644
--- a/application/api/controller/school/Order.php
+++ b/application/api/controller/school/Order.php
@@ -2,6 +2,7 @@
 
 namespace app\api\controller\school;
 
+use app\common\model\school\classes\ClassesSpec;
 use app\common\model\school\classes\order\Order as OrderModel;
 use app\common\model\school\classes\Teacher as Teachermodel;
 use bw\UrlLock;
@@ -83,6 +84,13 @@ class Order extends Base
         $classes_lib_id =  $this->request->post('classes_lib_id/d', 0); //课程id
         $classes_lib_spec_id =  $this->request->post('classes_lib_spec_id/d', 0); //想同时约的课时id
 //        $param  =  urldecode($this->request->post('param/s', "{}")); //参数
+        if(!$classes_lib_spec_id){
+            if(ClassesSpec::where("classes_lib_id",$classes_lib_id)->where("status",'1')->count()==1){
+                $classes_lib_spec_id = ClassesSpec::where("classes_lib_id",$classes_lib_id)->where("status",'1')->order("weigh desc,id desc")->value("id");
+            }
+
+        }
+
         $param  = [];
         if($classes_lib_spec_id){
             $param  =  [
@@ -119,7 +127,7 @@ class Order extends Base
         if($user)$user_id = $user['id'];
         $order_no =  $this->request->post('order_no/s', ''); //订单号
         $remark =  $this->request->post('remark/s', ''); //下单备注
-
+        $this->setUrlLock("only");
 //        repeat_filter("appointment\order\create".$user_id, 2);
         try{
 //            $lock = new UrlLock($user_id,"class-order-create-lock-suffix",120,"您的请求过于频繁,请您稍后再试!请求最大锁定间隔120秒!");
diff --git a/application/api/controller/school/Shop.php b/application/api/controller/school/Shop.php
index e18512a..b1989c6 100644
--- a/application/api/controller/school/Shop.php
+++ b/application/api/controller/school/Shop.php
@@ -25,6 +25,7 @@ class Shop extends Base
         parent::_initialize();
 
         //判断登录用户是否是员工
+        $this->setUrlLock();
     }
 
 
diff --git a/application/api/controller/school/activity/Order.php b/application/api/controller/school/activity/Order.php
index 98de2e1..08d6b8c 100644
--- a/application/api/controller/school/activity/Order.php
+++ b/application/api/controller/school/activity/Order.php
@@ -183,6 +183,7 @@ class Order extends Base
         if($user)$user_id = $user['id'];
         $order_no =  $this->request->post('order_no/s', ''); //订单号
         $remark =  $this->request->post('remark/s', ''); //下单备注
+        $this->setUrlLock("only");
 //        repeat_filter("appointment\order\create".$user_id, 2);
         try{
             //当前申请状态
diff --git a/application/api/controller/school/worker/Classes.php b/application/api/controller/school/worker/Classes.php
index 1fbb368..89e9a78 100644
--- a/application/api/controller/school/worker/Classes.php
+++ b/application/api/controller/school/worker/Classes.php
@@ -31,6 +31,9 @@ class Classes extends Base
         parent::_initialize();
 
         //判断登录用户是否是员工   'add','edit','del'
+
+        $this->setUrlLock();
+
     }
 
 
diff --git a/application/api/controller/school/worker/HourOrder.php b/application/api/controller/school/worker/HourOrder.php
index de4b3c0..ca19d94 100644
--- a/application/api/controller/school/worker/HourOrder.php
+++ b/application/api/controller/school/worker/HourOrder.php
@@ -92,6 +92,7 @@ class HourOrder extends Base
         $order_no =  $this->request->post('order_no/s', ''); //订单号
         $remark =  $this->request->post('remark/s', ''); //下单备注
 //        repeat_filter("appointment\order\create".$user_id, 2);
+        $this->setUrlLock("only");
         try{
             //当前申请状态
             $res = $this->model->cacheCreateOrder($order_no, $user_id,$remark, true);
diff --git a/application/common/controller/Api.php b/application/common/controller/Api.php
index 49b4b85..1040fe5 100644
--- a/application/common/controller/Api.php
+++ b/application/common/controller/Api.php
@@ -88,8 +88,10 @@ class Api
     }
 
 
-    public function setUrlLock(){
-        if($this->request->isPost() && !empty($this->model)){
+    protected $needUrlLock = [];
+
+    public function setUrlLock($url_key="",$url_suffix="",$model=null){
+        if(($this->request->isPost() || (!empty($this->needUrlLock) && in_array($this->request->action(),$this->needUrlLock))) && (!empty($this->model) || $model)){
             $user_id = 0;
             $user = $this->auth->getUser();//登录用户
             if($user)$user_id = $user['id'];
@@ -98,9 +100,16 @@ class Api
             $controllername = Loader::parseName($this->request->controller());
             $actionname = strtolower($this->request->action());
             $path = $modulename . '/' .  str_replace('.', '/', $controllername) . '/' . $actionname;
-            $this->model::$url_lock_key = $user_id;
-            $this->model::$url_lock_suffix = $path."lock-suffix";
-            $this->model::$url_lock = true;
+            if(!$model){
+                $this->model::$url_lock_key = $url_key ?: $user_id;
+                $this->model::$url_lock_suffix = $url_suffix ?: $path."lock-suffix";
+                $this->model::$url_lock = true;
+            }else{
+                $model::$url_lock_key = $url_key ?: $user_id;
+                $model::$url_lock_suffix = $url_suffix ?: $path."lock-suffix";
+                $model::$url_lock = true;
+            }
+
         }
     }
 
diff --git a/application/common/controller/Backend.php b/application/common/controller/Backend.php
index e66e7f7..f987159 100644
--- a/application/common/controller/Backend.php
+++ b/application/common/controller/Backend.php
@@ -2,6 +2,7 @@
 
 namespace app\common\controller;
 
+use addons\csmtable\library\xcore\xcore\utils\XcAdminSessionUtils;
 use app\admin\controller\famysql\Field;
 use app\admin\library\Auth;
 use app\admin\model\Admin;
@@ -249,7 +250,30 @@ class Backend extends Controller
     }
 
 
+    protected $needUrlLock = [];
 
+    public function setUrlLock($url_key="",$url_suffix="",$model=null){
+        if(($this->request->isPost() || (!empty($this->needUrlLock) && in_array($this->request->action(),$this->needUrlLock))) && (!empty($this->model) || $model)){
+            $user_id = $this->auth->id ?? 0;
+//            $user = $this->auth->getUser();//登录用户
+//            if($user)$user_id = $user['id'];
+
+            $modulename = $this->request->module();
+            $controllername = Loader::parseName($this->request->controller());
+            $actionname = strtolower($this->request->action());
+            $path = $modulename . '/' .  str_replace('.', '/', $controllername) . '/' . $actionname;
+            if(!$model){
+                $this->model::$url_lock_key = $url_key ?: $user_id;
+                $this->model::$url_lock_suffix = $url_suffix ?: $path."lock-suffix";
+                $this->model::$url_lock = true;
+            }else{
+                $model::$url_lock_key = $url_key ?: $user_id;
+                $model::$url_lock_suffix = $url_suffix ?: $path."lock-suffix";
+                $model::$url_lock = true;
+            }
+
+        }
+    }
 
     /**
      * 引入后台控制器的traits
@@ -297,6 +321,7 @@ class Backend extends Controller
             if (!$this->auth->match($this->noNeedRight)) {
                 // 判断控制器和方法是否有对应权限
                 if (!$this->auth->check($path)) {
+//                    var_dump($path);
                     Hook::listen('admin_nopermission', $this);
                     $this->error(__('You have no permission'), '');
                 }
@@ -352,18 +377,28 @@ class Backend extends Controller
             'jsname'         => 'backend/' . str_replace('.', '/', $controllername),
             'moduleurl'      => rtrim(url("/{$modulename}", '', false), '/'),
             'language'       => $lang,
-            'referer'        => Session::get("referer")
+            'referer'        => Session::get("referer"),
+
+
         ];
         $config = array_merge($config, Config::get("view_replace_str"));
 
         Config::set('upload', array_merge(Config::get('upload'), $upload));
 
+        if($this->auth->isLogin()){
+            $config["clogintoken"] = XcAdminSessionUtils::getToken();
+            $config["manystoretoken"] = "";
+        }
+
         // 配置信息后
         Hook::listen("config_init", $config);
         //加载当前控制器语言包
         $this->loadlang($controllername);
         //渲染站点配置
         $this->assign('site', $site);
+
+
+
         //渲染配置信息
         $this->assign('config', $config);
         //渲染权限对象
@@ -373,7 +408,7 @@ class Backend extends Controller
         $this->checkAssemblyParameters();
 
 //        $this->view->assign("selfhotList", $this->model->getSelfhotList());
-
+//        $this->assign('clogintoken', XcAdminSessionUtils::getToken());
     }
 
     /**
diff --git a/application/common/controller/ManystoreBase.php b/application/common/controller/ManystoreBase.php
index fc5726f..4ed78b0 100644
--- a/application/common/controller/ManystoreBase.php
+++ b/application/common/controller/ManystoreBase.php
@@ -2,6 +2,7 @@
 
 namespace app\common\controller;
 
+use addons\csmtable\library\xcore\xcore\utils\XcAdminSessionUtils;
 use app\admin\controller\famysql\Field;
 use app\common\library\Virtual;
 use app\common\model\dyqc\ManystoreShop;
@@ -209,6 +210,32 @@ class ManystoreBase extends Controller
 
 
 
+    protected $needUrlLock = [];
+
+    public function setUrlLock($url_key="",$url_suffix="",$model=null){
+        if(($this->request->isPost() || (!empty($this->needUrlLock) && in_array($this->request->action(),$this->needUrlLock))) && (!empty($this->model) || $model)){
+            $user_id = $this->auth->id ?? 0;
+//            $user = $this->auth->getUser();//登录用户
+//            if($user)$user_id = $user['id'];
+
+            $modulename = $this->request->module();
+            $controllername = Loader::parseName($this->request->controller());
+            $actionname = strtolower($this->request->action());
+            $path = $modulename . '/' .  str_replace('.', '/', $controllername) . '/' . $actionname;
+            if(!$model){
+                $this->model::$url_lock_key = $url_key ?: $user_id;
+                $this->model::$url_lock_suffix = $url_suffix ?: $path."lock-suffix";
+                $this->model::$url_lock = true;
+            }else{
+                $model::$url_lock_key = $url_key ?: $user_id;
+                $model::$url_lock_suffix = $url_suffix ?: $path."lock-suffix";
+                $model::$url_lock = true;
+            }
+
+        }
+    }
+
+
     /**
      * 引入后台控制器的traits
      */
@@ -357,6 +384,10 @@ class ManystoreBase extends Controller
 
         Config::set('upload', array_merge(Config::get('upload'), $upload));
 
+        if($this->auth->isLogin()){
+            $config["manystoretoken"] = $manystore["token"];
+            $config["clogintoken"] = "";
+        }
         // 配置信息后
         Hook::listen("config_init", $config);
         //加载当前控制器语言包
diff --git a/application/common/library/NightSchoolBigData.php b/application/common/library/NightSchoolBigData.php
new file mode 100644
index 0000000..d498f39
--- /dev/null
+++ b/application/common/library/NightSchoolBigData.php
@@ -0,0 +1,32 @@
+where('province',$province);
+          if( $city)$query = $query->where('city',$city);
+          if( $district)$query = $query->where('district',$district);
+       };
+       //统计当前课程总数
+        $count = ClassesLib::where($where)->sum("");
+
+
+    }
+
+
+
+
+
+}
\ No newline at end of file
diff --git a/application/common/model/dyqc/ManystoreShop.php b/application/common/model/dyqc/ManystoreShop.php
index 0d51295..c64aef1 100644
--- a/application/common/model/dyqc/ManystoreShop.php
+++ b/application/common/model/dyqc/ManystoreShop.php
@@ -6,6 +6,7 @@ use app\admin\model\Admin;
 use app\common\library\Virtual;
 use app\common\model\BaseModel;
 use app\common\model\school\Area;
+use app\common\model\school\classes\activity\Activity;
 use app\common\model\school\classes\ClassesLib;
 use app\common\model\school\classes\Teacher;
 use app\common\model\school\classes\Verification;
@@ -875,6 +876,26 @@ public static function getAuthInfo($user_id){
     $reason =""; //失败原因
     $check_full_msg = "";
     $check_full = false;
+
+    $verification = true; //核销权限
+    $verification_shop_id = 0; //可核销机构
+
+    try{
+        $verification_shop_id = ClassesLib::checkOptionAuth(0,$user_id,"user");
+    }catch (\Exception $e){
+
+    }
+    $verification_classes_lib_ids = (new ClassesLib)->getClassesAuthIds($user_id);
+    $verification_classes_activity_ids = (new Activity())->getActivityAuthIds($user_id);
+
+    //如果没有任何可管理的classes_lib_id 则返回错误
+    if(!$verification_classes_lib_ids && !$verification_shop_id && !$verification_classes_activity_ids){
+        $verification = false;
+    }
+    $verification_auth = compact("verification","verification_shop_id","verification_classes_lib_ids","verification_classes_activity_ids");
+
+
+
     $check_field = [
         "address_city",
         "province",
@@ -890,14 +911,14 @@ public static function getAuthInfo($user_id){
         "logo"
     ];
     $apply_info = null;
-    if(!$user_id)return compact("check_full_msg","check_full","check_field",'auth_status','shop_id','reason','apply_info',"type");
+    if(!$user_id)return compact("verification_auth","check_full_msg","check_full","check_field",'auth_status','shop_id','reason','apply_info',"type");
 
     //得到申请单
     $apply_info =  self::where("user_id",$user_id)->where("status","1")->find();
     if(!$apply_info)$apply_info =  self::where("user_id",$user_id)->find();
        //不存在说明未申请,直接返回
     if(!$apply_info){
-        return compact("check_full_msg","check_full","check_field",'auth_status','shop_id','reason','apply_info',"type");
+        return compact("verification_auth","check_full_msg","check_full","check_field",'auth_status','shop_id','reason','apply_info',"type");
     }
     $type =  $apply_info['type'];
     //从申请单取到申请状态
@@ -916,7 +937,7 @@ public static function getAuthInfo($user_id){
     $check_full_msg = $self->checkFullMsg($shop_id);
     $check_full = $self->checkFull($shop_id);
 
-    return compact("check_full_msg","check_full","check_field",'auth_status','shop_id','reason','apply_info',"type");
+    return compact("verification_auth","check_full_msg","check_full","check_field",'auth_status','shop_id','reason','apply_info',"type");
 }
 
 
diff --git a/application/common/model/school/Message.php b/application/common/model/school/Message.php
index de5e56a..c4c59ed 100644
--- a/application/common/model/school/Message.php
+++ b/application/common/model/school/Message.php
@@ -309,7 +309,7 @@ class Message extends BaseModel
         $unread_system_number =     self::getBaseWhere(array_merge(['status'=>'system'],$where))->count();
         $unread_classes_number =     self::getBaseWhere(array_merge(['status'=>'classes'],$where))->count();
         $unread_order_number =  self::getBaseWhere(array_merge(['status'=>'order'],$where))->count();
-
+        $unread_activity_number =  self::getBaseWhere(array_merge(['status'=>'activity'],$where))->count();;
 
 
         $where["type"] = '2';
@@ -317,11 +317,11 @@ class Message extends BaseModel
         $read_system_number =     self::getBaseWhere(array_merge(['status'=>'system'],$where))->count();
         $read_classes_number =     self::getBaseWhere(array_merge(['status'=>'classes'],$where))->count();
         $read_order_number =  self::getBaseWhere(array_merge(['status'=>'order'],$where))->count();
+        $read_activity_number =  self::getBaseWhere(array_merge(['status'=>'activity'],$where))->count();
 
 
-
-        return compact('unread_number','unread_system_number','unread_classes_number','unread_order_number',
-        'read_number','read_system_number','read_classes_number','read_order_number');
+        return compact("unread_activity_number",'unread_number','unread_system_number','unread_classes_number','unread_order_number',
+        'read_number','read_system_number','read_classes_number','read_order_number',"read_activity_number");
     }
 
 
@@ -338,19 +338,24 @@ class Message extends BaseModel
         $unread_classes_number =  0;
         $unread_order_number =  0;
 
+        $unread_activity_number =  0;
+
         $read_number =   0;
         $read_system_number =  0;
         $read_classes_number =  0;
         $read_order_number =  0;
+        $read_activity_number =  0;
 
         return compact('unread_number',
             'unread_system_number',
             'unread_classes_number',
+            'unread_activity_number',
             'unread_order_number',
             'read_number',
             'read_system_number',
             'read_classes_number',
-            'read_order_number'
+            'read_order_number',
+            'read_activity_number'
         );
         }
 
diff --git a/application/common/model/school/classes/ClassesLib.php b/application/common/model/school/classes/ClassesLib.php
index f551289..a5aed1c 100644
--- a/application/common/model/school/classes/ClassesLib.php
+++ b/application/common/model/school/classes/ClassesLib.php
@@ -1258,6 +1258,7 @@ $user_unpaid_order = $user_paid_order =null;
             $params["feel"] = "0";
         }
 
+       if(!isset($params["classes_num"]))$params["classes_num"] = 1;
 
        $rule =  [
                      'manystore_id'=>'require',
diff --git a/application/common/model/school/classes/ClassesSpec.php b/application/common/model/school/classes/ClassesSpec.php
index a2fefc6..4ebba43 100644
--- a/application/common/model/school/classes/ClassesSpec.php
+++ b/application/common/model/school/classes/ClassesSpec.php
@@ -32,7 +32,7 @@ class ClassesSpec extends BaseModel
         'time'
     ];
     
-    public $no_auth_fields = ['name','limit_num','status','weigh'];
+    public $no_auth_fields = ['name','limit_num','status','weigh',"start_time","end_time"];
     protected static function init()
     {
         self::afterInsert(function ($row) {
diff --git a/application/common/model/school/classes/activity/order/Order.php b/application/common/model/school/classes/activity/order/Order.php
index 9007d0f..d7b589c 100644
--- a/application/common/model/school/classes/activity/order/Order.php
+++ b/application/common/model/school/classes/activity/order/Order.php
@@ -770,7 +770,7 @@ class Order extends BaseModel
 
         //存在同规格正在进行中的课时预约
         $order_info = self::where('classes_activity_item_id',$classes_activity_item_id)
-            ->where('status',"not in",["-3","6"])
+            ->where('status',"not in",["-3","5","6"])
             ->where('user_id',$user_id)
             ->find();
         if($order_info && $check) throw new \Exception("该活动规格已预约或已上过,请勿重复预约!");
@@ -780,7 +780,7 @@ class Order extends BaseModel
         //允许人数为0说明不限制
         if($classes_lib_spec_info['limit_num'] > 0 && $check){
             //得到当前课时已参与人数
-            $sign_num =  self::where('classes_activity_item_id',$classes_activity_item_id)->where("status","not in",["-3","6"])->count();
+            $sign_num =  self::where('classes_activity_item_id',$classes_activity_item_id)->where("status","not in",["-3","5","6"])->count();
 
             if($sign_num >= $classes_lib_spec_info['limit_num']){
                 throw new \Exception("该活动已满,请选择其他活动!");
@@ -813,7 +813,7 @@ class Order extends BaseModel
                 $as = (new self)->getWithAlisaName();
                 //判断时间是否有交叠(只查所有的免费的预约记录)
                 $order_info = self::with("detail")->where("detail.price",0)
-                    ->where("{$as}.status","not in",["-3","6","9"])
+                    ->where("{$as}.status","not in",["-3","5","6","9"])
                     ->where(function ($query) use ($as,$start_time,$end_time) {
                         //兩個時間區間重合 存在任意交集 都不行
                         $query->where("detail.start_time BETWEEN {$start_time} AND {$end_time}");
@@ -837,7 +837,7 @@ class Order extends BaseModel
             $as = (new self)->getWithAlisaName();
             //判断时间是否有交叠(只查所有的免费的预约记录)
             $order_info = self::with("detail")
-                ->where("{$as}.status","not in",["-3","6","9"])
+                ->where("{$as}.status","not in",["-3","5","6","9"])
                 ->where(function ($query) use ($as,$start_time,$end_time) {
                     //兩個時間區間重合 存在任意交集 都不行
                     $query->where("detail.start_time BETWEEN {$start_time} AND {$end_time}");
diff --git a/application/common/model/school/classes/hourorder/Order.php b/application/common/model/school/classes/hourorder/Order.php
index b500653..ded9642 100644
--- a/application/common/model/school/classes/hourorder/Order.php
+++ b/application/common/model/school/classes/hourorder/Order.php
@@ -537,7 +537,7 @@ class Order extends BaseModel
 
         if($detail['sub_num']<=0) throw new \Exception("该课程已无剩余课时!");
         //不是可用状态
-        if($classesOrder['status']!="3") throw new \Exception("该课程单当前状态不可操作!");
+        if($check && $classesOrder['status']!="3") throw new \Exception("该课程单当前状态不可操作!");
         //售后中
         if($classesOrder['server_status']=="3") throw new \Exception("该课程单正在售后中,请勿操作!");
 
diff --git a/application/common/model/school/classes/order/Order.php b/application/common/model/school/classes/order/Order.php
index cae450f..f0f1625 100644
--- a/application/common/model/school/classes/order/Order.php
+++ b/application/common/model/school/classes/order/Order.php
@@ -750,7 +750,7 @@ class Order extends BaseModel
               $param  =  [
                 "type" =>'2',
                 "help_user_id" =>$order["user_id"]  ,
-                "help_type" => 'admin',
+                "help_type" => 'user',
               ];
 
             //确认订单
diff --git a/application/manystore/controller/csmtable/Cligenerateexcel.php b/application/manystore/controller/csmtable/Cligenerateexcel.php
new file mode 100644
index 0000000..c57a368
--- /dev/null
+++ b/application/manystore/controller/csmtable/Cligenerateexcel.php
@@ -0,0 +1,325 @@
+xlstask = new \app\admin\model\csmtable\Xlstask();
+    }
+
+    /**
+     * http://127.0.0.1/fastadmin_plugin_csmmeet/public/q3HJDu2RgE.php/csmtable/cligenerateexcel/index
+     */
+    public function index()
+    {
+        static::p('----generateExcelByClassname begin:');
+        set_time_limit(0);
+        $csmtable_xlstask_id = $this->request->request("csmtable_xlstask_id");
+
+        $pp = $this->request->request("params");
+        static::p($pp);
+        static::p($csmtable_xlstask_id);
+        $csmtable_xlstask_id = 119;
+        $pp = '{"search":null,"filter":"{}","op":"{}","sort":"weigh","order":"desc","offset":"0","limit":"10","csmtable_classname":"app\/admin\/controller\/fa\/Test","csmtable_methodname":"index","csmtable_columns":"[{\"field\":\"id\",\"title\":\"ID\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"title\",\"title\":\"\u6807\u9898\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"admin_id\",\"title\":\"\u7ba1\u7406\u5458ID\",\"datasource\":\"auth\/admin\",\"datafield\":\"nickname\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"category_id\",\"title\":\"\u5206\u7c7bID(\u5355\u9009)\",\"datasource\":\"category\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"category_ids\",\"title\":\"\u5206\u7c7bID(\u591a\u9009)\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"week\",\"title\":\"\u661f\u671f(\u5355\u9009)\",\"formatter\":\"\",\"searchList\":{\"monday\":\"\u661f\u671f\u4e00\",\"tuesday\":\"\u661f\u671f\u4e8c\",\"wednesday\":\"\u661f\u671f\u4e09\"},\"operate\":\"=\"},{\"field\":\"flag\",\"title\":\"\u6807\u5fd7(\u591a\u9009)\",\"formatter\":\"\",\"searchList\":{\"hot\":\"\u70ed\u95e8\",\"index\":\"\u9996\u9875\",\"recommend\":\"\u63a8\u8350\"},\"operate\":\"FIND_IN_SET\"},{\"field\":\"genderdata\",\"title\":\"\u6027\u522b(\u5355\u9009)\",\"formatter\":\"\",\"searchList\":{\"male\":\"\u7537\",\"female\":\"\u5973\"},\"operate\":\"=\"},{\"field\":\"hobbydata\",\"title\":\"\u7231\u597d(\u591a\u9009)\",\"formatter\":\"\",\"searchList\":{\"music\":\"\u97f3\u4e50\",\"reading\":\"\u8bfb\u4e66\",\"swimming\":\"\u6e38\u6cf3\"},\"operate\":\"FIND_IN_SET\"},{\"field\":\"image\",\"title\":\"\u56fe\u7247\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"images\",\"title\":\"\u56fe\u7247\u7ec4\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"attachfile\",\"title\":\"\u9644\u4ef6\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"keywords\",\"title\":\"\u5173\u952e\u5b57\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"description\",\"title\":\"\u63cf\u8ff0\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"city\",\"title\":\"\u7701\u5e02\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"price\",\"title\":\"\u4ef7\u683c\",\"formatter\":\"\",\"operate\":\"BETWEEN\"},{\"field\":\"views\",\"title\":\"\u70b9\u51fb\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"startdate\",\"title\":\"\u5f00\u59cb\u65e5\u671f\",\"formatter\":\"\",\"operate\":\"RANGE\"},{\"field\":\"activitytime\",\"title\":\"\u6d3b\u52a8\u65f6\u95f4(datetime)\",\"formatter\":\"\",\"operate\":\"RANGE\"},{\"field\":\"year\",\"title\":\"\u5e74\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"times\",\"title\":\"\u65f6\u95f4\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"refreshtime\",\"title\":\"\u5237\u65b0\u65f6\u95f4(int)\",\"formatter\":\"Table.api.formatter.datetime\",\"operate\":\"RANGE\"},{\"field\":\"createtime\",\"title\":\"\u521b\u5efa\u65f6\u95f4\",\"formatter\":\"Table.api.formatter.datetime\",\"operate\":\"RANGE\"},{\"field\":\"updatetime\",\"title\":\"\u66f4\u65b0\u65f6\u95f4\",\"formatter\":\"Table.api.formatter.datetime\",\"operate\":\"RANGE\"},{\"field\":\"weigh\",\"title\":\"\u6743\u91cd\",\"formatter\":\"\",\"operate\":\"=\"},{\"field\":\"switch\",\"title\":\"\u5f00\u5173\",\"formatter\":\"\",\"searchList\":{\"0\":\"\u5426\",\"1\":\"\u662f\"},\"operate\":\"=\"},{\"field\":\"status\",\"title\":\"\u72b6\u6001\",\"formatter\":\"\",\"searchList\":{\"normal\":\"\u6b63\u5e38\",\"hidden\":\"\u9690\u85cf\"},\"operate\":\"=\"},{\"field\":\"state\",\"title\":\"\u72b6\u6001\u503c\",\"formatter\":\"\",\"searchList\":{\"0\":\"\u7981\u7528\",\"1\":\"\u6b63\u5e38\",\"2\":\"\u63a8\u8350\"},\"operate\":\"=\"}]","csmtable_xlspagesize":null}';
+        $this->setProgress($csmtable_xlstask_id, 10);
+
+        $params = json_decode($pp, true);
+
+        $classname = str_replace('/', '\\', $this->getParamValue($params, 'csmtable_classname'));
+        $methodname = $this->getParamValue($params, 'csmtable_methodname');
+
+        $columnstr = $this->getParamValue($params, 'csmtable_columns');
+        $columns = json_decode($columnstr, true);
+
+        $excelPagesize = $this->getParamValue($params, 'csmtable_xlspagesize', 1000);
+        $this->generateExcelByClassname($csmtable_xlstask_id, $classname, $methodname, $params, $columns, $excelPagesize);
+
+        static::p('----generateExcelByClassname end:');
+        return;
+    }
+
+    private function setProgress(&$csmtable_xlstask_id, $progress, $filename = '')
+    {
+        // $dao = new \app\admin\model\csmtable\Xlstask();
+        // $this->xlstask->startTrans();
+        $this->xlstask->where("id", "=", $csmtable_xlstask_id)->update([
+            'progress' => $progress,
+            'filename' => $filename,
+            'updatetime' => time()
+        ]);
+        static::p('progress:' . $progress);
+        // $dao->commit();
+    }
+
+    private function getParamValue(&$params, $key, $defaultvalue = null)
+    {
+        $sr = null;
+        if (isset($params[$key])) {
+            $sr = $params[$key];
+        }
+        $sr = ($sr == null) ? $defaultvalue : $sr;
+        return $sr;
+    }
+
+    private function generateExcelByClassname(&$csmtable_xlstask_id, &$classname, &$methodname, &$params, &$columns, &$excelPagesize)
+    {
+        $pageno = 0; // 当前页数
+        $pagesize = 1000;
+
+        $excelRowIndex = 0; // 当前excel中的记录行数
+        $excelRows = []; // Excel记录
+        $excelFileNo = 1; // 第N个Excel
+        $excelFiles = [];
+
+        static::p("config excelPagesize:{$excelPagesize}");
+        $request = XcRequestUtils::getRequest();
+        $instance = new $classname($request);
+        while (true) {
+            $request->set('search', $this->getParamValue($params, 'search'));
+            $request->set('filter', $this->getParamValue($params, 'filter'));
+            $request->set('op', $this->getParamValue($params, 'op'));
+            $request->set('sort', $this->getParamValue($params, 'sort'));
+            $request->set('order', $this->getParamValue($params, 'order'));
+            // $request->set('offset',$this->getParamValue($params,'offset'));
+            $request->set('limit', $pagesize);
+            $request->setMethodReturn("isAjax", true);
+            $request->set("offset", $pageno * $pagesize);
+            $sr = App::invokeMethod([
+                $instance,
+                $methodname
+            ], null);
+            $request->clear();
+            if ($sr == null) {
+                break;
+            }
+
+            $datarows = &$sr->getData()['rows'];
+            $total = $sr->getData()['total'];
+
+            static::p("--remote total:{$total}/pageno:{$pageno}/offset:" . $pageno * $pagesize);
+            foreach ($datarows as &$row) {
+                if ($excelRowIndex >= $excelPagesize) {
+                    $progress = (int) ($pageno * $pagesize / $total * 70) + 10;
+                    $this->setProgress($csmtable_xlstask_id, $progress);
+
+                    static::p("------generate excel fileno:{$excelFileNo}/progress:{$progress}");
+                    $excelFiles[] = static::saveExcel($columns, $excelRows, $excelFileNo);
+                    $excelRowIndex = 0;
+                    unset($excelRows);
+                    $excelRows = [];
+                    $excelFileNo ++;
+                }
+                $excelRows[] = $row;
+                $excelRowIndex ++;
+            }
+            unset($datarows);
+            unset($sr);
+            $sr = null;
+
+            if ($total <= $pageno * $pagesize) {
+                break;
+            }
+            $pageno ++;
+            // break;
+        }
+
+        // 有剩余的Excel row,就保存剩余的
+        if ($excelRowIndex > 0) {
+            static::p("--generate excel fileno:{$excelFileNo}");
+            $excelFiles[] = static::saveExcel($columns, $excelRows, $excelFileNo);
+        }
+        // Excel保存到Zip
+        $this->setProgress($csmtable_xlstask_id, 90);
+        $zipfilename = static::saveExcelToZip($excelFiles);
+        echo $zipfilename . '
';
+        $this->setProgress($csmtable_xlstask_id, 100, $zipfilename);
+    }
+
+    private function saveExcel(&$columns, &$rows, &$excelNo)
+    {
+        echo $excelNo . '
';
+        $spreadsheet = new Spreadsheet();
+
+        $sheet = $spreadsheet->getActiveSheet();
+        $filename = 'excel-' . $excelNo;
+
+        foreach ($columns as $k => $item) {
+            $sheet->setCellValueByColumnAndRow($k + 1, 1, $item['title']);
+        }
+
+        $dsDatas = $this->getDataSourceDatas($columns, $rows);
+
+        foreach ($rows as $k => $item) {
+            foreach ($columns as $k2 => $column) {
+                $vv = $item[$column['field']];
+                $vv = $this->_convertValueByColumn($column, $vv, $dsDatas);
+                $sheet->setCellValueByColumnAndRow($k2 + 1, $k + 2, $vv);
+            }
+        }
+        unset($rows);
+        unset($dsDatas);
+        $filename = 'csmtable_' . time() . '_' . $excelNo . '.xlsx';
+        $filepath = &$this->uploadtmppath;
+        $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
+        $writer->save($filepath . $filename);
+        unset($writer);
+        $writer = null;
+        return [
+            'filename' => $filename,
+            'filepath' => $filepath
+        ];
+    }
+
+    private function getDataSourceDatas(&$columns, &$rows)
+    {
+        $sr = [];
+        foreach ($columns as &$column) {
+            if (isset($column['datasource']) && $column['datasource'] != null) {
+                $datafield = null;
+                if (isset($column['datafield']) && $column['datafield'] != null) {
+                    $datafield = $column['datafield'];
+                } else {
+                    $datafield = 'name';
+                }
+                $ids = [];
+                foreach ($rows as $item) {
+                    $ids[] = $item[$column['field']];
+                }
+
+                //v2.2.5 修复admin账号的安全楼栋
+                $datasdatasource_callremoteource = $column['datasource'];
+                if($datasdatasource_callremoteource=="auth/admin"){
+                    $datasdatasource_callremoteource = "csmtable/datasource/admin";
+                }
+                $im = CsmTableUtils::getInstanceAndMethod($datasdatasource_callremoteource);
+
+                if ($im != null) {
+                    $classname = $im[0];
+                    $methodname = $im[1];
+
+                    $request = XcRequestUtils::getRequest();
+                    $request->setMethodReturn("isAjax", true);
+                    $request->set('filter', '{"id":"' . implode(',', $ids) . '"}');
+                    $request->set('op', '{"id":"in"}');
+                    $request->set('sort', 'id');
+                    $request->set('order', 'desc');
+
+                    // \app\admin\controller\auth\Admin;
+                    $instance2 = new $classname($request);
+                    $json2 = App::invokeMethod([
+                        $instance2,
+                        $methodname
+                    ], null);
+                    $request->clear();
+
+                    if ($json2 == null) {
+                        break;
+                    }
+
+                    $datarows = &$json2->getData()['rows'];
+
+                    $vvs = [];
+                    foreach ($datarows as &$row) {
+                        $vv = null;
+                        if (isset($row[$datafield])) {
+                            $vv = $row[$datafield];
+                        } else {
+                            $vv = $row->$datafield;
+                        }
+
+                        $vvs['ID#' . $row['id']] = $vv;
+                    }
+                    unset($json2);
+                    unset($instance2);
+                    $instance2 = null;
+                }
+                $sr[$column['field']] = $vvs;
+            }
+        }
+        return $sr;
+    }
+
+    /**
+     * 将value根据table的options转换成文字
+     */
+    private function _convertValueByColumn(&$column, &$value, &$dsDatas)
+    {
+        $sr = '';
+
+        if (isset($column['searchList']) && $column['searchList'] != null) {
+            // searchlist类型的,将code转为name
+            $searchList = $column['searchList'];
+            // operate类型,字典数组,用逗号分隔
+            if (isset($column['operate']) && $column['operate'] != null && $column['operate'] == 'FIND_IN_SET') {
+                $ssarr = explode(",", $value);
+                $sslabel = [];
+                foreach ($ssarr as $ssarrv) {
+                    if (isset($searchList[$ssarrv])) {
+                        $sslabel[] = $searchList[$ssarrv];
+                    } else {
+                        $sslabel[] = $ssarrv;
+                    }
+                }
+                $sr = implode(',', $sslabel);
+            } else {
+                // 普通字典
+                if (isset($searchList[$value])) {
+                    $sr = $searchList[$value];
+                }
+            }
+        } else if (isset($column['formatter']) && $column['formatter'] != null && $column['formatter'] == "Table.api.formatter.datetime") {
+            // 时间型
+            if ($value != null && $value != '') {
+                $sr = date('Y-m-s h:i:s', $value);
+            }
+        } else if (isset($column['datasource']) && $column['datasource'] != null && $column['datasource'] != "") {
+            // 时间型
+            if (isset($dsDatas[$column['field']]) && $dsDatas[$column['field']] != null) {
+                $dsDataitem = $dsDatas[$column['field']];
+                if (isset($dsDataitem['ID#' . $value]) && $dsDataitem['ID#' . $value] != null) {
+                    $sr = $dsDataitem['ID#' . $value];
+                }
+            }
+            if ($sr == null || $sr == '') {
+                $sr = $value;
+            }
+        } else {
+            $sr = $value;
+        }
+        return $sr;
+    }
+
+    private function saveExcelToZip($excelFiles)
+    {
+        $zipfn = 'csmtable_' . time() . '.zip';
+        $zipfilename = $this->uploadtmppath . $zipfn;
+        $zip = new \ZipArchive();
+        $zip->open($zipfilename, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
+        foreach ($excelFiles as $item) {
+            $zip->addFile($item['filepath'] . $item['filename'], $item['filename']);
+        }
+        $zip->close();
+
+        foreach ($excelFiles as $item) {
+            unlink($item['filepath'] . $item['filename']);
+        }
+        return $zipfn;
+    }
+    
+    private static function p($str){
+        //echo( $str."
\r\n" ) ; 
+    }
+
+}
diff --git a/application/manystore/controller/csmtable/Csmgenerate.php b/application/manystore/controller/csmtable/Csmgenerate.php
new file mode 100644
index 0000000..22f9aad
--- /dev/null
+++ b/application/manystore/controller/csmtable/Csmgenerate.php
@@ -0,0 +1,88 @@
+request;
+        $filesource = $request->request('csmtable_filesource');
+        $indexurl = $request->request('csmtable_indexurl');
+
+        $dao = new \app\admin\model\csmtable\Xlstask();
+        // 限制下载
+        if (true) {
+            $userinfo = $this->auth->getUserInfo();
+ 
+            $adminId = $userinfo["id"];
+            $row = $dao->where("admin_id", "=", $adminId)
+                ->where("progress", "<", "100")
+                ->where("createtime", ">", time() - 1800)
+                ->where("iserror", "<>", "Y")
+                ->find();
+            if ($row) {
+                $this->error("当前有下载任务,请任务结束后再尝试下载。");
+            }
+        }
+
+        // 生成任务记录
+        $dao->where("admin_id", "=", $adminId)
+            ->where("filesource", '=', $filesource)
+            ->where("status", "=", "normal")
+            ->update([
+            "status" => "hidden"
+        ]);
+
+        // 触发异步生成Excel任务
+        $route2 = CsmTableUtils::getInstanceAndMethod($indexurl);
+        $classname = $route2[0];
+
+        $getparams = [
+            'search' => $request->request('search'),
+            'filter' => $request->request('filter'),
+            'op' => $request->request('op'),
+            'sort' => $request->request('sort'),
+            'order' => $request->request('order'),
+            'offset' => $request->request('offset'),
+            'limit' => $request->request('limit'),
+            'csmtable_classname' => str_replace('\\', '/', $classname),
+            'csmtable_methodname' => $route2[1],
+            'csmtable_columns' => $request->request('csmtable_columns')
+        ];
+
+ 
+        $param = [
+            'admin_id' => $adminId,
+            'filesource' => $filesource,
+            'param' => json_encode($getparams),
+            'createtime' => time(),
+ 
+        ];
+        $dao->create($param);
+        $this->success();
+        
+        // $id = $dao->getLastInsID();
+
+        // $ret = $this->_index($id);
+        // if($ret===true){
+        //     $this->success();
+        // }else{
+        //     $this->error($ret);
+        // }
+    }
+
+ 
+   
+ 
+}
diff --git a/application/manystore/controller/csmtable/Csmxlstable.php b/application/manystore/controller/csmtable/Csmxlstable.php
new file mode 100644
index 0000000..5c94f4c
--- /dev/null
+++ b/application/manystore/controller/csmtable/Csmxlstable.php
@@ -0,0 +1,85 @@
+model = new \app\admin\model\csmtable\Xlstask();
+    }
+
+    /**
+     * 前台轮询查询下载进度
+     * http://127.0.0.1/fastadmin_plugin_csmmeet/public/q3HJDu2RgE.php/csmtable/csmxlstable/queryGenerageStatus
+     */
+    public function queryGenerageStatus()
+    {
+        $filesource = $this->request->request("filesource");
+        $auth = Auth::instance();
+
+        $row = $this->model->where("admin_id", "=", $auth->id)
+            ->where("filesource", '=', $filesource)
+            ->where("status", "=", "normal")
+            ->field("id,createtime,progress,iserror,errormsg")
+            ->order("id", "desc")
+            ->find();
+        // echo $this->model->getLastSql();
+        if ($row != null) {
+            // $row->filesource = str_replace(Config::get('upload.cdnurl'), '', $row->filesource);
+            $row->createtime = date('Y-m-d H:i:s', $row->createtime);
+        }
+
+        $this->success('', null, [
+            'row' => $row
+        ]);
+    }
+
+    public function download()
+    {
+        $auth = Auth::instance();
+        $id = $this->request->request("id");
+        $row = $this->model->where("admin_id", "=", $auth->id)
+            ->where("id", "=", $id)
+            ->find();
+
+        if ($row == null) {
+            $this->error("文件不存在,请重新下载!");
+        }
+        $filename = $row->filename;
+        //var_dump($filename);
+        // $filename='csmtable_1588643591.zip';//完整文件名(路径加名字)
+        if (! file_exists($this->uploadtmppath . $filename)) {
+            header('HTTP/1.1 404 NOT FOUND');
+        } else {
+            $file = fopen($this->uploadtmppath . $filename, "rb");
+            Header("Content-type: application/octet-stream");
+            Header("Accept-Ranges: bytes");
+            Header("Accept-Length: " . filesize($this->uploadtmppath . $filename));
+            Header("Content-Disposition: attachment; filename=" . $filename);
+            echo fread($file, filesize($this->uploadtmppath . $filename));
+            fclose($file);
+            exit();
+        }
+    }
+}
diff --git a/application/manystore/controller/csmtable/Datasource.php b/application/manystore/controller/csmtable/Datasource.php
new file mode 100644
index 0000000..67d61da
--- /dev/null
+++ b/application/manystore/controller/csmtable/Datasource.php
@@ -0,0 +1,34 @@
+request->get("filter", '');
+        $filter = (array)json_decode($filter, true);
+
+        $dao = new \app\admin\model\Admin();
+        $list = $dao->where("id","in",$filter['id'])->field("id,nickname")->select();
+
+        return json(['rows' => $list]);
+    }
+
+   
+}
diff --git a/application/manystore/controller/csmtable/Test.php b/application/manystore/controller/csmtable/Test.php
new file mode 100644
index 0000000..69dcddb
--- /dev/null
+++ b/application/manystore/controller/csmtable/Test.php
@@ -0,0 +1,107 @@
+model = new \app\admin\model\csmtable\Test();
+        $this->view->assign("weekList", $this->model->getWeekList());
+        $this->view->assign("flagList", $this->model->getFlagList());
+        $this->view->assign("genderdataList", $this->model->getGenderdataList());
+        $this->view->assign("hobbydataList", $this->model->getHobbydataList());
+        $this->view->assign("statusList", $this->model->getStatusList());
+        $this->view->assign("stateList", $this->model->getStateList());
+    }
+
+    /**
+     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
+     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
+     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
+     */
+ 
+
+    // https://csmtable.163fan.com/amZUNRxJGT.php//csmtable/test/generatedatas
+    protected function generatedatas()
+    {
+        $generatecount = 10;
+        $subsieze = 1001;
+        $count = $this->model->count();
+
+        for ($i = 0; $i < $generatecount; $i ++) {
+            $rows = [];
+
+            for ($ii = 0; $ii < $subsieze; $ii ++) {
+                $co = $i * $subsieze + $ii + $count;
+                $param = [
+                    'admin_id' => 1,
+                    'category_id' => 1,
+                    'category_ids' => '1,2',
+                    'week' => 'monday',
+                    'flag' => 'index',
+                    'hobbydata' => 'music,swimming',
+                    'city' => 'xxx',
+                    'views' => Random::numeric(2),
+                    'price' => 0,
+                    'year' => 2020,
+                    'status' => 'normal',
+                    'state' => '1'
+                ];
+                $param['title'] = "我是{$co}篇测试文章" . time();
+                $param['createtime'] = time();
+                $param['content'] = Random::alpha(100);
+                $rows[] = $param;
+            }
+
+            $this->model->saveAll($rows);
+        }
+        $this->success("生成完成记录" . $generatecount * $subsieze, null, null, '10000');
+    }
+
+    /**
+     * 查看
+     */
+    public function index()
+    {
+        // 设置过滤方法
+        $this->request->filter([
+            'strip_tags'
+        ]);
+        if ($this->request->isAjax()) {
+            trace('----test------');
+            // 如果发送的来源是Selectpage,则转发到Selectpage
+            if ($this->request->request('keyField')) {
+                return $this->selectpage();
+            }
+            list ($where, $sort, $order, $offset, $limit) = $this->buildparams();
+            //在2.2.3版本中调整为fastadmin.1.3.3的写法
+            $list = $this->model
+                ->where($where)
+                ->order($sort, $order)
+                ->paginate($limit);
+                $result = array("total" => $list->total(), "rows" => $list->items(),"totalviews" => 1530);
+
+
+            return json($result);
+        }
+        return $this->view->fetch();
+    }
+ 
+}
diff --git a/application/manystore/controller/csmtable/Xlstask.php b/application/manystore/controller/csmtable/Xlstask.php
new file mode 100644
index 0000000..db51f98
--- /dev/null
+++ b/application/manystore/controller/csmtable/Xlstask.php
@@ -0,0 +1,57 @@
+model = new \app\admin\model\csmtable\Xlstask();
+    }
+
+    /**
+     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
+     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
+     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
+     */
+
+    public function index()
+    {
+        //设置过滤方法
+        $this->request->filter(['strip_tags', 'trim']);
+        if (false === $this->request->isAjax()) {
+            return $this->view->fetch();
+        }
+        //如果发送的来源是 Selectpage,则转发到 Selectpage
+        if ($this->request->request('keyField')) {
+            return $this->selectpage();
+        }
+        [$where, $sort, $order, $offset, $limit] = $this->buildparams();
+        $list = $this->model
+            ->where($where)
+            ->order($sort, $order)
+            ->paginate($limit);
+
+        XcDaoUtils::bindDbListColumn($list, "admin_id", new \app\admin\model\Admin(), "admin", ["nickname"]);
+
+        $result = ['total' => $list->total(), 'rows' => $list->items()];
+        return json($result);
+    }
+}
diff --git a/application/manystore/controller/school/classes/ClassesLib.php b/application/manystore/controller/school/classes/ClassesLib.php
index dd37c2c..3bb4e08 100644
--- a/application/manystore/controller/school/classes/ClassesLib.php
+++ b/application/manystore/controller/school/classes/ClassesLib.php
@@ -39,7 +39,7 @@ class ClassesLib extends ManystoreBase
     protected $model = null;
 
     //不用审核允许修改的字段
-    protected $no_auth_fields = ["classes_type","classes_cate_ids","classes_label_ids","self_label_tag",'headimage','images','notice','content',"virtual_num","virtual_collect","underline_price","selfhot","price","classes_num"];
+    protected $no_auth_fields = ["title","classes_type","classes_cate_ids","classes_label_ids","self_label_tag",'headimage','images','notice','content',"virtual_num","virtual_collect","underline_price","selfhot","price","classes_num"];
 
     //更新数据是否需要触发审核开关
     protected $need_auth = true;
diff --git a/extend/bw/UrlLock.php b/extend/bw/UrlLock.php
index 6352b8b..b3a87e9 100644
--- a/extend/bw/UrlLock.php
+++ b/extend/bw/UrlLock.php
@@ -76,6 +76,13 @@ class UrlLock
         return $this;
     }
 
+    /** 析构时释放锁
+     * @throws UrlLockException
+     */
+    public function __destruct()
+    {
+       if ($this->is_lock)$this->free();
+    }
     public function hasLock(){
         return $this->is_lock;
     }
diff --git a/extend/fast/Auth.php b/extend/fast/Auth.php
index 81429ef..2217416 100644
--- a/extend/fast/Auth.php
+++ b/extend/fast/Auth.php
@@ -134,6 +134,7 @@ class Auth
         if ('and' == $relation && empty($diff)) {
             return true;
         }
+//        var_dump($name,$uid);
 
         return false;
     }
diff --git a/extend/traits/CacheTrait.php b/extend/traits/CacheTrait.php
index e5f83f2..fbde1b2 100644
--- a/extend/traits/CacheTrait.php
+++ b/extend/traits/CacheTrait.php
@@ -79,20 +79,30 @@ trait CacheTrait
 //        $redis->del($hashKey);
 //        var_dump($hashKey);die;
         //判断锁是否存在,如果存在,返回错误
-        if ($redis->exists($hashKey)){
-//            var_dump(111111222);die;
+//        if ($redis->exists($hashKey)){
+////            var_dump(111111222);die;
+//            if($this->cache_lock_thorws_excption){
+//                throw new \Exception($this->cache_lock_error_msg);
+//            }else{
+//                return false;
+//            }
+//
+//        }
+        //如果不存在创建锁并返回
+//        $redis->set($hashKey, 1,$timeout);//注释掉
+        //替换成原子操作的命令
+        $nxLock =  $redis->set($hashKey, 1,['nx', 'ex' => $timeout]);
+        if ($nxLock == 1) {
+            return true;
+        } else {
             if($this->cache_lock_thorws_excption){
                 throw new \Exception($this->cache_lock_error_msg);
             }else{
                 return false;
             }
-
         }
-        //如果不存在创建锁并返回
-//        $redis->set($hashKey, 1,$timeout);//注释掉
-        //替换成原子操作的命令
-        $redis->set($hashKey, 1,['nx', 'ex' => $timeout]);
-        return true;
+
+
     }
 
 
@@ -112,9 +122,25 @@ trait CacheTrait
         $redis = $this->getRedis();
         if(!$key || !$suffix) return true;
         $hashKey = $key.$suffix;
-        if (!$redis->EXISTS($hashKey)) return true;
-        $redis->del($hashKey);
-        return true;
+
+        //执行lua脚本,确保删除锁是原子操作
+        $lua = 'if redis.call("get",KEYS[1]) == ARGV[1]
+        then
+            return redis.call("del",KEYS[1])
+        else
+            return 0
+        end';
+        $result = $redis->eval($lua, [$hashKey, 1], 1);
+
+        if ('1' == $result) {
+
+            return true;
+        }
+        return false;
+
+//        if (!$redis->EXISTS($hashKey)) return true;
+//        $redis->del($hashKey);
+//        return true;
     }
 
 
@@ -123,5 +149,4 @@ trait CacheTrait
 
 
 
-
 }
diff --git a/public/assets/js/backend/school/classes/classes_lib.js b/public/assets/js/backend/school/classes/classes_lib.js
index 3c9d6f8..1a837e9 100644
--- a/public/assets/js/backend/school/classes/classes_lib.js
+++ b/public/assets/js/backend/school/classes/classes_lib.js
@@ -1,4 +1,4 @@
-define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
+define(['jquery', 'bootstrap', 'backend', 'csmtable', 'form'], function ($, undefined, Backend, Table, Form) {
 
     var Controller = {
         index: function () {
@@ -31,6 +31,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                 sortName: 'weigh',
                 fixedColumns: true,
                 fixedRightNumber: 2,
+                asyndownload: true,
                 columns: [
                     [
 
diff --git a/public/assets/js/backend/school/classes/hourorder/order.js b/public/assets/js/backend/school/classes/hourorder/order.js
index 3704ec2..98c99c5 100644
--- a/public/assets/js/backend/school/classes/hourorder/order.js
+++ b/public/assets/js/backend/school/classes/hourorder/order.js
@@ -1,4 +1,4 @@
-define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
+define(['jquery', 'bootstrap', 'backend', 'csmtable', 'form'], function ($, undefined, Backend, Table, Form) {
 
     var Controller = {
         index: function () {
@@ -25,6 +25,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                 pk: 'id',
                 sortName: 'id',
                 fixedColumns: true,
+                asyndownload: true,
                 fixedRightNumber: 1,
                 columns: [
                     [
diff --git a/public/assets/js/backend/school/classes/order/order.js b/public/assets/js/backend/school/classes/order/order.js
index 16d666b..51a0be7 100644
--- a/public/assets/js/backend/school/classes/order/order.js
+++ b/public/assets/js/backend/school/classes/order/order.js
@@ -26,7 +26,7 @@ define(['jquery', 'bootstrap', 'backend', 'csmtable', 'form'], function ($, unde
                 sortName: 'id',
                 fixedColumns: true,
                 fixedRightNumber: 1,
-                // asyndownload: true,
+                 asyndownload: true,
                 columns: [
                     [
                         {checkbox: true},
diff --git a/public/assets/js/backend/user/user.js b/public/assets/js/backend/user/user.js
index a88f481..7788a9d 100644
--- a/public/assets/js/backend/user/user.js
+++ b/public/assets/js/backend/user/user.js
@@ -1,4 +1,4 @@
-define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
+define(['jquery', 'bootstrap', 'backend', 'csmtable', 'form'], function ($, undefined, Backend, Table, Form) {
 
     var Controller = {
         index: function () {
@@ -23,6 +23,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                 sortName: 'user.id',
                 fixedColumns: true,
                 fixedRightNumber: 1,
+                asyndownload: true,
                 columns: [
                     [
                         {checkbox: true},
diff --git a/public/assets/js/manystore/school/classes/teacher.js b/public/assets/js/manystore/school/classes/teacher.js
index db50456..938ed99 100644
--- a/public/assets/js/manystore/school/classes/teacher.js
+++ b/public/assets/js/manystore/school/classes/teacher.js
@@ -1,4 +1,4 @@
-define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
+define(['jquery', 'bootstrap', 'backend', 'csmtable', 'form'], function ($, undefined, Backend, Table, Form) {
 
     var Controller = {
         index: function () {
@@ -28,7 +28,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                 sortName: 'weigh',
                 fixedColumns: true,
                 fixedRightNumber: 2,
-
+                asyndownload: true,
                 columns: [
                     [
                         {checkbox: true},