From b90b528cb5c6eaebe03fba972fef658a741ce896 Mon Sep 17 00:00:00 2001
From: quanwei <419654421@qq.com>
Date: Thu, 26 Feb 2026 18:19:13 +0800
Subject: [PATCH] 活动评价

---
 shop_vue/src/views/plus/region/auth/role/edit.vue           |  228 ++
 shop_vue/src/views/plus/region/auth/access/part/Edit.vue    |  210 ++
 branch_vue/src/views/activity/activity/drawer/part/edit.vue |   81 
 shop_vue/src/views/branch/activity/add.vue                  |   74 
 shop_vue/src/views/plus/region/auth/role/Index.vue          |  142 +
 shop_vue/src/views/branch/activity/drawer/part/edit.vue     |   74 
 branch_vue/src/api/branch.js                                |   21 
 shop_vue/src/views/plus/region/role/edit.vue                |  170 ++
 agent_vue/src/api/plugs.js                                  |    4 
 admin/app/common/model/branch/ActivityComment.php           |  218 ++
 branch_vue/src/views/activity/activity/add.vue              |   75 
 admin/app/shop/service/region/MenusService.php              |   82 +
 mobile/pages/branch/admin/activity/edit.vue                 |   45 
 shop_vue/src/views/plus/region/role/add.vue                 |  121 +
 admin/app/branch/controller/activity/Comment.php            |   62 
 branch_vue/src/views/activity/comment/index.vue             |  233 ++
 operations_vue/static/UE/dialogs/spechars/spechars.js       |    4 
 shop_vue/static/UE/dialogs/spechars/spechars.js             |    4 
 shop_vue/src/views/plus/region/role/index.vue               |  135 +
 mobile/pages/user/my_activity/detail.vue                    |   14 
 shop_vue/src/views/plus/region/auth/user/dialog/Add.vue     |  130 +
 mobile/pages/user/my_activity/index.vue                     |   29 
 admin/app/shop/model/branch/ActivityComment.php             |   78 
 admin/app/common/model/branch/ActivityCommentImage.php      |   22 
 admin/app/api/controller/branch/ActivityComment.php         |   75 
 shop_vue/src/views/plus/region/user/dialog/Add.vue          |  305 +++
 admin/config/cache.php                                      |   24 
 mobile/pages.json                                           |   12 
 shop_vue/src/api/branch.js                                  |   21 
 shop_vue/src/views/plus/region/auth/role/add.vue            |  179 ++
 shop_vue/src/views/plus/region/auth/access/Index.vue        |  288 +++
 shop_vue/src/views/plus/region/auth/index.vue               |   35 
 admin/app/api/model/branch/ActivityComment.php              |   49 
 shop_vue/src/views/branch/comment/detail.vue                |  150 +
 admin/app/shop/controller/branch/ActivityComment.php        |   62 
 mobile/pages/branch/admin/activity/add.vue                  |   45 
 branch_vue/src/views/activity/comment/detail.vue            |  147 +
 shop_vue/src/views/plus/region/auth/user/dialog/Edit.vue    |  154 +
 shop_vue/src/views/plus/region/auth/access/part/Add.vue     |  218 ++
 agent_vue/src/api/user.js                                   |    4 
 shop_vue/src/views/plus/region/auth/user/Admin.vue          |  203 ++
 shop_vue/src/views/branch/setting/part/Basic.vue            |    6 
 shop_vue/src/views/branch/comment/index.vue                 |  236 ++
 branch_vue/static/UE/dialogs/spechars/spechars.js           |    4 
 agent_vue/src/views/help/Fonticon.vue                       |    6 
 mobile/pages/branch/activity/evaluate/evaluate.vue          |  277 +++
 admin/app/branch/model/activity/Comment.php                 |   90 +
 47 files changed, 4,751 insertions(+), 95 deletions(-)

diff --git a/admin/app/api/controller/branch/ActivityComment.php b/admin/app/api/controller/branch/ActivityComment.php
new file mode 100644
index 0000000..536c961
--- /dev/null
+++ b/admin/app/api/controller/branch/ActivityComment.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace app\api\controller\branch;
+
+use app\api\controller\Controller;
+use app\api\model\branch\ActivityComment as ActivityCommentModel;
+use app\api\model\branch\ActivityUser as ActivityUserModel;
+
+/**
+ * 活动评论控制器
+ */
+class ActivityComment extends Controller
+{
+    /**
+     * 获取活动评论列表
+     */
+    public function lists($activity_id)
+    {
+        $model = new ActivityCommentModel;
+        $list = $model->getActivityCommentList($activity_id, $this->postData());
+        return $this->renderSuccess('', compact('list'));
+    }
+
+    /**
+     * 获取活动评论统计
+     */
+    public function statistics($activity_id)
+    {
+        $model = new ActivityCommentModel;
+        $statistics = $model->getCommentStatistics($activity_id);
+        return $this->renderSuccess('', compact('statistics'));
+    }
+
+    /**
+     * 活动报名详情及评价表单
+     */
+    public function order($order_id)
+    {
+        // 报名记录
+        $activityUser = ActivityUserModel::detail($order_id, ['activity', 'activity.visitSupplier']);
+        // 验证是否允许评论
+        $model = new ActivityCommentModel;
+        if (!$model->checkActivityUserAllowComment($activityUser)) {
+            return $this->renderError($model->getError());
+        }
+
+        // 获取供应商名称
+        $supplierName = '';
+        if (isset($activityUser['activity']['visit_supplier_name'])) {
+            $supplierName = $activityUser['activity']['visit_supplier_name'];
+        } elseif (isset($activityUser['activity']['visitSupplier']) && $activityUser['activity']['visitSupplier'] && isset($activityUser['activity']['visitSupplier']['name'])) {
+            $supplierName = $activityUser['activity']['visitSupplier']['name'];
+        }
+
+        // 返回报名信息用于展示
+        $data = [
+            'order_id' => $activityUser['order_id'],
+            'activity_id' => $activityUser['activity_id'],
+            'activity_name' => $activityUser['activity']['name'],
+            'supplier_name' => $supplierName,
+        ];
+
+        // 提交评论
+        if ($this->request->isPost()) {
+            $formData =$this->request->request('formData');
+            $formData = json_decode($formData,true);
+            if ($model->addForActivityUser($activityUser, $formData)) {
+                return $this->renderSuccess('评价发表成功');
+            }
+            return $this->renderError($model->getError() ?: '评价发表失败');
+        }
+
+        return $this->renderSuccess('', $data);
+    }
+}
\ No newline at end of file
diff --git a/admin/app/api/model/branch/ActivityComment.php b/admin/app/api/model/branch/ActivityComment.php
new file mode 100644
index 0000000..44a8dcd
--- /dev/null
+++ b/admin/app/api/model/branch/ActivityComment.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace app\api\model\branch;
+
+use app\common\model\branch\ActivityComment as ActivityCommentModel;
+
+/**
+ * 活动评论API模型
+ */
+class ActivityComment extends ActivityCommentModel
+{
+    /**
+     * 隐藏字段
+     */
+    protected $hidden = [
+        'status',
+        'sort',
+        'is_delete',
+        'update_time'
+    ];
+
+    /**
+     * 根据活动报名记录添加评论
+     */
+    public function addForActivityUser($activityUser, $formData)
+    {
+        return $this->transaction(function () use ($activityUser, $formData) {
+            // 添加评论
+            $result = $this->addComment($activityUser, $formData);
+
+            if (!$result) {
+                return false;
+            }
+            // 保存评论图片
+            if (!empty($formData['image_list'])) {
+                $this->saveCommentImages($this['comment_id'], $formData['image_list']);
+            }
+            return true;
+        });
+    }
+
+    /**
+     * 检查活动报名是否可以评论
+     */
+    public function checkActivityUserAllowComment($activityUser)
+    {
+        return $this->checkAllowComment($activityUser);
+    }
+}
diff --git a/admin/app/branch/controller/activity/Comment.php b/admin/app/branch/controller/activity/Comment.php
new file mode 100644
index 0000000..9192af6
--- /dev/null
+++ b/admin/app/branch/controller/activity/Comment.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace app\branch\controller\activity;
+
+use app\branch\controller\Controller;
+use app\branch\model\activity\Comment as CommentModel;
+
+/**
+ * 活动评论控制器
+ */
+class Comment extends Controller
+{
+    /**
+     * 评论列表
+     */
+    public function index()
+    {
+        $model = new CommentModel;
+        $postData = $this->postData();
+
+        $where[] = ['is_delete', '=', 0];
+        
+        // 列表
+        $list = $model->getList($postData, $this->getBranchId());
+        // 待审核数量
+        $num = $model->getStatusNum($where, $this->getBranchId());
+        return $this->renderSuccess('', compact('list', 'num'));
+    }
+
+    /**
+     * 评论详情
+     */
+    public function detail($comment_id)
+    {
+        $data = CommentModel::detail($comment_id, ['user', 'activity', 'images.file']);
+        return $this->renderSuccess('', compact('data'));
+    }
+
+    /**
+     * 更新评论
+     */
+    public function edit($comment_id)
+    {
+        $model = CommentModel::detail($comment_id);
+        if ($model->editComment($this->postData())) {
+            return $this->renderSuccess('修改成功');
+        }
+        return $this->renderError('修改失败');
+    }
+
+    /**
+     * 删除评论
+     */
+    public function delete($comment_id)
+    {
+        $model = new CommentModel();
+        if (!$model->setDelete($comment_id)) {
+            return $this->renderError('删除失败');
+        }
+        return $this->renderSuccess('删除成功');
+    }
+}
diff --git a/admin/app/branch/model/activity/Comment.php b/admin/app/branch/model/activity/Comment.php
new file mode 100644
index 0000000..02c25a5
--- /dev/null
+++ b/admin/app/branch/model/activity/Comment.php
@@ -0,0 +1,90 @@
+<?php
+
+namespace app\branch\model\activity;
+
+use app\common\model\branch\ActivityComment as ActivityCommentModel;
+
+/**
+ * 活动评论模型
+ */
+class Comment extends ActivityCommentModel
+{
+    /**
+     * 获取列表
+     */
+    public function getList($params, $branch_id)
+    {
+        $model = $this->with(['user', 'activity'])
+            ->where('is_delete', '=', 0);
+
+        // 限制当前分会
+        $model = $model->whereHas('activity', function ($query) use ($branch_id) {
+            $query->where('branch_id', '=', $branch_id);
+        });
+
+        // 按审核状态筛选
+        if (isset($params['status']) && $params['status'] != -1) {
+            $model = $model->where('status', '=', $params['status']);
+        }
+
+        // 按评分筛选
+        if (isset($params['score']) && $params['score'] > 0) {
+            if ($params['score'] == 10) {
+                // 好评 4-5分
+                $model = $model->where('score', '>=', 4);
+            } elseif ($params['score'] == 20) {
+                // 中评 2-3分
+                $model = $model->whereBetween('score', [2, 3]);
+            } elseif ($params['score'] == 30) {
+                // 差评 1分
+                $model = $model->where('score', '=', 1);
+            }
+        }
+
+        // 按活动名称搜索
+        if (isset($params['name']) && !empty($params['name'])) {
+            $model = $model->whereHas('activity', function ($query) use ($params) {
+                $query->where('name', 'like', '%' . $params['name'] . '%');
+            });
+        }
+
+        return $model->order(['sort' => 'asc', 'create_time' => 'desc'])
+            ->paginate($params);
+    }
+
+    /**
+     * 获取待审核数量
+     */
+    public function getStatusNum($branch_id = 0)
+    {
+        $model = $this->where('status', '=', 0)
+            ->where('is_delete', '=', 0);
+        
+        if ($branch_id) {
+            $model = $model->whereHas('activity', function ($query) use ($branch_id) {
+                $query->where('branch_id', '=', $branch_id);
+            });
+        }
+        
+        return $model->count();
+    }
+
+    /**
+     * 更新评论
+     */
+    public function editComment($data)
+    {
+        return $this->save([
+            'status' => $data['status'] ?? $this['status'],
+            'sort' => $data['sort'] ?? $this['sort'],
+        ]);
+    }
+
+    /**
+     * 软删除
+     */
+    public function setDelete($comment_id)
+    {
+        return $this->where('comment_id', '=', $comment_id)->save(['is_delete' => 1]);
+    }
+}
diff --git a/admin/app/common/model/branch/ActivityComment.php b/admin/app/common/model/branch/ActivityComment.php
new file mode 100644
index 0000000..61334fe
--- /dev/null
+++ b/admin/app/common/model/branch/ActivityComment.php
@@ -0,0 +1,218 @@
+<?php
+
+namespace app\common\model\branch;
+
+use app\common\model\BaseModel;
+
+/**
+ * 活动评论模型
+ */
+class ActivityComment extends BaseModel
+{
+    protected $name = 'branch_activity_comment';
+    protected $pk = 'comment_id';
+
+    /**
+     * 追加字段
+     * @var string[]
+     */
+    protected $append = [
+        'create_time_text',
+    ];
+
+    /**
+     * 关联用户表
+     */
+    public function user()
+    {
+        return $this->belongsTo('app\\common\\model\\user\\User', 'user_id', 'user_id')
+            ->field(['user_id', 'nickName', 'avatarUrl', 'real_name']);
+    }
+
+    /**
+     * 关联活动表
+     */
+    public function activity()
+    {
+        return $this->belongsTo('app\\common\\model\\branch\\Activity', 'activity_id', 'activity_id');
+    }
+
+    /**
+     * 关联活动报名表
+     */
+    public function activityUser()
+    {
+        return $this->belongsTo('app\\common\\model\\branch\\ActivityUser', 'order_id', 'order_id');
+    }
+
+    /**
+     * 关联评论图片表
+     */
+    public function images()
+    {
+        return $this->hasMany('app\\common\\model\\branch\\ActivityCommentImage', 'comment_id', 'comment_id');
+    }
+
+    /**
+     * 关联图片文件
+     */
+
+    /**
+     * 创建时间文本
+     */
+    public function getCreateTimeTextAttr($value, $data)
+    {
+        return isset($data['create_time']) ? date('Y-m-d H:i:s', $data['create_time']) : '';
+    }
+
+    /**
+     * 检查报名记录是否允许评论
+
+    /**
+     * 获取活动评论列表
+     */
+    public function getActivityCommentList($activity_id, $params = [])
+    {
+        $model = $this->with(['user', 'images.file'])
+            ->where('activity_id', '=', $activity_id)
+            ->where('is_delete', '=', 0)
+            ->where('status', '=', 1);
+
+        // 按评分筛选
+        if (isset($params['score']) && $params['score'] > 0) {
+            $model = $model->where('score', '=', $params['score']);
+        }
+
+        return $model->order(['sort' => 'asc', 'create_time' => 'desc'])
+            ->paginate($params);
+    }
+
+    /**
+     * 获取活动评论统计
+     */
+    public function getCommentStatistics($activity_id)
+    {
+        return $this->field([
+            'count(comment_id) AS `all`',
+            'count(score >= 4 OR NULL) AS `good`',
+            'count(score >= 2 AND score <= 3 OR NULL) AS `medium`',
+            'count(score = 1 OR NULL) AS `bad`',
+        ])->where([
+            'activity_id' => $activity_id,
+            'is_delete' => 0,
+            'status' => 1
+        ])->find();
+    }
+
+    /**
+     * 获取企业的差评数量
+     * @param int $supplier_id 企业ID
+     * @return int 差评数量
+     */
+    public function getSupplierNegativeCommentCount($supplier_id,$visit_supplier_name,$exclude_activity_id=0)
+    {
+        $model=$this;
+        if ($exclude_activity_id){
+            $model = $model->where('activity_id', '<>', $exclude_activity_id);
+        }
+        $count = $model->where(function ($query) use ($supplier_id,$visit_supplier_name) {
+            $query->where('supplier_id', '=', $supplier_id)
+                ->whereOr('supplier_name', '=', $visit_supplier_name);
+        })->where([
+            'score' => 1, // 1分为差评
+            'is_delete' => 0,
+            'status' => 1
+        ])->count();
+
+        return $count;
+    }
+
+    /**
+     * 验证报名记录是否允许评论
+     * @param object $activityUser 报名记录
+     * @return bool
+     */
+    public function checkAllowComment($activityUser)
+    {
+        // 验证是否已签到
+        if ($activityUser['is_verify'] != 1) {
+            $this->error = '请先签到后再评价';
+            return false;
+        }
+
+        // 验证活动是否已结束
+        $activity = $activityUser['activity'];
+        if ($activity['status_text']['status'] != 2) {
+            $this->error = '活动结束后才能评价';
+            return false;
+        }
+
+        // 验证是否已评价
+        $hasComment = $this->where(['order_id' => $activityUser['order_id']])->find();
+        if ($hasComment) {
+            $this->error = '您已经评价过该活动';
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * 添加评论
+     */
+    public function addComment($activityUser, $data)
+    {
+        // 验证是否允许评论
+        if (!$this->checkAllowComment($activityUser)) {
+            return false;
+        }
+
+        $commentData = [
+            'activity_id' => $activityUser['activity_id'],
+            'order_id' => $activityUser['order_id'],
+            'user_id' => $activityUser['user_id'],
+            'supplier_id' => $activityUser['activity']['visit_supplier_id'] ?: 0,
+            'supplier_name' => $activityUser['activity']['visit_supplier_name'] ?: '',
+            'content' => $data['content'] ?: '',
+            'score' => $data['score'] ?: 5,
+            'is_picture' => !empty($data['image_list']) ? 1 : 0,
+            'sort' => 100,
+            'status' => 0, // 待审核
+            'app_id' => self::$app_id,
+        ];
+
+        return $this->save($commentData);
+    }
+
+    /**
+     * 保存评论图片
+     */
+    public function saveCommentImages($comment_id, $image_list)
+    {
+        $this->images()->delete();
+        if (empty($image_list)) {
+            return true;
+        }
+
+        $imageData = [];
+        foreach ($image_list as $image) {
+            $imageData[] = [
+                'comment_id' => $comment_id,
+                'image_id' => $image['file_id'],
+                'app_id' => self::$app_id,
+                'create_time' => time(),
+            ];
+        }
+
+        $commentImageModel = new ActivityCommentImage();
+        return $commentImageModel->saveAll($imageData);
+    }
+
+    /**
+     * 详情
+     */
+    public static function detail($comment_id, $with = [])
+    {
+        return (new static())->with($with)->find($comment_id);
+    }
+}
diff --git a/admin/app/common/model/branch/ActivityCommentImage.php b/admin/app/common/model/branch/ActivityCommentImage.php
new file mode 100644
index 0000000..81c4602
--- /dev/null
+++ b/admin/app/common/model/branch/ActivityCommentImage.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace app\common\model\branch;
+
+use app\common\model\BaseModel;
+
+/**
+ * 活动评论图片模型
+ */
+class ActivityCommentImage extends BaseModel
+{
+    protected $name = 'branch_activity_comment_image';
+    protected $pk = 'id';
+
+    /**
+     * 关联文件表
+     */
+    public function file()
+    {
+        return $this->belongsTo('app\\common\\model\\file\\UploadFile', 'image_id', 'file_id');
+    }
+}
diff --git a/admin/app/shop/controller/branch/ActivityComment.php b/admin/app/shop/controller/branch/ActivityComment.php
new file mode 100644
index 0000000..0e2878f
--- /dev/null
+++ b/admin/app/shop/controller/branch/ActivityComment.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace app\shop\controller\branch;
+
+use app\shop\controller\Controller;
+use app\shop\model\branch\ActivityComment as ActivityCommentModel;
+
+/**
+ * 活动评论控制器
+ */
+class ActivityComment extends Controller
+{
+    /**
+     * 评论列表
+     */
+    public function index()
+    {
+        $model = new ActivityCommentModel;
+        $postData = $this->postData();
+
+        $where[] = ['is_delete', '=', 0];
+        
+        // 列表
+        $list = $model->getList($postData);
+        // 待审核数量
+        $num = $model->getStatusNum($where);
+        return $this->renderSuccess('', compact('list', 'num'));
+    }
+
+    /**
+     * 评论详情
+     */
+    public function detail($comment_id)
+    {
+        $data = ActivityCommentModel::detail($comment_id, ['user', 'activity', 'activity.branch', 'images'=>['file']]);
+        return $this->renderSuccess('', compact('data'));
+    }
+
+    /**
+     * 更新评论
+     */
+    public function edit($comment_id)
+    {
+        $model = ActivityCommentModel::detail($comment_id);
+        if ($model->editComment($this->postData())) {
+            return $this->renderSuccess('修改成功');
+        }
+        return $this->renderError('修改失败');
+    }
+
+    /**
+     * 删除评论
+     */
+    public function delete($comment_id)
+    {
+        $model = new ActivityCommentModel();
+        if (!$model->setDelete($comment_id)) {
+            return $this->renderError('删除失败');
+        }
+        return $this->renderSuccess('删除成功');
+    }
+}
diff --git a/admin/app/shop/model/branch/ActivityComment.php b/admin/app/shop/model/branch/ActivityComment.php
new file mode 100644
index 0000000..bc8b881
--- /dev/null
+++ b/admin/app/shop/model/branch/ActivityComment.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace app\shop\model\branch;
+
+use app\common\model\branch\ActivityComment as ActivityCommentModel;
+
+/**
+ * 活动评论模型
+ */
+class ActivityComment extends ActivityCommentModel
+{
+    /**
+     * 获取列表
+     */
+    public function getList($params)
+    {
+        $model = $this->with(['user', 'activity', 'activity.branch'])
+            ->where('is_delete', '=', 0);
+
+        // 按审核状态筛选
+        if (isset($params['status']) && $params['status'] != -1) {
+            $model = $model->where('status', '=', $params['status']);
+        }
+
+        // 按评分筛选
+        if (isset($params['score']) && $params['score'] > 0) {
+            if ($params['score'] == 10) {
+                // 好评 4-5分
+                $model = $model->where('score', '>=', 4);
+            } elseif ($params['score'] == 20) {
+                // 中评 2-3分
+                $model = $model->whereBetween('score', [2, 3]);
+            } elseif ($params['score'] == 30) {
+                // 差评 1分
+                $model = $model->where('score', '=', 1);
+            }
+        }
+
+        // 按活动名称搜索
+        if (isset($params['name']) && !empty($params['name'])) {
+            $model = $model->whereHas('activity', function ($query) use ($params) {
+                $query->where('name', 'like', '%' . $params['name'] . '%');
+            });
+        }
+
+        return $model->order(['sort' => 'asc', 'create_time' => 'desc'])
+            ->paginate($params);
+    }
+
+    /**
+     * 获取待审核数量
+     */
+    public function getStatusNum()
+    {
+        return $this->where('status', '=', 0)
+            ->where('is_delete', '=', 0)
+            ->count();
+    }
+
+    /**
+     * 更新评论
+     */
+    public function editComment($data)
+    {
+        return $this->save([
+            'status' => $data['status'] ?? $this['status'],
+            'sort' => $data['sort'] ?? $this['sort'],
+        ]);
+    }
+
+    /**
+     * 软删除
+     */
+    public function setDelete($comment_id)
+    {
+        return $this->where('comment_id', '=', $comment_id)->save(['is_delete' => 1]);
+    }
+}
diff --git a/admin/app/shop/service/region/MenusService.php b/admin/app/shop/service/region/MenusService.php
new file mode 100644
index 0000000..eb656e8
--- /dev/null
+++ b/admin/app/shop/service/region/MenusService.php
@@ -0,0 +1,82 @@
+<?php
+
+namespace app\shop\service\region;
+
+use app\common\model\plus\operations\Access;
+use app\common\service\region\AuthService;
+
+/**
+ * 区域代理菜单服务
+ */
+class MenusService
+{
+    /**
+     * 获取菜单列表
+     * @param int $userId 用户ID
+     * @return array
+     */
+    public function getMenus($userId)
+    {
+        // 获取用户有权限的菜单
+        return AuthService::getUserMenus($userId);
+    }
+
+    /**
+     * 获取所有菜单列表(用于权限分配)
+     * @return array
+     */
+    public function getAllMenus()
+    {
+        $accessModel = new Access();
+        $accessList = $accessModel->order(['sort' => 'asc', 'create_time' => 'asc'])->select();
+        
+        return $this->buildMenuTree($accessList ? $accessList->toArray() : []);
+    }
+
+    /**
+     * 构建菜单树结构
+     * @param array $data 权限数据
+     * @param int $parentId 父级ID
+     * @return array
+     */
+    private function buildMenuTree($data, $parentId = 0)
+    {
+        $tree = [];
+        foreach ($data as $item) {
+            if ($item['parent_id'] == $parentId) {
+                $item['children'] = $this->buildMenuTree($data, $item['access_id']);
+                $tree[] = $item;
+            }
+        }
+        return $tree;
+    }
+
+    /**
+     * 获取面包屑导航
+     * @param string $path 当前路径
+     * @return array
+     */
+    public function getBreadcrumb($path)
+    {
+        $accessModel = new Access();
+        $current = $accessModel->where('path', '=', $path)->find();
+        
+        if (!$current) {
+            return [];
+        }
+
+        $breadcrumb = [$current];
+        $parentId = $current['parent_id'];
+        
+        while ($parentId > 0) {
+            $parent = $accessModel->where('access_id', '=', $parentId)->find();
+            if (!$parent) {
+                break;
+            }
+            array_unshift($breadcrumb, $parent);
+            $parentId = $parent['parent_id'];
+        }
+
+        return $breadcrumb;
+    }
+}
diff --git a/admin/config/cache.php b/admin/config/cache.php
index 98c8c4b..af86a16 100644
--- a/admin/config/cache.php
+++ b/admin/config/cache.php
@@ -27,5 +27,29 @@
             'serialize'  => [],
         ],
         // 更多的缓存连接
+        'redis' => [
+            // 驱动方式
+            'type'       => 'redis',
+            // 服务器地址
+            'host'       =>'127.0.0.1',
+            // 端口
+            'port'       =>  6379,
+            // 密码
+            'password'   =>  '',
+            // 缓存库
+            'select'     =>  0,
+            // 超时时间(秒)
+            'timeout'    => 0,
+            // 缓存有效期 0表示永久缓存
+            'expire'     => 0,
+            // 是否长连接
+            'persistent' => false,
+            // 缓存前缀
+            'prefix'     => '',
+            // 缓存标签前缀
+            'tag_prefix' => 'tag:',
+            // 序列化机制 例如 ['serialize', 'unserialize']
+            'serialize'  => [],
+        ],
     ],
 ];
diff --git a/agent_vue/src/api/plugs.js b/agent_vue/src/api/plugs.js
index d427f41..9fa8fc7 100644
--- a/agent_vue/src/api/plugs.js
+++ b/agent_vue/src/api/plugs.js
@@ -21,7 +21,7 @@
   deleteplugs(data, errorback) {
     return request._post('/agent/plus.plus/delete', data, errorback);
   },
-  /*修改插件状�?/
+  /*修改插件状态*/
   updatePlugsStatus(data, errorback) {
     return request._post('/agent/plus.plus/updateStatus', data, errorback);
   },
@@ -32,4 +32,4 @@
 
 }
 
-export default PlugsApi;
+export default PlugsApi;
\ No newline at end of file
diff --git a/agent_vue/src/api/user.js b/agent_vue/src/api/user.js
index 76b7624..54e439d 100644
--- a/agent_vue/src/api/user.js
+++ b/agent_vue/src/api/user.js
@@ -9,7 +9,7 @@
     editPassword(data, errorback) {
         return request._post('/agent/agent.user/renew', data, errorback);
     },
-    /*退出登�?/
+    /*退出登录*/
     loginOut(data, errorback) {
         return request._post('/agent/passport/logout', data, errorback);
     },
@@ -23,4 +23,4 @@
     },
 }
 
-export default UserApi;
+export default UserApi;
\ No newline at end of file
diff --git a/agent_vue/src/views/help/Fonticon.vue b/agent_vue/src/views/help/Fonticon.vue
index 2210e9b..7c630bf 100644
--- a/agent_vue/src/views/help/Fonticon.vue
+++ b/agent_vue/src/views/help/Fonticon.vue
@@ -1,8 +1,8 @@
 <template>
   <!--
     	作者:4948286@qq.com
-    	时间�?019-12-24
-    	描述:字体图�?
+    	时间:2019-12-24
+    	描述:字体图标
     -->
     <div>
       dddd
@@ -13,4 +13,4 @@
 </script>
 
 <style>
-</style>
+</style>
\ No newline at end of file
diff --git a/branch_vue/src/api/branch.js b/branch_vue/src/api/branch.js
index ad7c550..32c43e5 100644
--- a/branch_vue/src/api/branch.js
+++ b/branch_vue/src/api/branch.js
@@ -103,6 +103,10 @@
   activityStatus(data, errorback) {
     return request._post('/branch/activity.activity/status', data, errorback);
   },
+  /*检查企业差评*/
+  checkNegativeComment(data, errorback) {
+    return request._post('/branch/activity.activity/checkNegativeComment', data, errorback);
+  },
   /*报名列表*/
   activityUserList(data, errorback) {
     return request._post('/branch/activityUser.activityUser/index', data, errorback);
@@ -116,6 +120,23 @@
     return request._post('/branch/activity.file/delete', data, errorback);
   },
 
+  /*活动评论列表*/
+  activityCommentList(data, errorback) {
+    return request._post('/branch/activity.comment/index', data, errorback);
+  },
+  /*活动评论详情*/
+  activityCommentDetail(data, errorback) {
+    return request._post('/branch/activity.comment/detail', data, errorback);
+  },
+  /*编辑活动评论*/
+  editActivityComment(data, errorback) {
+    return request._post('/branch/activity.comment/edit', data, errorback);
+  },
+  /*删除活动评论*/
+  deleteActivityComment(data, errorback) {
+    return request._post('/branch/activity.comment/delete', data, errorback);
+  },
+
   /*获取职务*/
   positionList(data, errorback) {
     return request._post('/branch/position.position/index', data, errorback);
diff --git a/branch_vue/src/views/activity/activity/add.vue b/branch_vue/src/views/activity/activity/add.vue
index 8bd56fa..7472429 100644
--- a/branch_vue/src/views/activity/activity/add.vue
+++ b/branch_vue/src/views/activity/activity/add.vue
@@ -337,30 +337,67 @@
       // }
       self.$refs.form.validate(valid => {
         if (valid) {
-          self.loading = true;
-          form.content = this.$refs.ue.getUEContent();
-          // 如果走访企业,则被走访企业就是场地提供者
-          if (form.is_visit) {
-            form.space_supplier_id = '';
-          } else {
-            form.visit_supplier_id = '';
-          }
-          BranchApi.addActivity({formData: JSON.stringify(form)}, true)
-            .then(data => {
-              self.loading = false;
-              self.$message({
-                message: data.msg,
-                type: 'success'
-              });
-              self.$router.push('/activity/activity/index');
-            })
-            .catch(error => {
-              self.loading = false;
+          // 如果是走访活动,先检查差评
+          if (form.is_visit && (form.visit_supplier_id || form.visit_supplier_name)) {
+            BranchApi.checkNegativeComment({
+              visit_supplier_id: form.visit_supplier_id || 0,
+              visit_supplier_name: form.visit_supplier_name || '',
+              activity_id: 0
+            }).then(res => {
+              if (res.data.has_warning) {
+                // 显示确认对话框
+                self.$confirm(res.data.message, '提示', {
+                  confirmButtonText: '继续走访',
+                  cancelButtonText: '取消',
+                  type: 'warning'
+                }).then(() => {
+                  // 用户确认继续,直接提交
+                  self.submitForm();
+                }).catch(() => {
+                  // 用户取消
+                });
+              } else {
+                // 没有差评警告,直接提交
+                self.submitForm();
+              }
+            }).catch(error => {
+              // 检查失败,直接提交
+              self.submitForm();
             });
+          } else {
+            // 不是走访活动,直接提交
+            self.submitForm();
+          }
         }
       });
     },
 
+    /*提交表单*/
+    submitForm() {
+      let self = this;
+      self.loading = true;
+      let form = self.form;
+      form.content = this.$refs.ue.getUEContent();
+      // 如果走访企业,则被走访企业就是场地提供者
+      if (form.is_visit) {
+        form.space_supplier_id = '';
+      } else {
+        form.visit_supplier_id = '';
+      }
+      BranchApi.addActivity({formData: JSON.stringify(form)}, true)
+        .then(data => {
+          self.loading = false;
+          self.$message({
+            message: data.msg,
+            type: 'success'
+          });
+          self.$router.push('/activity/activity/index');
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
     /*选择的地址*/
     selectFromMap(e){
       this.form.coordinate = e.location.lat + ',' + e.location.lng;
diff --git a/branch_vue/src/views/activity/activity/drawer/part/edit.vue b/branch_vue/src/views/activity/activity/drawer/part/edit.vue
index e6ca209..19a7307 100644
--- a/branch_vue/src/views/activity/activity/drawer/part/edit.vue
+++ b/branch_vue/src/views/activity/activity/drawer/part/edit.vue
@@ -318,33 +318,70 @@
       // form.verify_user_ids = verify_user_ids.join(',');
       self.$refs.form.validate(valid => {
         if (valid) {
-          self.loading = true;
-          form.content = this.$refs.ue.getUEContent();
-          // 如果走访企业,则被走访企业就是场地提供者
-          if (form.is_visit) {
-            form.space_supplier_id = '';
-          } else {
-            form.visit_supplier_id = '';
-          }
-          BranchApi.editActivity({
-            activity_id: form.activity_id,
-            formData: JSON.stringify(form)
-          }, true)
-            .then(data => {
-              self.loading = false;
-              self.$message({
-                message: data.msg,
-                type: 'success'
-              });
-              this.$emit('success');
-            })
-            .catch(error => {
-              self.loading = false;
+          // 如果是走访活动,先检查差评
+          if (form.is_visit && (form.visit_supplier_id || form.visit_supplier_name)) {
+            BranchApi.checkNegativeComment({
+              visit_supplier_id: form.visit_supplier_id || 0,
+              visit_supplier_name: form.visit_supplier_name || '',
+              activity_id: form.activity_id || 0
+            }).then(res => {
+              if (res.data.has_warning) {
+                // 显示确认对话框
+                self.$confirm(res.data.message, '提示', {
+                  confirmButtonText: '继续走访',
+                  cancelButtonText: '取消',
+                  type: 'warning'
+                }).then(() => {
+                  // 用户确认继续,直接提交
+                  self.submitForm();
+                }).catch(() => {
+                  // 用户取消
+                });
+              } else {
+                // 没有差评警告,直接提交
+                self.submitForm();
+              }
+            }).catch(error => {
+              // 检查失败,直接提交
+              self.submitForm();
             });
+          } else {
+            // 不是走访活动,直接提交
+            self.submitForm();
+          }
         }
       });
     },
 
+    /*提交表单*/
+    submitForm() {
+      let self = this;
+      self.loading = true;
+      let form = self.form;
+      form.content = this.$refs.ue.getUEContent();
+      // 如果走访企业,则被走访企业就是场地提供者
+      if (form.is_visit) {
+        form.space_supplier_id = '';
+      } else {
+        form.visit_supplier_id = '';
+      }
+      BranchApi.editActivity({
+        activity_id: form.activity_id,
+        formData: JSON.stringify(form)
+      }, true)
+        .then(data => {
+          self.loading = false;
+          self.$message({
+            message: data.msg,
+            type: 'success'
+          });
+          this.$emit('success');
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
     /*选择的地址*/
     selectFromMap(e){
       this.form.coordinate = e.location.lat + ',' + e.location.lng;
diff --git a/branch_vue/src/views/activity/comment/detail.vue b/branch_vue/src/views/activity/comment/detail.vue
new file mode 100644
index 0000000..e57f017
--- /dev/null
+++ b/branch_vue/src/views/activity/comment/detail.vue
@@ -0,0 +1,147 @@
+<template>
+  <div class="evaluation-detail pb50" v-loading="!loading">
+    <!--form表单-->
+    <el-form size="small" ref="form" :model="form" label-width="120px">
+      <div class="common-form">活动评价详情</div>
+      <el-form-item label="用户">
+        <p v-if="form.user">{{ form.user.nickName }}</p>
+      </el-form-item>
+      <el-form-item label="活动名称">
+        <p v-if="form.activity">{{ form.activity.name }}</p>
+      </el-form-item>
+      <el-form-item label="走访企业" v-if="form.supplier_name">
+        <p>{{ form.supplier_name }}</p>
+      </el-form-item>
+      <el-form-item label="评论时间">
+        <p>{{ form.create_time_text }}</p>
+      </el-form-item>
+      <el-form-item label="评价图片">
+        <div class="d-s-c evaluation-imgs pb16">
+          <div
+            class="item"
+            v-if="form.images && form.images.length > 0"
+            v-for="(item, index) in form.images"
+            :key="index"
+          >
+            <img v-if="item.file" v-img-url="item.file.file_path" />
+          </div>
+          <span v-if="!form.images || form.images.length == 0">暂无图片</span>
+        </div>
+      </el-form-item>
+      <el-form-item label="评分">
+        <el-rate v-model="form.score" disabled></el-rate>
+        <span class="ml10">{{ form.score }}分</span>
+      </el-form-item>
+      <el-form-item label="评价内容">
+        <div>{{ form.content || '暂无评价内容' }}</div>
+      </el-form-item>
+      <el-form-item label="排序">
+        <el-input type="number" v-model="form.sort" placeholder="请输入数字" style="width: 200px;"></el-input>
+      </el-form-item>
+      <el-form-item label="审核">
+        <el-radio-group v-model="form.status">
+          <el-radio :label="1">通过</el-radio>
+          <el-radio :label="2">不通过</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <!--提交-->
+      <div class="common-button-wrapper">
+        <el-button size="small" type="info" @click="cancelFunc">取消</el-button>
+        <el-button size="small" type="primary" @click="onSubmit">提交</el-button>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import BranchApi from '@/api/branch.js';
+export default {
+  components: {},
+  data() {
+    return {
+      /*form表单数据*/
+      form: {
+        user: {},
+        activity: {}
+      },
+      loading: false,
+      comment_id: 0
+    };
+  },
+  created() {
+    this.comment_id = this.$route.query.comment_id;
+    /*获取列表*/
+    this.getComment();
+  },
+  methods: {
+    /*获取评论*/
+    getComment() {
+      let self = this;
+      BranchApi.activityCommentDetail(
+        {
+          comment_id: self.comment_id
+        },
+        true
+      )
+        .then(data => {
+          self.loading = true;
+          self.form = data.data.data;
+        })
+        .catch(error => {});
+    },
+
+    /*提交*/
+    onSubmit() {
+      let self = this;
+      BranchApi.editActivityComment(
+        {
+          comment_id: self.comment_id,
+          status: self.form.status,
+          sort: self.form.sort
+        },
+        true
+      )
+        .then(data => {
+          if (data.code == 1) {
+            self.$message({
+              message: '恭喜你,操作成功',
+              type: 'success'
+            });
+            self.$router.push('/activity/comment/index');
+          } else {
+            self.$message.error(data.msg || '操作失败');
+          }
+        })
+        .catch(error => {});
+    },
+
+    /*取消*/
+    cancelFunc() {
+      this.$router.back(-1);
+    }
+  }
+};
+</script>
+
+<style>
+.evaluation-detail {
+  margin-bottom: 50px;
+}
+.evaluation-detail .el-form-item {
+  border-bottom: 1px solid #eeeeee;
+}
+.evaluation-detail .el-form-item__label {
+  color: #bbbbbb;
+}
+.evaluation-detail .evaluation-imgs .item {
+  width: 100px;
+  height: 100px;
+  margin-right: 4px;
+  border: 1px solid #d1d5dd;
+}
+.evaluation-detail .evaluation-imgs .item img {
+  width: 98px;
+  height: 98px;
+  object-fit: contain;
+}
+</style>
diff --git a/branch_vue/src/views/activity/comment/index.vue b/branch_vue/src/views/activity/comment/index.vue
new file mode 100644
index 0000000..be4a2d3
--- /dev/null
+++ b/branch_vue/src/views/activity/comment/index.vue
@@ -0,0 +1,233 @@
+<template>
+  <div class="product">
+    <!--搜索表单-->
+    <div class="common-seach-wrap">
+      <el-form size="small" :inline="true" :model="searchForm" class="demo-form-inline">
+        <el-form-item label="评分">
+          <el-select size="small" v-model="searchForm.score" placeholder="全部">
+            <el-option label="全部" :value="0"></el-option>
+            <el-option v-for="(item, index) in commentList" :key="index" :label="item.name" :value="item.val"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="活动名称">
+          <el-input size="small" v-model="searchForm.name" placeholder="请输入活动名称"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button size="small" type="primary" icon="el-icon-search" @click="onSubmit">查询</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <template>
+      <el-tabs v-model="activeName" @tab-click="handleClick">
+        <el-tab-pane label="全部评价" name="-1"></el-tab-pane>
+        <el-tab-pane :label="'待审核(' + num + ')'" name="0"></el-tab-pane>
+        <el-tab-pane label="审核通过" name="1"></el-tab-pane>
+        <el-tab-pane label="审核未通过" name="2"></el-tab-pane>
+      </el-tabs>
+    </template>
+
+    <!--内容-->
+    <div class="product-content">
+      <div class="table-wrap">
+        <el-table size="small" :data="tableData" border style="width: 100%" v-loading="loading">
+          <el-table-column label="活动" width="300px">
+            <template slot-scope="scope">
+              <div class="product-info">
+                <div class="info">
+                  <div class="name">{{ scope.row.activity ? scope.row.activity.name : '-' }}</div>
+                </div>
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column prop="user.nickName" label="用户">
+            <template slot-scope="scope">
+              <span v-if="scope.row.user">{{ scope.row.user.nickName }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="score" label="评分">
+            <template slot-scope="scope">
+              <el-rate v-model="scope.row.score" disabled></el-rate>
+            </template>
+          </el-table-column>
+          <el-table-column prop="content" label="评价内容" width="200">
+            <template slot-scope="scope">
+              <p class="ww100 text-ellipsis-2">{{ scope.row.content }}</p>
+            </template>
+          </el-table-column>
+          <el-table-column prop="is_picture" label="图片">
+            <template slot-scope="scope">
+              <span v-if="scope.row.is_picture == 0">没有</span>
+              <span v-else>有</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="status" label="评价状态">
+            <template slot-scope="scope">
+              <span v-if="scope.row.status == 0" class="red fb">待审核</span>
+              <span v-if="scope.row.status == 1" class="green">审核通过</span>
+              <span v-if="scope.row.status == 2" class="gray9">审核未通过</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="sort" label="排序"></el-table-column>
+          <el-table-column prop="create_time" label="评论时间"></el-table-column>
+          <el-table-column fixed="right" label="操作" width="90">
+            <template slot-scope="scope">
+              <el-button @click="detailClick(scope.row)" type="text" size="small">详情</el-button>
+              <el-button @click="delClick(scope.row)" type="text" size="small">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <!--分页-->
+      <div class="pagination">
+        <el-pagination
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+          background
+          :current-page="curPage"
+          :page-size="pageSize"
+          layout="total, prev, pager, next, jumper"
+          :total="totalDataNumber"
+        ></el-pagination>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import BranchApi from '@/api/branch.js';
+export default {
+  components: {},
+  data() {
+    return {
+      loading: true,
+      activeName: '-1',
+      num: 0,
+      /*列表数据*/
+      tableData: [],
+      /*一页多少条*/
+      pageSize: 20,
+      /*总条数*/
+      totalDataNumber: 0,
+      /*当前是第几页*/
+      curPage: 1,
+      /*搜索参数*/
+      searchForm: {
+        score: 0,
+        name: ''
+      },
+      /*评价等级*/
+      commentList: [
+        { name: '好评', val: 10 },
+        { name: '中评', val: 20 },
+        { name: '差评', val: 30 }
+      ],
+      status: -1
+    };
+  },
+  created() {
+    /*获取列表*/
+    this.getData();
+  },
+  methods: {
+    /*选择第几页*/
+    handleCurrentChange(val) {
+      let self = this;
+      self.curPage = val;
+      self.loading = true;
+      let Params = self.searchForm;
+      self.getData(Params);
+    },
+
+    /*每页多少条*/
+    handleSizeChange(val) {
+      this.curPage = 1;
+      this.pageSize = val;
+      this.getData();
+    },
+
+    /*获取列表*/
+    getData(param = '') {
+      let self = this;
+      let Params = {};
+      Params.status = self.status;
+      Params.page = self.curPage;
+      Params.list_rows = self.pageSize;
+      if (param != '') {
+        Params.score = param.score;
+        Params.name = param.name;
+      }
+      BranchApi.activityCommentList(Params, true)
+        .then(res => {
+          self.loading = false;
+          self.tableData = res.data.list.data;
+          self.totalDataNumber = res.data.list.total;
+          self.num = res.data.num;
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    /*打开详情*/
+    detailClick(row) {
+      this.$router.push({
+        path: '/activity/comment/detail',
+        query: {
+          comment_id: row.comment_id
+        }
+      });
+    },
+
+    /*删除*/
+    delClick: function(row) {
+      let self = this;
+      self
+        .$confirm('删除后不可恢复,确认删除该记录吗?', '提示', {
+          type: 'warning'
+        })
+        .then(() => {
+          BranchApi.deleteActivityComment({
+            comment_id: row.comment_id
+          }).then(data => {
+            self.$message({
+              message: '删除成功',
+              type: 'success'
+            });
+            self.getData();
+          });
+        });
+    },
+
+    /*搜索查询*/
+    onSubmit() {
+      let self = this;
+      self.loading = true;
+      let Params = self.searchForm;
+      Params.page = self.curPage;
+      Params.list_rows = self.pageSize;
+      Params.status = self.status;
+      BranchApi.activityCommentList(Params, true)
+        .then(data => {
+          self.loading = false;
+          self.tableData = data.data.list.data;
+          self.totalDataNumber = data.data.list.total;
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    /*切换选项卡*/
+    handleClick(tab, event) {
+      let self = this;
+      self.curPage = 1;
+      self.loading = true;
+      self.status = tab.name;
+      self.getData();
+    }
+  }
+};
+</script>
+
+<style></style>
diff --git a/branch_vue/static/UE/dialogs/spechars/spechars.js b/branch_vue/static/UE/dialogs/spechars/spechars.js
index f4c155e..fd5d7e3 100644
--- a/branch_vue/static/UE/dialogs/spechars/spechars.js
+++ b/branch_vue/static/UE/dialogs/spechars/spechars.js
@@ -6,7 +6,7 @@
  * To change this template use File | Settings | File Templates.
  */
 var charsContent = [
-    { name:"tsfh", title:lang.tsfh, content:toArray("、,。,·,ˉ,ˇ,¨,〃,々,—,~,‖,…,‘,’,“,”,〔,〕,〈,〉,《,》,「,」,『,』,〖,〗,【,】,±,×,÷,∶,∧,∨,∑,∏,∪,∩,∈,∷,√,⊥,∥,∠,⌒,⊙,∫,∮,≡,≌,≈,∽,∝,≠,≮,≯,≤,≥,∞,∵,∴,♂,♀,°,′,″,℃,$,¤,¢,£,‰,§,№,☆,★,○,●,◎,◇,◆,□,■,△,▲,※,→,←,↑,↓,〓,〡,〢,〣,〤,〥,〦,〧,〨,〩,㊣,㎎,㎏,㎜,㎝,㎞,㎡,㏄,㏎,㏑,㏒,㏕,︰,¬,¦,℡,ˊ,ˋ,˙,–,―,‥,‵,℅,℉,↖,↗,↘,↙,∕,∟,∣,≒,≦,≧,⊿,═,║,╒,╓,╔,╕,╖,╗,╘,╙,╚,╛,╜,╝,╞,╟,╠,╡,╢,╣,╤,╥,╦,╧,╨,╩,╪,╫,╬,╭,╮,╯,╰,╱,╲,╳,▁,▂,▃,▄,▅,▆,▇,�,█,▉,▊,▋,▌,▍,▎,▏,▓,▔,▕,▼,▽,◢,◣,◤,◥,☉,⊕,〒,〝,〞")},
+    { name:"tsfh", title:lang.tsfh, content:toArray("、,。,·,ˉ,ˇ,¨,〃,々,—,~,‖,…,‘,’,“,”,〔,〕,〈,〉,《,》,「,」,『,』,〖,〗,【,】,±,×,÷,∶,∧,∨,∑,∏,∪,∩,∈,∷,√,⊥,∥,∠,⌒,⊙,∫,∮,≡,≌,≈,∽,∝,≠,≮,≯,≤,≥,∞,∵,∴,♂,♀,°,′,″,℃,$,¤,¢,£,‰,§,№,☆,★,○,●,◎,◇,◆,□,■,△,▲,※,→,←,↑,↓,〓,〡,〢,〣,〤,〥,〦,〧,〨,〩,㊣,㎎,㎏,㎜,㎝,㎞,㎡,㏄,㏎,㏑,㏒,㏕,︰,¬,¦,℡,ˊ,ˋ,˙,–,―,‥,‵,℅,℉,↖,↗,↘,↙,∕,∟,∣,≒,≦,≧,⊿,═,║,╒,╓,╔,╕,╖,╗,╘,╙,╚,╛,╜,╝,╞,╟,╠,╡,╢,╣,╤,╥,╦,╧,╨,╩,╪,╫,╬,╭,╮,╯,╰,╱,╲,╳,▁,▂,▃,▄,▅,▆,▇,█,█,▉,▊,▋,▌,▍,▎,▏,▓,▔,▕,▼,▽,◢,◣,◤,◥,☉,⊕,〒,〝,〞")},
     { name:"lmsz", title:lang.lmsz, content:toArray("ⅰ,ⅱ,ⅲ,ⅳ,ⅴ,ⅵ,ⅶ,ⅷ,ⅸ,ⅹ,Ⅰ,Ⅱ,Ⅲ,Ⅳ,Ⅴ,Ⅵ,Ⅶ,Ⅷ,Ⅸ,Ⅹ,Ⅺ,Ⅻ")},
     { name:"szfh", title:lang.szfh, content:toArray("⒈,⒉,⒊,⒋,⒌,⒍,⒎,⒏,⒐,⒑,⒒,⒓,⒔,⒕,⒖,⒗,⒘,⒙,⒚,⒛,⑴,⑵,⑶,⑷,⑸,⑹,⑺,⑻,⑼,⑽,⑾,⑿,⒀,⒁,⒂,⒃,⒄,⒅,⒆,⒇,①,②,③,④,⑤,⑥,⑦,⑧,⑨,⑩,㈠,㈡,㈢,㈣,㈤,㈥,㈦,㈧,㈨,㈩")},
     { name:"rwfh", title:lang.rwfh, content:toArray("ぁ,あ,ぃ,い,ぅ,う,ぇ,え,ぉ,お,か,が,き,ぎ,く,ぐ,け,げ,こ,ご,さ,ざ,し,じ,す,ず,せ,ぜ,そ,ぞ,た,だ,ち,ぢ,っ,つ,づ,て,で,と,ど,な,に,ぬ,ね,の,は,ば,ぱ,ひ,び,ぴ,ふ,ぶ,ぷ,へ,べ,ぺ,ほ,ぼ,ぽ,ま,み,む,め,も,ゃ,や,ゅ,ゆ,ょ,よ,ら,り,る,れ,ろ,ゎ,わ,ゐ,ゑ,を,ん,ァ,ア,ィ,イ,ゥ,ウ,ェ,エ,ォ,オ,カ,ガ,キ,ギ,ク,グ,ケ,ゲ,コ,ゴ,サ,ザ,シ,ジ,ス,ズ,セ,ゼ,ソ,ゾ,タ,ダ,チ,ヂ,ッ,ツ,ヅ,テ,デ,ト,ド,ナ,ニ,ヌ,ネ,ノ,ハ,バ,パ,ヒ,ビ,ピ,フ,ブ,プ,ヘ,ベ,ペ,ホ,ボ,ポ,マ,ミ,ム,メ,モ,ャ,ヤ,ュ,ユ,ョ,ヨ,ラ,リ,ル,レ,ロ,ヮ,ワ,ヰ,ヱ,ヲ,ン,ヴ,ヵ,ヶ")},
@@ -54,4 +54,4 @@
 })(charsContent);
 function toArray(str) {
     return str.split(",");
-}
+}
\ No newline at end of file
diff --git a/mobile/pages.json b/mobile/pages.json
index 6c4d749..de0b085 100644
--- a/mobile/pages.json
+++ b/mobile/pages.json
@@ -573,6 +573,16 @@
 							//#endif
 						}
 					}
+				}, {
+					"path": "activity/evaluate/evaluate",
+					"style": {
+						"navigationBarTitleText": "活动评价",
+						"app-plus": {
+							//#ifdef H5
+							"titleNView": false
+							//#endif
+						}
+					}
 				},
 				{
 					"path": "activity/product/index",
@@ -1606,7 +1616,7 @@
 							//#endif
 						}
 					}
-				},{
+				}, {
 					"path": "operations/index",
 					"style": {
 						"navigationStyle": "custom",
diff --git a/mobile/pages/branch/activity/evaluate/evaluate.vue b/mobile/pages/branch/activity/evaluate/evaluate.vue
new file mode 100644
index 0000000..528d15d
--- /dev/null
+++ b/mobile/pages/branch/activity/evaluate/evaluate.vue
@@ -0,0 +1,277 @@
+<template>
+	<view class="evaluate pb100" v-if="!loadding">
+		<form @submit="formSubmit">
+			<view class="evaluate-item p30">
+				<view class="product d-s-c">
+					<view class="info ml20">
+						<view class="name f28 fb">活动评价</view>
+						<view class="pt10 f24 gray6">{{activityInfo.activity_name}}</view>
+						<view class="pt10 f24 gray9" v-if="activityInfo.supplier_name">被走访企业:{{activityInfo.supplier_name}}</view>
+					</view>
+				</view>
+				<view class="grade evalu p-30-0 mt30">
+					<view class="evalu-value">
+						<text class="f28 gray6">评分:</text>
+						<view class="eval">
+							<i v-for="(itemEv,indexEv) in starList" :key="indexEv" :class="itemEv?'icon iconfont icon-start':'icon iconfont icon-start1'"
+							 @click="chooseScore(indexEv)"></i>
+						</view>
+					</view>
+				</view>
+				<view class="grade d-a-c p-30-0 mt30">
+					<view :class="(form.score == 5||form.score == 4) ? 'flex-1 d-c-c active' : 'flex-1 d-c-c'" @click="gradeFunc(5)">
+						<view class="item d-c-c">
+							<text class="icon iconfont icon-pingjiahaoping"></text>
+							<text class="ml10">好评</text>
+						</view>
+					</view>
+					<view :class="(form.score == 3||form.score == 2) ? 'flex-1 d-c-c active' : 'flex-1 d-c-c'" @click="gradeFunc(3)">
+						<view class="item d-c-c">
+							<text class="icon iconfont icon-pingjiazhongping"></text>
+							<text class="ml10">中评</text>
+						</view>
+					</view>
+					<view :class="form.score == 1 ? 'flex-1 d-c-c active' : 'flex-1 d-c-c'" @click="gradeFunc(1)">
+						<view class="item d-c-c">
+							<text class="icon iconfont icon-pingjiachaping"></text>
+							<text class="ml10">差评</text>
+						</view>
+					</view>
+				</view>
+				<view class="textarea-box d-s-c f28 mt30">
+					<textarea class="p10 box-s-b border flex-1" v-model="form.content" placeholder="请输入评价内容" />
+				</view>
+				<view class="upload-list d-s-c">
+					<view class="item" v-for="(imgs, img_num) in form.image_list" :key="img_num" @click="deleteImg(img_num)">
+						<image :src="imgs.file_path" mode="aspectFill"></image>
+					</view>
+					<view class="item upload-btn d-c-c d-c" @click="openUpload" v-if="form.image_list.length < 9">
+						<text class="icon iconfont icon-xiangji"></text>
+						<text class="gray9">上传图片</text>
+					</view>
+				</view>
+			</view>
+			<view class="foot-btns"><button form-type="submit" class="btn-red">确认提交</button></view>
+		</form>
+
+		<!--上传图片-->
+		<Upload v-if="isUpload" @getImgs="getImgsFunc"></Upload>
+	</view>
+</template>
+
+<script>
+import Upload from '@/components/upload/upload.vue';
+export default {
+	components: {
+		Upload
+	},
+	data() {
+		return {
+			/*是否加载完成*/
+			loadding: true,
+			order_id: '',
+			/*活动信息*/
+			activityInfo: {},
+			/*表单数据*/
+			form: {
+				score: 5,
+				content: '',
+				image_list: []
+			},
+			/*是否打开上传图片*/
+			isUpload: false,
+			/*星星评分列表*/
+			starList: [true, true, true, true, true]
+		};
+	},
+	onLoad(e) {
+		this.order_id = e.order_id;
+	},
+	mounted() {
+		uni.showLoading({
+			title: '加载中'
+		});
+		this.getData();
+	},
+	methods: {
+		getData() {
+			let self = this;
+			let order_id = self.order_id;
+			self._get(
+				'branch.activityComment/order',
+				{
+					order_id: order_id
+				},
+				function(res) {
+					self.activityInfo = res.data;
+					self.loadding = false;
+					uni.hideLoading();
+				}
+			);
+		},
+		/*选择评分*/
+		gradeFunc(score) {
+			this.form.score = score;
+			this.updateStarList(score);
+		},
+		/*点击星星评分*/
+		chooseScore(index) {
+			let score = index + 1;
+			this.form.score = score;
+			this.updateStarList(score);
+		},
+		/*更新星星显示*/
+		updateStarList(score) {
+			this.starList = [false, false, false, false, false];
+			for(let i = 0; i < score; i++) {
+				this.starList[i] = true;
+			}
+		},
+		/*提交*/
+		formSubmit: function(e) {
+			let self = this;
+			let order_id = self.order_id;
+
+			if(!self.form.score) {
+				self.showError('请选择评分');
+				return;
+			}
+
+			let formData = {
+				score: self.form.score,
+				content: self.form.content || '',
+				image_list: self.form.image_list
+			};
+
+			self._post(
+				'branch.activityComment/order',
+				{
+					order_id: order_id,
+					formData: JSON.stringify(formData)
+				},
+				function(res) {
+					self.showSuccess(res.msg, function() {
+						uni.hideLoading();
+					}, null, function() {
+						self.gotoPage('/pages/user/my_activity/index', 'redirect');
+					});
+				}
+			);
+		},
+
+		/*打开上传图片*/
+		openUpload() {
+			this.isUpload = true;
+		},
+
+		/*获取上传的图片*/
+		getImgsFunc(e) {
+			let self = this;
+			if(e && typeof(e) != 'undefined'){
+				self.form.image_list = self.form.image_list.concat(e);
+			}
+			self.isUpload = false;
+		},
+
+		/*点击图片删除*/
+		deleteImg(n){
+			this.loadding=true;
+			this.form.image_list.splice(n,1);
+			this.loadding=false;
+		}
+	}
+};
+</script>
+
+<style>
+.evaluate {
+	background: #f5f5f5;
+}
+.evaluate-item {
+	margin-bottom: 20rpx;
+	background: #ffffff;
+	border-radius: 20rpx;
+}
+.product .info {
+	flex: 1;
+}
+.evaluate .grade .item .iconfont {
+	width: 60rpx;
+	height: 60rpx;
+	line-height: 60rpx;
+	border-radius: 50%;
+	font-size: 40rpx;
+	color: #ffffff;
+	text-align: center;
+}
+.evaluate .grade .item {
+	height: 60rpx;
+	padding-right: 20rpx;
+	line-height: 60rpx;
+	border-radius: 30rpx;
+	transition: background-color 0.4s;
+}
+.grade .flex-1:nth-child(1) .iconfont {
+	background: #f42222;
+}
+.grade .flex-1:nth-child(2) .iconfont {
+	background: #f2b509;
+}
+.grade .flex-1:nth-child(3) .iconfont {
+	background: #999999;
+}
+.grade .flex-1.active:nth-child(1) .item {
+	background: #f42222;
+	color: #ffffff;
+}
+.grade .flex-1.active:nth-child(2) .item {
+	background: #f2b509;
+	color: #ffffff;
+}
+.grade .flex-1.active:nth-child(3) .item {
+	background: #999999;
+	color: #ffffff;
+}
+.icon-start{
+	color: #f5a623;
+}
+.evalu-value{
+	display: flex;
+	margin-bottom: 30rpx;
+	align-items: center;
+}
+.eval{
+	display: flex;
+	justify-content: space-around;
+	align-items: center;
+}
+.evalu{
+	display: flex;
+	align-items: baseline;
+	flex-direction: column;
+}
+.upload-list {
+	flex-wrap: wrap;
+}
+.upload-list .item {
+	width: 160rpx;
+	height: 160rpx;
+	margin-right: 20rpx;
+	margin-bottom: 20rpx;
+	border-radius: 10rpx;
+	position: relative;
+}
+.upload-list .item image {
+	width: 100%;
+	height: 100%;
+	border-radius: 10rpx;
+}
+.upload-list .item.upload-btn {
+	border: 2rpx dashed #dddddd;
+	background: #f9f9f9;
+}
+.upload-list .item.upload-btn .iconfont {
+	font-size: 50rpx;
+	color: #999999;
+}
+</style>
diff --git a/mobile/pages/branch/admin/activity/add.vue b/mobile/pages/branch/admin/activity/add.vue
index 2074a82..0268c30 100644
--- a/mobile/pages/branch/admin/activity/add.vue
+++ b/mobile/pages/branch/admin/activity/add.vue
@@ -410,6 +410,51 @@
 				// 	});
 				// 	return false;
 				// }
+
+				// 如果是走访活动,先检查差评
+				if (formData.is_visit && (formData.visit_supplier_id || formData.visit_supplier_name)) {
+					uni.showLoading({
+						title: '正在检查',
+						mask: true
+					});
+					self._post('branch.admin.activity/checkNegativeComment', {
+						visit_supplier_id: formData.visit_supplier_id || 0,
+						visit_supplier_name: formData.visit_supplier_name || '',
+						activity_id: 0
+					}, function(res) {
+						uni.hideLoading();
+						if (res.data.has_warning) {
+							// 显示确认对话框
+							uni.showModal({
+								title: '提示',
+								content: res.data.message,
+								confirmText: '继续走访',
+								cancelText: '取消',
+								success: function(modalRes) {
+									if (modalRes.confirm) {
+										// 用户确认继续,直接提交
+										self.doSubmit(formData);
+									}
+								}
+							});
+						} else {
+							// 没有差评警告,直接提交
+							self.doSubmit(formData);
+						}
+					}, function() {
+						// 检查失败,直接提交
+						uni.hideLoading();
+						self.doSubmit(formData);
+					});
+				} else {
+					// 不是走访活动,直接提交
+					self.doSubmit(formData);
+				}
+			},
+
+			// 实际提交表单
+			doSubmit(formData) {
+				let self = this;
 				uni.showLoading({
 					title: '正在提交',
 					mask: true
diff --git a/mobile/pages/branch/admin/activity/edit.vue b/mobile/pages/branch/admin/activity/edit.vue
index 4fde21f..d6e6af2 100644
--- a/mobile/pages/branch/admin/activity/edit.vue
+++ b/mobile/pages/branch/admin/activity/edit.vue
@@ -446,6 +446,51 @@
 				// 	});
 				// 	return false;
 				// }
+
+				// 如果是走访活动,先检查差评
+				if (formData.is_visit && (formData.visit_supplier_id || formData.visit_supplier_name)) {
+					uni.showLoading({
+						title: '正在检查',
+						mask: true
+					});
+					self._post('branch.admin.activity/checkNegativeComment', {
+						visit_supplier_id: formData.visit_supplier_id || 0,
+						visit_supplier_name: formData.visit_supplier_name || '',
+						activity_id: self.activity_id || 0
+					}, function(res) {
+						uni.hideLoading();
+						if (res.data.has_warning) {
+							// 显示确认对话框
+							uni.showModal({
+								title: '提示',
+								content: res.data.message,
+								confirmText: '继续走访',
+								cancelText: '取消',
+								success: function(modalRes) {
+									if (modalRes.confirm) {
+										// 用户确认继续,直接提交
+										self.doSubmit(formData);
+									}
+								}
+							});
+						} else {
+							// 没有差评警告,直接提交
+							self.doSubmit(formData);
+						}
+					}, function() {
+						// 检查失败,直接提交
+						uni.hideLoading();
+						self.doSubmit(formData);
+					});
+				} else {
+					// 不是走访活动,直接提交
+					self.doSubmit(formData);
+				}
+			},
+
+			// 实际提交表单
+			doSubmit(formData) {
+				let self = this;
 				uni.showLoading({
 					title: '正在提交',
 					mask: true
diff --git a/mobile/pages/user/my_activity/detail.vue b/mobile/pages/user/my_activity/detail.vue
index 633caf1..f31ae3f 100644
--- a/mobile/pages/user/my_activity/detail.vue
+++ b/mobile/pages/user/my_activity/detail.vue
@@ -21,6 +21,15 @@
 				<view>{{detail.real_name}}({{detail.mobile}})</view>
 			</view>
 		</view>
+		<view class="detail-section radius24" v-if="detail.is_verify && detail.activity.status_text.status == 2">
+			<view class="bg-white comment-box p20">
+				<view class="d-b-c">
+					<view class="f28 fb">活动评价</view>
+					<view class="f24 theme-price" @click="gotoEvaluate" v-if="!detail.is_comment">去评价</view>
+					<view class="f24 gray9" v-else>已评价</view>
+				</view>
+			</view>
+		</view>
 		<view class="detail-section radius24">
 			<view class="bg-white detail-info-box" @click="gotoDetail">
 				<view class="pr20">
@@ -136,6 +145,11 @@
 			gotoDetail() {
 				this.gotoPage('/pages/branch/activity/detail/detail?activity_id=' + this.detail.activity_id);
 			},
+
+			// 跳转到评价页面
+			gotoEvaluate() {
+				this.gotoPage('/pages/branch/activity/evaluate/evaluate?order_id=' + this.order_id);
+			},
 			
 			callPhone(phone){
 				uni.makePhoneCall({
diff --git a/mobile/pages/user/my_activity/index.vue b/mobile/pages/user/my_activity/index.vue
index 1bc5666..918b557 100644
--- a/mobile/pages/user/my_activity/index.vue
+++ b/mobile/pages/user/my_activity/index.vue
@@ -57,6 +57,11 @@
 							</view>
 							<view>{{item.real_name}}({{item.mobile}})</view>
 						</view>
+						<!-- 评价按钮 -->
+						<view class="item-operation d-e-c pt30" v-if="item.is_verify==1 && item.activity.status_text.status==2">
+							<view class="item-btn" v-if="!item.comment" @click.stop="gotoEvaluate(item.order_id)">去评价</view>
+							<view class="item-btn disabled" v-else>已评价</view>
+						</view>
 						<!-- <view class="item-operation d-e-c pt30">
 							<view class="item-btn" @click="gotoDetail(item.order_id)">查看核销码</view>
 						</view> -->
@@ -194,7 +199,13 @@
 
 			/*跳转详情*/
 			gotoDetail(e) {
-				let url = 'pages/user/my_activity/detail?id=' + e
+				let url = '/pages/user/my_activity/detail?id=' + e
+				this.gotoPage(url);
+			},
+
+			/*跳转评价*/
+			gotoEvaluate(e) {
+				let url = '/pages/branch/activity/evaluate/evaluate?order_id=' + e
 				this.gotoPage(url);
 			},
 
@@ -295,9 +306,25 @@
 					.friend-info {
 						background: #FCF8ED;
 					}
+
+					.item-operation {
+						.item-btn {
+							font-size: 26rpx;
+							color: #333333;
+							border: 1rpx solid #cccccc;
+							border-radius: 60rpx;
+							padding: 14rpx 30rpx;
+
+							&.disabled {
+								background: #f5f5f5;
+								color: #999999;
+							}
+						}
+					}
 				}
 			}
 		}
 	}
 
 </style>
+
diff --git a/operations_vue/static/UE/dialogs/spechars/spechars.js b/operations_vue/static/UE/dialogs/spechars/spechars.js
index f4c155e..fd5d7e3 100644
--- a/operations_vue/static/UE/dialogs/spechars/spechars.js
+++ b/operations_vue/static/UE/dialogs/spechars/spechars.js
@@ -6,7 +6,7 @@
  * To change this template use File | Settings | File Templates.
  */
 var charsContent = [
-    { name:"tsfh", title:lang.tsfh, content:toArray("、,。,·,ˉ,ˇ,¨,〃,々,—,~,‖,…,‘,’,“,”,〔,〕,〈,〉,《,》,「,」,『,』,〖,〗,【,】,±,×,÷,∶,∧,∨,∑,∏,∪,∩,∈,∷,√,⊥,∥,∠,⌒,⊙,∫,∮,≡,≌,≈,∽,∝,≠,≮,≯,≤,≥,∞,∵,∴,♂,♀,°,′,″,℃,$,¤,¢,£,‰,§,№,☆,★,○,●,◎,◇,◆,□,■,△,▲,※,→,←,↑,↓,〓,〡,〢,〣,〤,〥,〦,〧,〨,〩,㊣,㎎,㎏,㎜,㎝,㎞,㎡,㏄,㏎,㏑,㏒,㏕,︰,¬,¦,℡,ˊ,ˋ,˙,–,―,‥,‵,℅,℉,↖,↗,↘,↙,∕,∟,∣,≒,≦,≧,⊿,═,║,╒,╓,╔,╕,╖,╗,╘,╙,╚,╛,╜,╝,╞,╟,╠,╡,╢,╣,╤,╥,╦,╧,╨,╩,╪,╫,╬,╭,╮,╯,╰,╱,╲,╳,▁,▂,▃,▄,▅,▆,▇,�,█,▉,▊,▋,▌,▍,▎,▏,▓,▔,▕,▼,▽,◢,◣,◤,◥,☉,⊕,〒,〝,〞")},
+    { name:"tsfh", title:lang.tsfh, content:toArray("、,。,·,ˉ,ˇ,¨,〃,々,—,~,‖,…,‘,’,“,”,〔,〕,〈,〉,《,》,「,」,『,』,〖,〗,【,】,±,×,÷,∶,∧,∨,∑,∏,∪,∩,∈,∷,√,⊥,∥,∠,⌒,⊙,∫,∮,≡,≌,≈,∽,∝,≠,≮,≯,≤,≥,∞,∵,∴,♂,♀,°,′,″,℃,$,¤,¢,£,‰,§,№,☆,★,○,●,◎,◇,◆,□,■,△,▲,※,→,←,↑,↓,〓,〡,〢,〣,〤,〥,〦,〧,〨,〩,㊣,㎎,㎏,㎜,㎝,㎞,㎡,㏄,㏎,㏑,㏒,㏕,︰,¬,¦,℡,ˊ,ˋ,˙,–,―,‥,‵,℅,℉,↖,↗,↘,↙,∕,∟,∣,≒,≦,≧,⊿,═,║,╒,╓,╔,╕,╖,╗,╘,╙,╚,╛,╜,╝,╞,╟,╠,╡,╢,╣,╤,╥,╦,╧,╨,╩,╪,╫,╬,╭,╮,╯,╰,╱,╲,╳,▁,▂,▃,▄,▅,▆,▇,█,█,▉,▊,▋,▌,▍,▎,▏,▓,▔,▕,▼,▽,◢,◣,◤,◥,☉,⊕,〒,〝,〞")},
     { name:"lmsz", title:lang.lmsz, content:toArray("ⅰ,ⅱ,ⅲ,ⅳ,ⅴ,ⅵ,ⅶ,ⅷ,ⅸ,ⅹ,Ⅰ,Ⅱ,Ⅲ,Ⅳ,Ⅴ,Ⅵ,Ⅶ,Ⅷ,Ⅸ,Ⅹ,Ⅺ,Ⅻ")},
     { name:"szfh", title:lang.szfh, content:toArray("⒈,⒉,⒊,⒋,⒌,⒍,⒎,⒏,⒐,⒑,⒒,⒓,⒔,⒕,⒖,⒗,⒘,⒙,⒚,⒛,⑴,⑵,⑶,⑷,⑸,⑹,⑺,⑻,⑼,⑽,⑾,⑿,⒀,⒁,⒂,⒃,⒄,⒅,⒆,⒇,①,②,③,④,⑤,⑥,⑦,⑧,⑨,⑩,㈠,㈡,㈢,㈣,㈤,㈥,㈦,㈧,㈨,㈩")},
     { name:"rwfh", title:lang.rwfh, content:toArray("ぁ,あ,ぃ,い,ぅ,う,ぇ,え,ぉ,お,か,が,き,ぎ,く,ぐ,け,げ,こ,ご,さ,ざ,し,じ,す,ず,せ,ぜ,そ,ぞ,た,だ,ち,ぢ,っ,つ,づ,て,で,と,ど,な,に,ぬ,ね,の,は,ば,ぱ,ひ,び,ぴ,ふ,ぶ,ぷ,へ,べ,ぺ,ほ,ぼ,ぽ,ま,み,む,め,も,ゃ,や,ゅ,ゆ,ょ,よ,ら,り,る,れ,ろ,ゎ,わ,ゐ,ゑ,を,ん,ァ,ア,ィ,イ,ゥ,ウ,ェ,エ,ォ,オ,カ,ガ,キ,ギ,ク,グ,ケ,ゲ,コ,ゴ,サ,ザ,シ,ジ,ス,ズ,セ,ゼ,ソ,ゾ,タ,ダ,チ,ヂ,ッ,ツ,ヅ,テ,デ,ト,ド,ナ,ニ,ヌ,ネ,ノ,ハ,バ,パ,ヒ,ビ,ピ,フ,ブ,プ,ヘ,ベ,ペ,ホ,ボ,ポ,マ,ミ,ム,メ,モ,ャ,ヤ,ュ,ユ,ョ,ヨ,ラ,リ,ル,レ,ロ,ヮ,ワ,ヰ,ヱ,ヲ,ン,ヴ,ヵ,ヶ")},
@@ -54,4 +54,4 @@
 })(charsContent);
 function toArray(str) {
     return str.split(",");
-}
+}
\ No newline at end of file
diff --git a/shop_vue/src/api/branch.js b/shop_vue/src/api/branch.js
index 52851f7..fdad109 100644
--- a/shop_vue/src/api/branch.js
+++ b/shop_vue/src/api/branch.js
@@ -107,6 +107,10 @@
   activityStatus(data, errorback) {
     return request._post('/shop/branch.activity/status', data, errorback);
   },
+  /*检查企业差评*/
+  checkNegativeComment(data, errorback) {
+    return request._post('/shop/branch.activity/checkNegativeComment', data, errorback);
+  },
   /*报名列表*/
   activityUserList(data, errorback) {
     return request._post('/shop/branch.activityUser/index', data, errorback);
@@ -116,6 +120,23 @@
     return request._post('/shop/branch.activityFile/lists', data, errorback);
   },
 
+  /*活动评论列表*/
+  activityCommentList(data, errorback) {
+    return request._post('/shop/branch.activityComment/index', data, errorback);
+  },
+  /*活动评论详情*/
+  activityCommentDetail(data, errorback) {
+    return request._post('/shop/branch.activityComment/detail', data, errorback);
+  },
+  /*编辑活动评论*/
+  editActivityComment(data, errorback) {
+    return request._post('/shop/branch.activityComment/edit', data, errorback);
+  },
+  /*删除活动评论*/
+  deleteActivityComment(data, errorback) {
+    return request._post('/shop/branch.activityComment/delete', data, errorback);
+  },
+
   /*获取职务*/
   positionList(data, errorback) {
     return request._post('/shop/branch.position/index', data, errorback);
diff --git a/shop_vue/src/views/branch/activity/add.vue b/shop_vue/src/views/branch/activity/add.vue
index b541948..760cc57 100644
--- a/shop_vue/src/views/branch/activity/add.vue
+++ b/shop_vue/src/views/branch/activity/add.vue
@@ -320,30 +320,66 @@
       // }
       self.$refs.form.validate(valid => {
         if (valid) {
-          self.loading = true;
-          self.form.content = this.$refs.ue.getUEContent();
-          // 如果走访企业,则被走访企业就是场地提供者
-          if (self.form.is_visit) {
-            self.form.space_supplier_id = '';
-          } else {
-            self.form.visit_supplier_id = '';
-          }
-          BranchApi.addActivity(form, true)
-            .then(data => {
-              self.loading = false;
-              self.$message({
-                message: data.msg,
-                type: 'success'
-              });
-              self.$router.push('/branch/activity/index');
-            })
-            .catch(error => {
-              self.loading = false;
+          // 如果是走访活动,先检查差评
+          if (self.form.is_visit && (self.form.visit_supplier_id || self.form.visit_supplier_name)) {
+            BranchApi.checkNegativeComment({
+              visit_supplier_id: self.form.visit_supplier_id || 0,
+              visit_supplier_name: self.form.visit_supplier_name || '',
+              activity_id: 0
+            }).then(res => {
+              if (res.data.has_warning) {
+                // 显示确认对话框
+                self.$confirm(res.data.message, '提示', {
+                  confirmButtonText: '继续走访',
+                  cancelButtonText: '取消',
+                  type: 'warning'
+                }).then(() => {
+                  // 用户确认继续,直接提交
+                  self.submitForm();
+                }).catch(() => {
+                  // 用户取消
+                });
+              } else {
+                // 没有差评警告,直接提交
+                self.submitForm();
+              }
+            }).catch(error => {
+              // 检查失败,直接提交
+              self.submitForm();
             });
+          } else {
+            // 不是走访活动,直接提交
+            self.submitForm();
+          }
         }
       });
     },
 
+    /*提交表单*/
+    submitForm() {
+      let self = this;
+      self.loading = true;
+      self.form.content = this.$refs.ue.getUEContent();
+      // 如果走访企业,则被走访企业就是场地提供者
+      if (self.form.is_visit) {
+        self.form.space_supplier_id = '';
+      } else {
+        self.form.visit_supplier_id = '';
+      }
+      BranchApi.addActivity(self.form, true)
+        .then(data => {
+          self.loading = false;
+          self.$message({
+            message: data.msg,
+            type: 'success'
+          });
+          self.$router.push('/branch/activity/index');
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
     /*选择的地址*/
     selectFromMap(e){
       this.form.coordinate = e.location.lat + ',' + e.location.lng;
diff --git a/shop_vue/src/views/branch/activity/drawer/part/edit.vue b/shop_vue/src/views/branch/activity/drawer/part/edit.vue
index 6a91186..34e54fd 100644
--- a/shop_vue/src/views/branch/activity/drawer/part/edit.vue
+++ b/shop_vue/src/views/branch/activity/drawer/part/edit.vue
@@ -323,30 +323,66 @@
       // form.verify_user_ids = verify_user_ids.join(',');
       self.$refs.form.validate(valid => {
         if (valid) {
-          self.loading = true;
-          self.form.content = this.$refs.ue.getUEContent();
-          // 如果走访企业,则被走访企业就是场地提供者
-          if (self.form.is_visit) {
-            self.form.space_supplier_id = '';
-          } else {
-            self.form.visit_supplier_id = '';
-          }
-          BranchApi.editActivity(form, true)
-            .then(data => {
-              self.loading = false;
-              self.$message({
-                message: data.msg,
-                type: 'success'
-              });
-              this.$emit('success');
-            })
-            .catch(error => {
-              self.loading = false;
+          // 如果是走访活动,先检查差评
+          if (self.form.is_visit && (self.form.visit_supplier_id || self.form.visit_supplier_name)) {
+            BranchApi.checkNegativeComment({
+              visit_supplier_id: self.form.visit_supplier_id || 0,
+              visit_supplier_name: self.form.visit_supplier_name || '',
+              activity_id: self.form.activity_id || 0
+            }).then(res => {
+              if (res.data.has_warning) {
+                // 显示确认对话框
+                self.$confirm(res.data.message, '提示', {
+                  confirmButtonText: '继续走访',
+                  cancelButtonText: '取消',
+                  type: 'warning'
+                }).then(() => {
+                  // 用户确认继续,直接提交
+                  self.submitForm();
+                }).catch(() => {
+                  // 用户取消
+                });
+              } else {
+                // 没有差评警告,直接提交
+                self.submitForm();
+              }
+            }).catch(error => {
+              // 检查失败,直接提交
+              self.submitForm();
             });
+          } else {
+            // 不是走访活动,直接提交
+            self.submitForm();
+          }
         }
       });
     },
 
+    /*提交表单*/
+    submitForm() {
+      let self = this;
+      self.loading = true;
+      self.form.content = this.$refs.ue.getUEContent();
+      // 如果走访企业,则被走访企业就是场地提供者
+      if (self.form.is_visit) {
+        self.form.space_supplier_id = '';
+      } else {
+        self.form.visit_supplier_id = '';
+      }
+      BranchApi.editActivity(self.form, true)
+        .then(data => {
+          self.loading = false;
+          self.$message({
+            message: data.msg,
+            type: 'success'
+          });
+          this.$emit('success');
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
     /*选择的地址*/
     selectFromMap(e){
       this.form.coordinate = e.location.lat + ',' + e.location.lng;
diff --git a/shop_vue/src/views/branch/comment/detail.vue b/shop_vue/src/views/branch/comment/detail.vue
new file mode 100644
index 0000000..33359dc
--- /dev/null
+++ b/shop_vue/src/views/branch/comment/detail.vue
@@ -0,0 +1,150 @@
+<template>
+  <div class="evaluation-detail pb50" v-loading="!loading">
+    <!--form表单-->
+    <el-form size="small" ref="form" :model="form" label-width="120px">
+      <div class="common-form">活动评价详情</div>
+      <el-form-item label="用户">
+        <p v-if="form.user">{{ form.user.nickName }}</p>
+      </el-form-item>
+      <el-form-item label="活动名称">
+        <p v-if="form.activity">{{ form.activity.name }}</p>
+      </el-form-item>
+      <el-form-item label="分会" v-if="form.activity && form.activity.branch">
+        <p>{{ form.activity.branch.name }}</p>
+      </el-form-item>
+      <el-form-item label="走访企业" v-if="form.supplier_name">
+        <p>{{ form.supplier_name }}</p>
+      </el-form-item>
+      <el-form-item label="评论时间">
+        <p>{{ form.create_time_text }}</p>
+      </el-form-item>
+      <el-form-item label="评价图片">
+        <div class="d-s-c evaluation-imgs pb16">
+          <div
+            class="item"
+            v-if="form.images && form.images.length > 0"
+            v-for="(item, index) in form.images"
+            :key="index"
+          >
+            <img v-if="item.file" v-img-url="item.file.file_path" />
+          </div>
+          <span v-if="!form.images || form.images.length == 0">暂无图片</span>
+        </div>
+      </el-form-item>
+      <el-form-item label="评分">
+        <el-rate v-model="form.score" disabled></el-rate>
+        <span class="ml10">{{ form.score }}分</span>
+      </el-form-item>
+      <el-form-item label="评价内容">
+        <div>{{ form.content || '暂无评价内容' }}</div>
+      </el-form-item>
+      <el-form-item label="排序">
+        <el-input type="number" v-model="form.sort" placeholder="请输入数字" style="width: 200px;"></el-input>
+      </el-form-item>
+      <el-form-item label="审核">
+        <el-radio-group v-model="form.status">
+          <el-radio :label="1">通过</el-radio>
+          <el-radio :label="2">不通过</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <!--提交-->
+      <div class="common-button-wrapper">
+        <el-button size="small" type="info" @click="cancelFunc">取消</el-button>
+        <el-button size="small" type="primary" @click="onSubmit">提交</el-button>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import BranchApi from '@/api/branch.js';
+export default {
+  components: {},
+  data() {
+    return {
+      /*form表单数据*/
+      form: {
+        user: {},
+        activity: {}
+      },
+      loading: false,
+      comment_id: 0
+    };
+  },
+  created() {
+    this.comment_id = this.$route.query.comment_id;
+    /*获取列表*/
+    this.getComment();
+  },
+  methods: {
+    /*获取评论*/
+    getComment() {
+      let self = this;
+      BranchApi.activityCommentDetail(
+        {
+          comment_id: self.comment_id
+        },
+        true
+      )
+        .then(data => {
+          self.loading = true;
+          self.form = data.data.data;
+        })
+        .catch(error => {});
+    },
+
+    /*提交*/
+    onSubmit() {
+      let self = this;
+      BranchApi.editActivityComment(
+        {
+          comment_id: self.comment_id,
+          status: self.form.status,
+          sort: self.form.sort
+        },
+        true
+      )
+        .then(data => {
+          if (data.code == 1) {
+            self.$message({
+              message: '恭喜你,操作成功',
+              type: 'success'
+            });
+            self.$router.push('/branch/comment/index');
+          } else {
+            self.$message.error(data.msg || '操作失败');
+          }
+        })
+        .catch(error => {});
+    },
+
+    /*取消*/
+    cancelFunc() {
+      this.$router.back(-1);
+    }
+  }
+};
+</script>
+
+<style>
+.evaluation-detail {
+  margin-bottom: 50px;
+}
+.evaluation-detail .el-form-item {
+  border-bottom: 1px solid #eeeeee;
+}
+.evaluation-detail .el-form-item__label {
+  color: #bbbbbb;
+}
+.evaluation-detail .evaluation-imgs .item {
+  width: 100px;
+  height: 100px;
+  margin-right: 4px;
+  border: 1px solid #d1d5dd;
+}
+.evaluation-detail .evaluation-imgs .item img {
+  width: 98px;
+  height: 98px;
+  object-fit: contain;
+}
+</style>
diff --git a/shop_vue/src/views/branch/comment/index.vue b/shop_vue/src/views/branch/comment/index.vue
new file mode 100644
index 0000000..31b7bb7
--- /dev/null
+++ b/shop_vue/src/views/branch/comment/index.vue
@@ -0,0 +1,236 @@
+<template>
+  <div class="product">
+    <!--搜索表单-->
+    <div class="common-seach-wrap">
+      <el-form size="small" :inline="true" :model="searchForm" class="demo-form-inline">
+        <el-form-item label="评分">
+          <el-select size="small" v-model="searchForm.score" placeholder="全部">
+            <el-option label="全部" :value="0"></el-option>
+            <el-option v-for="(item, index) in commentList" :key="index" :label="item.name" :value="item.val"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="活动名称">
+          <el-input size="small" v-model="searchForm.name" placeholder="请输入活动名称"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button size="small" type="primary" icon="el-icon-search" @click="onSubmit">查询</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <template>
+      <el-tabs v-model="activeName" @tab-click="handleClick">
+        <el-tab-pane label="全部评价" name="-1"></el-tab-pane>
+        <el-tab-pane :label="'待审核(' + num + ')'" name="0"></el-tab-pane>
+        <el-tab-pane label="审核通过" name="1"></el-tab-pane>
+        <el-tab-pane label="审核未通过" name="2"></el-tab-pane>
+      </el-tabs>
+    </template>
+
+    <!--内容-->
+    <div class="product-content">
+      <div class="table-wrap">
+        <el-table size="small" :data="tableData" border style="width: 100%" v-loading="loading">
+          <el-table-column label="活动" width="300px">
+            <template slot-scope="scope">
+              <div class="product-info">
+                <div class="info">
+                  <div class="name">{{ scope.row.activity ? scope.row.activity.name : '-' }}</div>
+                  <div class="branch" v-if="scope.row.activity && scope.row.activity.branch">
+                    <el-tag size="small">{{ scope.row.activity.branch.name }}</el-tag>
+                  </div>
+                </div>
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column prop="user.nickName" label="用户">
+            <template slot-scope="scope">
+              <span v-if="scope.row.user">{{ scope.row.user.nickName }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="score" label="评分">
+            <template slot-scope="scope">
+              <el-rate v-model="scope.row.score" disabled></el-rate>
+            </template>
+          </el-table-column>
+          <el-table-column prop="content" label="评价内容" width="200">
+            <template slot-scope="scope">
+              <p class="ww100 text-ellipsis-2">{{ scope.row.content }}</p>
+            </template>
+          </el-table-column>
+          <el-table-column prop="is_picture" label="图片">
+            <template slot-scope="scope">
+              <span v-if="scope.row.is_picture == 0">没有</span>
+              <span v-else>有</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="status" label="评价状态">
+            <template slot-scope="scope">
+              <span v-if="scope.row.status == 0" class="red fb">待审核</span>
+              <span v-if="scope.row.status == 1" class="green">审核通过</span>
+              <span v-if="scope.row.status == 2" class="gray9">审核未通过</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="sort" label="排序"></el-table-column>
+          <el-table-column prop="create_time" label="评论时间"></el-table-column>
+          <el-table-column fixed="right" label="操作" width="90">
+            <template slot-scope="scope">
+              <el-button @click="detailClick(scope.row)" type="text" size="small">详情</el-button>
+              <el-button @click="delClick(scope.row)" type="text" size="small">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <!--分页-->
+      <div class="pagination">
+        <el-pagination
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+          background
+          :current-page="curPage"
+          :page-size="pageSize"
+          layout="total, prev, pager, next, jumper"
+          :total="totalDataNumber"
+        ></el-pagination>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import BranchApi from '@/api/branch.js';
+export default {
+  components: {},
+  data() {
+    return {
+      loading: true,
+      activeName: '-1',
+      num: 0,
+      /*列表数据*/
+      tableData: [],
+      /*一页多少条*/
+      pageSize: 20,
+      /*总条数*/
+      totalDataNumber: 0,
+      /*当前是第几页*/
+      curPage: 1,
+      /*搜索参数*/
+      searchForm: {
+        score: 0,
+        name: ''
+      },
+      /*评价等级*/
+      commentList: [
+        { name: '好评', val: 10 },
+        { name: '中评', val: 20 },
+        { name: '差评', val: 30 }
+      ],
+      status: -1
+    };
+  },
+  created() {
+    /*获取列表*/
+    this.getData();
+  },
+  methods: {
+    /*选择第几页*/
+    handleCurrentChange(val) {
+      let self = this;
+      self.curPage = val;
+      self.loading = true;
+      let Params = self.searchForm;
+      self.getData(Params);
+    },
+
+    /*每页多少条*/
+    handleSizeChange(val) {
+      this.curPage = 1;
+      this.pageSize = val;
+      this.getData();
+    },
+
+    /*获取列表*/
+    getData(param = '') {
+      let self = this;
+      let Params = {};
+      Params.status = self.status;
+      Params.page = self.curPage;
+      Params.list_rows = self.pageSize;
+      if (param != '') {
+        Params.score = param.score;
+        Params.name = param.name;
+      }
+      BranchApi.activityCommentList(Params, true)
+        .then(res => {
+          self.loading = false;
+          self.tableData = res.data.list.data;
+          self.totalDataNumber = res.data.list.total;
+          self.num = res.data.num;
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    /*打开详情*/
+    detailClick(row) {
+      this.$router.push({
+        path: '/branch/comment/detail',
+        query: {
+          comment_id: row.comment_id
+        }
+      });
+    },
+
+    /*删除*/
+    delClick: function(row) {
+      let self = this;
+      self
+        .$confirm('删除后不可恢复,确认删除该记录吗?', '提示', {
+          type: 'warning'
+        })
+        .then(() => {
+          BranchApi.deleteActivityComment({
+            comment_id: row.comment_id
+          }).then(data => {
+            self.$message({
+              message: '删除成功',
+              type: 'success'
+            });
+            self.getData();
+          });
+        });
+    },
+
+    /*搜索查询*/
+    onSubmit() {
+      let self = this;
+      self.loading = true;
+      let Params = self.searchForm;
+      Params.page = self.curPage;
+      Params.list_rows = self.pageSize;
+      Params.status = self.status;
+      BranchApi.activityCommentList(Params, true)
+        .then(data => {
+          self.loading = false;
+          self.tableData = data.data.list.data;
+          self.totalDataNumber = data.data.list.total;
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    /*切换选项卡*/
+    handleClick(tab, event) {
+      let self = this;
+      self.curPage = 1;
+      self.loading = true;
+      self.status = tab.name;
+      self.getData();
+    }
+  }
+};
+</script>
+
+<style></style>
diff --git a/shop_vue/src/views/branch/setting/part/Basic.vue b/shop_vue/src/views/branch/setting/part/Basic.vue
index 375484b..2c6f06c 100644
--- a/shop_vue/src/views/branch/setting/part/Basic.vue
+++ b/shop_vue/src/views/branch/setting/part/Basic.vue
@@ -33,6 +33,10 @@
       <el-form-item label="照片下载消耗积分">
         <el-input v-model="form.download_image_points" type="number" class="max-w460"></el-input>
       </el-form-item>
+      <div class="common-form">评论</div>
+      <el-form-item label="差评阈值">
+        <el-input v-model="form.negative_comment_threshold" type="number" class="max-w460"></el-input>
+      </el-form-item>
       <!-- <el-form-item label="视频下载消耗积分">
         <el-input v-model="form.download_video_points" type="number" class="max-w460"></el-input>
       </el-form-item> -->
@@ -83,7 +87,7 @@
           self.loading = false;
         });
     },
-    
+
   }
 };
 </script>
diff --git a/shop_vue/src/views/plus/region/auth/access/Index.vue b/shop_vue/src/views/plus/region/auth/access/Index.vue
new file mode 100644
index 0000000..7ad0d67
--- /dev/null
+++ b/shop_vue/src/views/plus/region/auth/access/Index.vue
@@ -0,0 +1,288 @@
+<template>
+  <!--
+    	作者:参考 access/Index.vue
+    	时间:2026-01-20
+    	描述:区域代理商-菜单&权限
+    -->
+  <div class="product">
+    <!--添加菜单&权限-->
+    <div class="common-level-rail d-b-c">
+      <el-button size="small" type="primary" @click="addClick" icon="el-icon-plus">添加菜单&权限</el-button>
+      <el-form :inline="true" :model="formSearch" size="small">
+        <el-form-item>
+          <el-checkbox v-model="formSearch.is_menu" @change="changeIsMenuFunc">只显示菜单</el-checkbox>
+          <el-checkbox v-model="formSearch.pack_up" @change="changePackUpFunc">收起</el-checkbox>
+        </el-form-item>
+      </el-form>
+    </div>
+    <!--内容-->
+    <div class="product-content">
+      <div class="table-wrap">
+        <div>
+          <el-table
+            size="small"
+            :data="tableData"
+            style="width: 100%;margin-bottom: 20px;"
+            row-key="access_id"
+            border
+            default-expand-all
+            ref="theTable"
+            :tree-props="{ children: 'children' }"
+            v-loading="loading"
+          >
+            <el-table-column prop="name" label="菜单名称">
+              <template slot-scope="scope">
+                <span v-if="scope.row.path=='/plus'" class="fb red f18">
+                  {{scope.row.name}}
+                </span>
+                <span v-else>
+                  {{scope.row.name}}
+                </span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="path" label="路径"></el-table-column>
+            <el-table-column prop="is_route" label="类别" width="90">
+              <template slot-scope="scope">
+                <span v-if="scope.row.is_route==1">页面</span>
+                <span v-if="scope.row.is_route==0">按钮</span>
+                <span v-if="scope.row.is_route==2">独立单页面</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="is_show" label="是否显示" width="80">
+              <template slot-scope="scope">
+                <el-switch
+                  v-model="scope.row.is_show"
+                  :active-value="1"
+                  :inactive-value="0"
+                  @change="isShowFunc(scope.row)"
+                  active-color="#13ce66"
+                  inactive-color="#cccccc"
+                ></el-switch>
+              </template>
+            </el-table-column>
+            <el-table-column prop="sort" label="排序" width="60"></el-table-column>
+            <el-table-column prop="create_time" label="添加时间" width="140"></el-table-column>
+            <el-table-column prop="name" label="操作" width="230">
+              <template slot-scope="scope">
+                <el-button @click="addClick(scope.row,'copy')" type="text" size="small" v-if="scope.row.path!='/plus'">一键复制</el-button>
+                <el-button @click="addClick(scope.row,'child')" type="text" size="small">添加子菜单</el-button>
+                <el-button @click="editClick(scope.row)" type="text" size="small">编辑</el-button>
+                <el-button @click="deleteClick(scope.row)" type="text" size="small" v-if="scope.row.path!='/plus'">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </div>
+    </div>
+
+    <!--添加-->
+    <Add v-if="open_add" :open_add="open_add" :add_type="add_type" :rawData="rawData" :selectModel="selectModel" @closeDialog="closeDialogFunc($event, 'add')"></Add>
+
+    <!--编辑-->
+    <Edit v-if="open_edit" :open_edit="open_edit" :rawData="rawData" :selectModel="selectModel" @closeDialog="closeDialogFunc($event, 'edit')"></Edit>
+
+  </div>
+</template>
+<script>
+import PlusApi from '@/api/plus/region.js';
+import Edit from './part/Edit.vue';
+import Add from './part/Add.vue';
+import { deepClone } from '@/utils/base.js';
+export default {
+  components: {
+    /*编辑组件*/
+    Edit: Edit,
+    Add: Add
+  },
+  data() {
+    return {
+      /*是否正在加载*/
+      loading: true,
+      /*筛选搜索*/
+      formSearch: {
+        /*是否只显示菜单*/
+        is_menu: false,
+        /*是否收起*/
+        pack_up: false
+      },
+      /*原始数据*/
+      rawData: [],
+      /*表格数据*/
+      tableData: [],
+      /*是否打开添加弹窗*/
+      open_add: false,
+      /*添加类型*/
+      add_type:'',
+      /*选中的对象*/
+      selectModel:{},
+      /*是否打开编辑弹窗*/
+      open_edit: false,
+      /*当前编辑的对象*/
+      userModel: {},
+    };
+  },
+  created() {
+    /*获取列表*/
+    this.getTableList();
+  },
+  methods: {
+    /*列表是否只显示菜单*/
+    changeIsMenuFunc(e) {
+      let list = deepClone(this.rawData);
+      if (e) {
+        this.showScreen(list, 1);
+        this.tableData = list;
+      } else {
+        this.tableData = list;
+      }
+    },
+
+    /*是否显示开关*/
+    isShowFunc(e) {
+      let self = this;
+      PlusApi.regionAccessStatus({ access_id: e.access_id, status: e.is_show }, true)
+        .then(data => {
+          if (data.code == 1) {
+            self.$message({
+              message: data.msg,
+              type: 'success'
+            });
+            self.getTableList();
+          }
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    /*是否收起*/
+    changePackUpFunc(e) {
+      this.forArr(this.tableData, !e);
+    },
+
+    /*列表收起*/
+    forArr(arr, isExpand) {
+      arr.forEach(i => {
+        this.$refs.theTable.toggleRowExpansion(i, isExpand);
+        if (i.children) {
+          this.forArr(i.children, isExpand);
+        }
+      });
+    },
+
+    /*切换显示类别*/
+    changeShowFunc(e) {
+      let list = deepClone(this.rawData);
+      if (e == 'all') {
+        this.tableData = list;
+      } else {
+        let type;
+        if (e == 'show') {
+          type = 1;
+        }
+        if (e == 'hide') {
+          type = 0;
+        }
+        this.showScreen(list, type);
+        this.tableData = list;
+      }
+    },
+
+    /*显示筛选*/
+    showScreen(list, type) {
+      for (let i = 0; i < list.length; i++) {
+        let item = list[i];
+        if (typeof item.is_menu != 'undefined' && item.is_menu != type) {
+          list.splice(i, 1);
+          i--;
+        } else {
+          if (item.children.length > 0) {
+            this.showScreen(item.children, type);
+          }
+        }
+      }
+    },
+
+    /*获取列表*/
+    getTableList() {
+      let self = this;
+      let Params = {};
+      PlusApi.regionAccessList(Params, true)
+        .then(res => {
+          self.loading = false;
+          self.rawData = res.data;
+          self.tableData = res.data;
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    /*打开添加*/
+    addClick(e,type) {
+      if(e&&typeof(e)!='undefined'){
+        this.add_type=type;
+        this.selectModel=deepClone(e);
+      }else{
+        this.parents_id=0;
+      }
+      this.open_add = true;
+    },
+
+    /*打开编辑*/
+    editClick(item) {
+      this.selectModel = item;
+      this.open_edit = true;
+    },
+
+    closeDialogFunc(e, f) {
+      if (f == 'add') {
+        this.open_add = e.openDialog;
+        if (e.type == 'success') {
+          this.getTableList();
+        }
+      }
+      if (f == 'edit') {
+        this.open_edit = e.openDialog;
+        if (e.type == 'success') {
+          this.getTableList();
+        }
+      }
+    },
+
+    /*删除用户*/
+    deleteClick(row) {
+      let self = this;
+      self
+        .$confirm('删除后不可恢复,确认删除该记录吗?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        .then(() => {
+          self.loading = true;
+          PlusApi.regionAccessDelete(
+            {
+              access_id: row.access_id
+            },
+            true
+          )
+            .then(data => {
+              if (data.code == 1) {
+                self.loading = false;
+                self.$message({
+                  message: data.msg,
+                  type: 'success'
+                });
+                self.getTableList();
+              }
+            })
+            .catch(error => {
+              self.loading = false;
+            });
+        })
+        .catch(() => {});
+    }
+  }
+};
+</script>
diff --git a/shop_vue/src/views/plus/region/auth/access/part/Add.vue b/shop_vue/src/views/plus/region/auth/access/part/Add.vue
new file mode 100644
index 0000000..b94036e
--- /dev/null
+++ b/shop_vue/src/views/plus/region/auth/access/part/Add.vue
@@ -0,0 +1,218 @@
+<template>
+  <!--
+    	作者:参考 access/part/Add.vue
+    	时间:2026-01-20
+    	描述:区域代理商权限管理-添加菜单&权限
+    -->
+  <el-dialog title="添加菜单&权限" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false">
+    <el-form size="small" :model="formData" :rules="formRules" ref="form">
+      <!--菜单名称-->
+      <el-form-item label="菜单名称" prop="name" :label-width="formLabelWidth">
+        <el-input v-model="formData.name" autocomplete="off" placeholder="请输入菜单名称"></el-input>
+      </el-form-item>
+      <!--类型-->
+      <el-form-item label="类型" prop="name" :label-width="formLabelWidth">
+        <el-radio-group v-model="formData.is_route">
+          <el-radio :label="1">页面</el-radio>
+          <el-radio :label="0">按钮</el-radio>
+          <el-radio :label="2">独立单页面</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <!--上级菜单-->
+      <el-form-item label="上级菜单" prop="parent_id" :label-width="formLabelWidth">
+        <el-cascader size="small" v-model="parentsVal" :options="accessList" :props="propsParam" @change="handleChange"></el-cascader>
+      </el-form-item>
+      <!--路径-->
+      <el-form-item label="路径" prop="path" :label-width="formLabelWidth">
+        <el-input v-model="formData.path" autocomplete="off" placeholder="请输入组件文件路径"></el-input>
+        <p>提示:对应前端给的文件路径,例如:/index/index</p>
+      </el-form-item>
+      <!--图标-->
+      <el-form-item label="图标" :label-width="formLabelWidth">
+        <el-input v-model="formData.icon" autocomplete="off" placeholder="请输入icon"></el-input>
+        <p>提示:请选择系统提供的图标</p>
+      </el-form-item>
+      <!--是否是菜单-->
+      <el-form-item label="是否是菜单" :label-width="formLabelWidth" v-if="formData.is_route==1">
+        <el-radio-group v-model="formData.is_menu">
+          <el-radio :label="1">是</el-radio>
+          <el-radio :label="0">否</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <!--是否显示-->
+      <el-form-item label="是否显示" :label-width="formLabelWidth">
+        <el-radio-group v-model="formData.is_show">
+          <el-radio :label="1">是</el-radio>
+          <el-radio :label="0">否</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <!--重定向-->
+      <el-form-item label="重定向" :label-width="formLabelWidth" v-if="formData.is_route == 1">
+        <el-input v-model="formData.redirect_name" autocomplete="off" placeholder="请输入重定向地址"></el-input>
+      </el-form-item>
+      <!--备注-->
+      <el-form-item label="备注" prop="sort" :label-width="formLabelWidth">
+        <el-input v-model="formData.remark" placeholder="请输入备注" type="textarea"></el-input>
+      </el-form-item>
+      <!--排序-->
+      <el-form-item label="排序" prop="sort" :label-width="formLabelWidth">
+        <el-input v-model="formData.sort" placeholder="请输入排序" type="number"></el-input>
+      </el-form-item>
+    </el-form>
+    <!--操作按钮-->
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="dialogFormVisible">取 消</el-button>
+      <el-button type="primary" @click="onSubmit()" :disabled="loading">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import PlusApi from '@/api/plus/region.js';
+import { deepClone, formatModel } from '@/utils/base.js';
+export default {
+  data() {
+    return {
+      /*是否加载中*/
+      loading: false,
+      /*form表单数据对象*/
+      formData: {
+        /*菜单名称*/
+        name: '',
+        /*路由地址*/
+        path: '',
+        /*组件名*/
+        views: '',
+        /*别名*/
+        alias: '',
+        /*图标*/
+        icon: '',
+        /*是否是菜单*/
+        is_menu: 0,
+        /*是否是路由*/
+        is_route: 1,
+        /*是否显示*/
+        is_show: 1,
+        /*排序*/
+        sort: 1,
+        /*父集ID*/
+        parent_id: 0
+      },
+      /*验证规则*/
+      formRules: {
+        name: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
+        path: [{ required: true, message: '请输入路径', trigger: 'blur' }],
+        views: [{ required: true, message: '请输入组件名称', trigger: 'blur' }],
+        alias: [{ required: true, message: '请输入别名', trigger: 'blur' }]
+      },
+      /*当前父集ID*/
+      parentsVal: [],
+      /*菜单列表*/
+      accessList: [],
+      /*排序*/
+      srot: '1',
+      /*左边长度*/
+      formLabelWidth: '120px',
+      /*是否显示*/
+      dialogVisible: false,
+      /*展示数据*/
+      propsParam: {
+        label: 'name',
+        value: 'access_id',
+        checkStrictly: true
+      }
+    };
+  },
+  props: {
+    open_add: Boolean,
+    add_type: String,
+    rawData: Array,
+    selectModel: Object
+  },
+  created() {
+
+    this.dialogVisible = this.open_add;
+    this.accessList = deepClone(this.rawData);
+    this.accessList.unshift({ name: '顶级菜单', access_id: 0 });
+    if (this.add_type == 'copy') {
+      this.formData = formatModel(this.formData, this.selectModel);
+      this.findParentsID(this.accessList);
+    } else if (this.add_type == 'child') {
+      this.formData.parent_id = this.selectModel.access_id;
+      this.findParentsID(this.accessList);
+    }
+  },
+  methods: {
+    /*选择菜单*/
+    handleChange(e) {},
+
+    /*查找父集id*/
+    findParentsID(list){
+      let flag=false;
+      for(let i=0;i<list.length;i++){
+        let item=list[i];
+        if(item.access_id==this.formData.parent_id){
+          this.parentsVal.unshift(item.access_id);
+          flag=true;
+          break;
+        }else{
+          let children=item.children;
+          if(typeof children!='undefined'&&children.length>0){
+              if(this.findParentsID(children)){
+                this.parentsVal.unshift(item.access_id);
+                flag=true;
+                break;
+              }
+          }
+        }
+      }
+      return flag;
+    },
+
+    /*添加菜单*/
+    onSubmit() {
+      let self = this;
+      let params = this.formData;
+      if (self.parentsVal.length > 0) {
+        params.parent_id = self.parentsVal[self.parentsVal.length - 1];
+      }
+      self.$refs.form.validate(valid => {
+        if (valid) {
+          self.loading = true;
+          PlusApi.regionAccessAdd(params, true)
+            .then(res => {
+              if (res.code == 1) {
+                self.$message({
+                  message: res.msg,
+                  type: 'success'
+                });
+                self.dialogFormVisible(true);
+                self.loading = false;
+              }
+            })
+            .catch(error => {
+              self.loading = false;
+            });
+        }
+      });
+    },
+
+    /*关闭弹窗*/
+    dialogFormVisible(e) {
+      if (e) {
+        this.$emit('closeDialog', {
+          type: 'success',
+          openDialog: false
+        });
+      } else {
+        this.$emit('closeDialog', {
+          type: 'error',
+          openDialog: false
+        });
+      }
+    }
+  }
+};
+</script>
+
+<style></style>
diff --git a/shop_vue/src/views/plus/region/auth/access/part/Edit.vue b/shop_vue/src/views/plus/region/auth/access/part/Edit.vue
new file mode 100644
index 0000000..18761f8
--- /dev/null
+++ b/shop_vue/src/views/plus/region/auth/access/part/Edit.vue
@@ -0,0 +1,210 @@
+<template>
+  <!--
+    	作者:参考 access/part/Edit.vue
+    	时间:2026-01-20
+    	描述:区域代理商权限管理-修改菜单&权限
+    -->
+  <el-dialog title="修改菜单&权限" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false">
+    <el-form size="small" :model="formData" :rules="formRules" ref="form">
+      <!--菜单名称-->
+      <el-form-item label="菜单名称" prop="name" :label-width="formLabelWidth">
+        <el-input v-model="formData.name" autocomplete="off" placeholder="请输入菜单名称"></el-input>
+      </el-form-item>
+      <!--类型-->
+      <el-form-item label="类型" prop="name" :label-width="formLabelWidth">
+        <el-radio-group v-model="formData.is_route">
+          <el-radio :label="1">页面</el-radio>
+          <el-radio :label="0">按钮</el-radio>
+          <el-radio :label="2">独立单页面</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <!--上级菜单-->
+      <el-form-item label="上级菜单" prop="parent_id" :label-width="formLabelWidth">
+        <el-cascader size="small" v-model="parentsVal" :options="accessList" :props="propsParam" @change="handleChange"></el-cascader>
+      </el-form-item>
+      <!--路径-->
+      <el-form-item label="路径" prop="path" :label-width="formLabelWidth">
+        <el-input v-model="formData.path" autocomplete="off" placeholder="请输入组件文件路径" :disabled="formData.path=='/plus'"></el-input>
+        <p>提示:对应前端给的文件路径,例如:index/index</p>
+      </el-form-item>
+      <!--图标-->
+      <el-form-item label="图标" :label-width="formLabelWidth">
+        <el-input v-model="formData.icon" autocomplete="off" placeholder="请输入icon"></el-input>
+        <p>提示:请选择系统提供的图标</p>
+      </el-form-item>
+      <!--是否是菜单-->
+      <el-form-item label="是否是菜单" :label-width="formLabelWidth" v-if="formData.is_route==1">
+        <el-radio-group v-model="formData.is_menu">
+          <el-radio :label="1">是</el-radio>
+          <el-radio :label="0">否</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <!--是否显示-->
+      <el-form-item label="是否显示" :label-width="formLabelWidth">
+        <el-radio-group v-model="formData.is_show">
+          <el-radio :label="1">是</el-radio>
+          <el-radio :label="0">否</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <!--重定向-->
+      <el-form-item label="重定向" :label-width="formLabelWidth" v-if="formData.is_route == 1">
+        <el-input v-model="formData.redirect_name" autocomplete="off" placeholder="请输入重定向地址"></el-input>
+      </el-form-item>
+      <!--备注-->
+      <el-form-item label="备注" prop="sort" :label-width="formLabelWidth">
+        <el-input v-model="formData.remark" placeholder="请输入备注" type="textarea"></el-input>
+      </el-form-item>
+      <!--排序-->
+      <el-form-item label="排序" prop="sort" :label-width="formLabelWidth"><el-input v-model="formData.sort" placeholder="请输入排序" type="number"></el-input></el-form-item>
+    </el-form>
+    <!--操作按钮-->
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="dialogFormVisible">取 消</el-button>
+      <el-button type="primary" @click="onSubmit()" :disabled="loading">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import PlusApi from '@/api/plus/region.js';
+import { deepClone } from '@/utils/base.js';
+export default {
+  data() {
+    return {
+      /*是否加载中*/
+      loading: false,
+      /*form表单数据对象*/
+      formData: {
+        /*菜单名称*/
+        name: '',
+        /*路由地址*/
+        path:'',
+        /*组件名*/
+        views:'',
+        /*别名*/
+        alias:'',
+        /*图标*/
+        icon:'',
+        /*是否是菜单*/
+        is_menu: 1,
+        /*是否是路由*/
+        is_route: 1,
+        /*是否显示*/
+        is_show: 0,
+        /*排序*/
+        sort: 1,
+        /*父集ID*/
+        parent_id: 0
+      },
+      /*验证规则*/
+      formRules: {
+        name: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
+        path: [{ required: true, message: '请输入路径', trigger: 'blur' }],
+        views: [{ required: true, message: '请输入组件名称', trigger: 'blur' }],
+        alias: [{ required: true, message: '请输入别名', trigger: 'blur' }]
+      },
+      /*当前父集ID*/
+      parentsVal: [],
+      /*菜单列表*/
+      accessList: [],
+      /*排序*/
+      srot: '1',
+      /*左边长度*/
+      formLabelWidth: '120px',
+      /*是否显示*/
+      dialogVisible: false,
+      /*展示数据*/
+      propsParam: {
+        label: 'name',
+        value: 'access_id',
+        checkStrictly: true
+      }
+    };
+  },
+  props: {
+    open_edit:Boolean,
+    add_type:String,
+    rawData:Array,
+    selectModel:Object
+  },
+  created() {
+    this.dialogVisible = this.open_edit;
+    this.accessList = deepClone(this.rawData);
+    this.accessList.unshift({name:'顶级菜单',access_id:0})
+    this.formData=deepClone(this.selectModel);
+    this.findParentsID(this.accessList);
+
+  },
+  methods: {
+
+    /*选择菜单*/
+    handleChange(e) {
+    },
+
+    /*查找父集id*/
+    findParentsID(list){
+      let flag=false;
+      for(let i=0;i<list.length;i++){
+        let item=list[i];
+        if(item.access_id==this.formData.parent_id){
+          this.parentsVal.unshift(item.access_id);
+          flag=true;
+          break;
+        }else{
+          let children=item.children;
+          if(typeof children!='undefined'&&children.length>0){
+              if(this.findParentsID(children)){
+                this.parentsVal.unshift(item.access_id);
+                flag=true;
+                break;
+              }
+          }
+        }
+      }
+      return flag;
+    },
+
+    /*修改菜单*/
+    onSubmit() {
+      let self = this;
+      let params = self.formData;
+      if(self.parentsVal.length>0){
+        params.parent_id=self.parentsVal[self.parentsVal.length-1];
+      }
+      self.$refs.form.validate(valid => {
+        if (valid) {
+          self.loading = true;
+          PlusApi.regionAccessEdit(params, true)
+            .then(res => {
+              if (res.code == 1) {
+                self.$message({
+                  message: res.msg,
+                  type: 'success',
+                });
+                self.$emit('closeDialog', {
+                  type: 'success',
+                  openDialog: false,
+                  data:params
+                });
+                self.loading = false;
+              }
+            })
+            .catch(error => {
+              self.loading = false;
+            });
+        }
+      });
+    },
+
+    /*关闭弹窗*/
+    dialogFormVisible(e) {
+      this.$emit('closeDialog', {
+        type: 'error',
+        openDialog: false
+      });
+    }
+  }
+};
+</script>
+
+<style></style>
diff --git a/shop_vue/src/views/plus/region/auth/index.vue b/shop_vue/src/views/plus/region/auth/index.vue
new file mode 100644
index 0000000..1956554
--- /dev/null
+++ b/shop_vue/src/views/plus/region/auth/index.vue
@@ -0,0 +1,35 @@
+<template>
+  <div>
+    <el-tabs size="small" v-model="activeName" type="card" @tab-click="handleClick">
+      <el-tab-pane label="管理员" name="user"></el-tab-pane>
+      <el-tab-pane label="角色" name="role"></el-tab-pane>
+    </el-tabs>
+    <!--角色管理-->
+    <Role v-if="activeName == 'role'"></Role>
+    <!--管理员列表-->
+    <User v-if="activeName == 'user'"></User>
+  </div>
+</template>
+<script>
+import Role from './role/Index';
+import User from './user/Admin';
+export default {
+  components: {
+    Role,
+    User
+  },
+  data() {
+    return {
+      /*当前选中*/
+      activeName: 'user',
+    };
+  },
+  created() {},
+  methods: {
+
+    handleClick(e) {
+      this.activeName = e.name;
+    }
+  }
+};
+</script>
diff --git a/shop_vue/src/views/plus/region/auth/role/Index.vue b/shop_vue/src/views/plus/region/auth/role/Index.vue
new file mode 100644
index 0000000..7e24471
--- /dev/null
+++ b/shop_vue/src/views/plus/region/auth/role/Index.vue
@@ -0,0 +1,142 @@
+<template>
+  <!--
+        作者:参考 auth/role
+        时间:2026-01-20
+        描述:区域代理商-角色管理
+    -->
+  <div class="user">
+    <div class="common-level-rail">
+      <el-button size="small" type="primary" icon="el-icon-plus" v-auth="'/plus/region/auth/role/add'" @click="addClick">添加角色</el-button>
+    </div>
+
+    <!--内容-->
+    <div class="product-content">
+      <div class="table-wrap">
+        <el-table size="small" :data="tableData" border style="width: 100%" v-loading="loading">
+          <el-table-column prop="role_id" label="角色ID"></el-table-column>
+          <el-table-column prop="role_name" label="角色名称"></el-table-column>
+          <el-table-column prop="sort" label="排序"></el-table-column>
+          <el-table-column prop="create_time" label="添加时间"></el-table-column>
+          <el-table-column fixed="right" label="操作" width="150">
+            <template slot-scope="scope">
+              <el-button @click="editClick(scope.row)" v-auth="'/plus/region/auth/role/edit'" type="text" size="small">编辑</el-button>
+              <el-button @click="deleteClick(scope.row)" v-if="scope.row.region_level == 0" v-auth="'/plus/region/auth/role/delete'" type="text" size="small">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </div>
+
+  </div>
+</template>
+
+<script>
+import PlusApi from '@/api/plus/region.js';
+export default {
+  data() {
+    return {
+      /*是否加载完成*/
+      loading: true,
+      /*列表数据*/
+      tableData: [],
+      /*是否打开添加弹窗*/
+      open_add: false,
+      /*是否打开编辑弹窗*/
+      open_edit: false,
+      /*当前编辑的对象*/
+      curModel: {}
+    };
+  },
+  created() {
+    /*获取列表*/
+    this.getTableList();
+  },
+  methods: {
+    /*获取列表*/
+    getTableList() {
+      let self = this;
+      let Params = {};
+      PlusApi.regionRoleList(Params, true)
+        .then(data => {
+          self.loading = false;
+          self.tableData = data.data.list;
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    /*打开添加*/
+    addClick() {
+      this.$router.push('/plus/region/auth/role/add');
+    },
+
+    /*关闭添加*/
+    closeAdd(e){
+      this.open_add = false;
+      if(e.type=='success'){
+        this.getTableList();
+      }
+    },
+
+    /*打开编辑*/
+    editClick(row) {
+      this.curModel = row;
+      this.$router.push({
+        path: '/plus/region/auth/role/edit',
+        query: {
+          role_id: row.role_id,
+          scene: 'edit'
+        }
+      });
+      //this.open_edit = true;
+    },
+
+    /*关闭编辑*/
+    closeEdit(e){
+      this.open_edit = false;
+      if(e.type=='success'){
+        this.getTableList();
+      }
+    },
+
+    /*删除*/
+    deleteClick(row) {
+      let self = this;
+      self
+        .$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        .then(() => {
+          self.loading = true;
+          PlusApi.regionRoleDelete(
+            {
+              role_id: row.role_id
+            },
+            true
+          )
+            .then(data => {
+              self.loading = false;
+              if (data.code == 1) {
+                self.$message({
+                  message: '恭喜你,该角色删除成功',
+                  type: 'success'
+                });
+                self.getTableList();
+              } else {
+                self.loading = false;
+              }
+            })
+            .catch(error => {
+              self.loading = false;
+            });
+        })
+        .catch(() => {});
+    }
+  }
+};
+</script>
+
+<style></style>
diff --git a/shop_vue/src/views/plus/region/auth/role/add.vue b/shop_vue/src/views/plus/region/auth/role/add.vue
new file mode 100644
index 0000000..1b6504f
--- /dev/null
+++ b/shop_vue/src/views/plus/region/auth/role/add.vue
@@ -0,0 +1,179 @@
+<template>
+  <!--
+        作者:参考 auth/role/add
+        时间:2026-01-21
+        描述:区域代理商-角色管理-添加角色
+    -->
+  <div v-loading="loading">
+    <!--form表单-->
+    <el-form size="small" ref="form" :model="form" :rules="formRules" label-width="180px">
+      <!--添加门店-->
+      <div class="common-form">添加角色</div>
+
+      <el-form-item label="角色名称:" prop="role_name">
+        <el-input v-model="form.role_name" placeholder="请输入角色名称" class="max-w460"></el-input>
+      </el-form-item>
+
+      <el-form-item label="权限列表:" v-model="form.access_id">
+        <el-tree :data="treeData" show-checkbox node-key="access_id" :default-expand-all="true" :default-checked-keys="[]" :props="defaultProps" @check="handleCheckChange"></el-tree>
+      </el-form-item>
+
+      <el-form-item label="排序:"><el-input type="number" v-model="form.sort" placeholder="请输入排序数字,数字越小越靠前" class="max-w460"></el-input></el-form-item>
+
+      <!--提交-->
+      <div class="common-button-wrapper">
+        <el-button size="small" type="info" @click="cancelFunc">取消</el-button>
+        <el-button type="primary" size="small" @click="onSubmit" :loading="loading">提交</el-button>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import PlusApi from '@/api/plus/region.js';
+
+export default {
+  data() {
+    return {
+      /*是否正在加载*/
+      loading:true,
+      /*form表单数据对象*/
+      form: {
+        access_id: [],
+        sort: 100
+      },
+      data: [], // 原始数据
+      treeData: [], // 树形结构数据
+      roleList: [],
+      defaultProps: {
+        children: 'children',
+        label: 'name'
+      },
+      /*form验证*/
+      formRules: {
+        role_name: [
+          {
+            required: true,
+            message: '请输入角色名称',
+            trigger: 'blur'
+          }
+        ],
+        sort: [
+          {
+            required: true,
+            message: '请输入排序',
+            trigger: 'blur'
+          }
+        ]
+      },
+    };
+  },
+  created() {
+    /*获取数据*/
+    this.getData();
+  },
+  methods: {
+    /*添加角色*/
+    onSubmit() {
+      let self = this;
+      let form = self.form;
+      self.$refs.form.validate(valid => {
+        if (valid) {
+          self.loading = true;
+          PlusApi.regionRoleAdd({
+            params: JSON.stringify(form)
+          }, true)
+            .then(data => {
+              self.loading = false;
+              self.$message({
+                message: '添加成功',
+                type: 'success'
+              });
+              self.$router.push('/plus/region/auth/role/index');
+            })
+            .catch(error => {
+              self.loading = false;
+            });
+        }
+      });
+    },
+
+    /*获取数据*/
+    getData() {
+      let self = this;
+      PlusApi.regionRoleAddInfo()
+        .then(data => {
+          self.data = data.data.menu;
+          self.treeData = self.buildTree(self.data); // 构建树形结构
+          self.roleList = data.data.roleList;
+          self.loading = false;
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    // 将扁平化数据转换为树形结构
+    buildTree(data) {
+      if (!data || !Array.isArray(data)) {
+        return [];
+      }
+      
+      // 创建映射表
+      const map = {};
+      const roots = [];
+      
+      // 首先创建映射
+      for (let i = 0; i < data.length; i++) {
+        map[data[i].access_id] = i;
+        // 初始化children数组
+        data[i].children = [];
+      }
+      
+      // 然后建立父子关系
+      for (let i = 0; i < data.length; i++) {
+        const node = data[i];
+        if (node.parent_id === 0 || node.parent_id === '0') {
+          // 如果parent_id为0,则为根节点
+          roots.push(node);
+        } else {
+          // 查找父节点
+          const parentId = node.parent_id;
+          if (map.hasOwnProperty(parentId)) {
+            // 将当前节点添加到其父节点的children数组中
+            data[map[parentId]].children.push(node);
+          } else {
+            // 如果找不到父节点,也作为根节点处理
+            roots.push(node);
+          }
+        }
+      }
+      
+      return roots;
+    },
+
+    //监听选中
+    handleCheckChange(data, checked) {
+      this.form.access_id = checked.checkedKeys.concat(checked.halfCheckedKeys);
+    },
+
+    /*取消*/
+    cancelFunc() {
+      this.$router.back(-1);
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.basic-setting-content {
+}
+
+.product-add {
+  padding-bottom: 50px;
+}
+
+.img {
+  margin-top: 10px;
+}
+</style>
\ No newline at end of file
diff --git a/shop_vue/src/views/plus/region/auth/role/edit.vue b/shop_vue/src/views/plus/region/auth/role/edit.vue
new file mode 100644
index 0000000..c376516
--- /dev/null
+++ b/shop_vue/src/views/plus/region/auth/role/edit.vue
@@ -0,0 +1,228 @@
+<template>
+  <!--
+        作者:参考 auth/role/edit
+        时间:2026-01-21
+        描述:区域代理商-角色管理-编辑角色
+    -->
+  <div v-loading="loading">
+    <!--form表单-->
+    <el-form size="small" ref="form" :model="form" :rules="formRules" label-width="180px">
+      <!--编辑角色-->
+      <div class="common-form">编辑角色</div>
+
+      <el-form-item label="角色名称:" prop="role_name">
+        <el-input v-model="form.role_name" placeholder="请输入角色名称" class="max-w460"></el-input>
+      </el-form-item>
+
+      <el-form-item label="权限列表:" v-model="form.access_id">
+        <el-tree
+          :data="treeData"
+          show-checkbox
+          node-key="access_id"
+          :default-expand-all="true"
+          :default-checked-keys="select_menu"
+          :props="defaultProps"
+          @check="handleCheckChange"
+        ></el-tree>
+      </el-form-item>
+
+      <el-form-item label="排序:"><el-input type="number" v-model="form.sort" placeholder="请输入排序数字,数字越小越靠前" class="max-w460"></el-input></el-form-item>
+
+      <!--提交-->
+      <div class="common-button-wrapper">
+        <el-button size="small" type="info" @click="cancelFunc">取消</el-button>
+        <el-button type="primary" size="small" @click="onSubmit" :loading="loading">提交</el-button>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import PlusApi from '@/api/plus/region.js';
+
+export default {
+  data() {
+    return {
+      /*是否正在加载*/
+      loading:true,
+      /*表单数据对象*/
+      form: {
+        access_id: [],
+      },
+      data: [], // 原始数据
+      treeData: [], // 树形结构数据
+      /*角色列表*/
+      roleList: [],
+      /*权限选中*/
+      select_menu: [],
+      /*权限树菜单重新自定义字段*/
+      defaultProps: {
+        children: 'children',
+        label: 'name'
+      },
+      role_id: 0,
+      /*form验证*/
+      formRules: {
+        role_name: [
+          {
+            required: true,
+            message: '请输入角色名称',
+            trigger: 'blur'
+          }
+        ],
+        sort: [
+          {
+            required: true,
+            message: '请输入排序',
+            trigger: 'blur'
+          }
+        ]
+      },
+    };
+  },
+  created() {
+    this.role_id = this.$route.query.role_id;
+    /*获取数据*/
+    this.getData();
+  },
+  methods: {
+    /*修改角色*/
+    onSubmit() {
+      let self = this;
+      let form = self.form;
+      self.$refs.form.validate(valid => {
+        if (valid) {
+          self.loading = true;
+          PlusApi.regionRoleEdit({
+            role_id: self.role_id,
+            params: JSON.stringify(form)
+          }, true)
+            .then(data => {
+              self.loading = false;
+              self.$message({
+                message: '修改成功',
+                type: 'success'
+              });
+              self.$router.push('/plus/region/auth/role/index');
+            })
+            .catch(error => {
+              self.loading = false;
+            });
+        }
+      });
+    },
+
+    /*获取所有的数据*/
+    getData() {
+      let self = this;
+      PlusApi.regionRoleEditInfo({
+        role_id: self.role_id
+      })
+        .then(data => {
+          self.treeData = data.data.accessList;
+          //self.treeData = self.buildTree(self.data); // 构建树形结构
+          self.select_menu = data.data.select_menu;
+          self.form = data.data.model;
+          self.roleList = data.data.roleList;
+
+          if (self.form.parent_id == 0) {
+            self.form.parent_id = 0 + '';
+          }
+          self.loading = false;
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    // 将扁平化数据转换为树形结构
+    buildTree(data) {
+      if (!data || !Array.isArray(data)) {
+        return [];
+      }
+
+      // 创建映射表
+      const map = {};
+      const roots = [];
+
+      // 首先创建映射
+      for (let i = 0; i < data.length; i++) {
+        map[data[i].access_id] = i;
+        // 初始化children数组
+        data[i].children = [];
+      }
+
+      // 然后建立父子关系
+      for (let i = 0; i < data.length; i++) {
+        const node = data[i];
+        if (node.parent_id === 0 || node.parent_id === '0') {
+          // 如果parent_id为0,则为根节点
+          roots.push(node);
+        } else {
+          // 查找父节点
+          const parentId = node.parent_id;
+          if (map.hasOwnProperty(parentId)) {
+            // 将当前节点添加到其父节点的children数组中
+            data[map[parentId]].children.push(node);
+          } else {
+            // 如果找不到父节点,也作为根节点处理
+            roots.push(node);
+          }
+        }
+      }
+
+      return roots;
+    },
+
+    /*清除数据*/
+    clearData(list, authlist) {
+      let total = 0;
+      let leng = list.length;
+      for (let i = 0; i < leng; i++) {
+        let item = list[i];
+        if (item.children != null && item.children.length > 0) {
+          let flag = this.clearData(item.children, authlist);
+          if (!flag) {
+            let _index = authlist.indexOf(item.access_id);
+            if (_index >= 0) {
+              authlist.splice(_index, 1);
+            }
+          }
+        }
+        if (authlist.indexOf(item.access_id) != -1) {
+          total++;
+        }
+      }
+      if (total < leng) {
+        return false;
+      } else {
+        return true;
+      }
+    },
+
+    /*监听选中*/
+    handleCheckChange(data, checked) {
+      this.form.access_id = checked.checkedKeys.concat(checked.halfCheckedKeys);
+    },
+
+    /*取消*/
+    cancelFunc() {
+      this.$router.back(-1);
+    }
+
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.basic-setting-content {
+}
+
+.product-add {
+  padding-bottom: 50px;
+}
+
+.img {
+  margin-top: 10px;
+}
+</style>
diff --git a/shop_vue/src/views/plus/region/auth/user/Admin.vue b/shop_vue/src/views/plus/region/auth/user/Admin.vue
new file mode 100644
index 0000000..93cf54a
--- /dev/null
+++ b/shop_vue/src/views/plus/region/auth/user/Admin.vue
@@ -0,0 +1,203 @@
+<template>
+  <!--
+        作者:参考 auth/user
+        时间:2026-01-20
+        描述:区域代理商-管理员列表
+    -->
+  <div class="user">
+    <!--添加管理员-->
+    <div class="common-level-rail">
+      <el-button size="small" type="primary" icon="el-icon-plus" @click="addClick" v-auth="'/plus/region/user/admin/add'">添加管理员</el-button>
+    </div>
+
+    <!--内容-->
+    <div class="product-content">
+      <div class="table-wrap">
+        <el-table size="small" :data="tableData" border style="width: 100%" v-loading="loading">
+          <el-table-column prop="region_user_id" label="管理员ID"></el-table-column>
+          <el-table-column prop="user_name" label="用户名"></el-table-column>
+          <el-table-column prop="role.role_name" label="所属角色">
+            <template slot-scope="scope">
+              <div>
+                <span class="mr10 green" v-for="(item, index) in scope.row.roles" :key="index">{{ item.role.role_name }}</span>
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column prop="real_name" label="姓名"></el-table-column>
+          <el-table-column prop="create_time" label="添加时间"></el-table-column>
+          <el-table-column fixed="right" label="操作" width="90">
+            <template slot-scope="scope">
+              <el-button v-if="scope.row.is_super < 1" @click="editClick(scope.row)" type="text" size="small" v-auth="'/plus/region/user/admin/edit'">编辑</el-button>
+              <el-button v-if="scope.row.is_super < 1" @click="deleteClick(scope.row)" type="text" size="small" v-auth="'/plus/region/user/admin/delete'">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+
+      <!--分页-->
+      <div class="pagination">
+        <el-pagination
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+          background
+          :current-page="curPage"
+          :page-size="pageSize"
+          layout="total, prev, pager, next, jumper"
+          :total="totalDataNumber"
+        ></el-pagination>
+      </div>
+    </div>
+
+    <Add :open="open_add" :roleList="roleList" @close="closeAdd"></Add>
+
+    <Edit :open="open_edit" :roleList="roleList" :region_user_id="curModel.region_user_id"  @close="closeEdit"></Edit>
+
+  </div>
+</template>
+
+<script>
+import PlusApi from '@/api/plus/region.js';
+import Add from './dialog/Add.vue';
+import Edit from './dialog/Edit.vue';
+export default {
+  components: {
+    Add,
+    Edit
+  },
+  inject: ['reload'],
+  data() {
+    return {
+      /*是否加载完成*/
+      loading: true,
+      /*角色是否加载完成*/
+      role_loading:true,
+      /*列表数据*/
+      tableData: [],
+      /*一页多少条*/
+      pageSize: 20,
+      /*一共多少条数据*/
+      totalDataNumber: 0,
+      /*当前是第几页*/
+      curPage: 1,
+      /*横向表单数据模型*/
+      formInline: {
+        user: '',
+        region: ''
+      },
+      /*是否打开添加弹窗*/
+      open_add: false,
+      /*是否打开编辑弹窗*/
+      open_edit: false,
+      /*当前编辑的对象*/
+      curModel: {},
+      /*角色列表*/
+      roleList:[]
+    };
+  },
+  created() {
+    /*获取列表*/
+    this.getTableList();
+  },
+  methods: {
+    /*选择第几页*/
+    handleCurrentChange(val) {
+      let self = this;
+      self.curPage = val;
+      self.loading = true;
+      self.getTableList();
+    },
+
+    /*每页多少条*/
+    handleSizeChange(val) {
+      this.curPage = 1;
+      this.pageSize = val;
+      this.getTableList();
+    },
+
+    /*获取列表*/
+    getTableList() {
+      let self = this;
+      let Params = {};
+      Params.page = self.curPage;
+      Params.list_rows = self.pageSize;
+      PlusApi.regionAdminList(Params, true)
+        .then(data => {
+          self.loading = false;
+          self.role_loading = false;
+          self.roleList = data.data.roleList;
+          self.tableData = data.data.list.data;
+          self.totalDataNumber = data.data.list.total;
+        })
+        .catch(error => {});
+    },
+
+    /*打开添加*/
+    addClick() {
+      if(!this.role_loading){
+         this.open_add=true;
+      }
+    },
+
+    /*关闭添加*/
+    closeAdd(e){
+      this.open_add=false;
+      if(e.type=='success'){
+        this.getTableList();
+      }
+    },
+
+    /*打开编辑*/
+    editClick(row) {
+      this.curModel=row;
+      this.open_edit=true;
+    },
+
+    /*关闭添加*/
+    closeEdit(e){
+      this.open_edit=false;
+      if(e.type=='success'){
+        this.getTableList();
+      }
+    },
+
+    /*删除*/
+    deleteClick(row) {
+      let self = this;
+      self
+        .$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        .then(() => {
+          self.loading = true;
+          PlusApi.regionAdminDelete(
+            {
+              shop_user_id: row.shop_user_id
+            },
+            true
+          )
+            .then(data => {
+              self.loading = false;
+              if (data.code == 1) {
+                self.$message({
+                  message: '恭喜你,该管理员删除成功',
+                  type: 'success'
+                });
+                //刷新页面
+                self.getTableList();
+              } else {
+                self.loading = false;
+              }
+            })
+            .catch(error => {
+              self.loading = false;
+            });
+        })
+        .catch(() => {});
+    }
+  }
+};
+</script>
+
+<style></style>
diff --git a/shop_vue/src/views/plus/region/auth/user/dialog/Add.vue b/shop_vue/src/views/plus/region/auth/user/dialog/Add.vue
new file mode 100644
index 0000000..94cd62b
--- /dev/null
+++ b/shop_vue/src/views/plus/region/auth/user/dialog/Add.vue
@@ -0,0 +1,130 @@
+<template>
+  <!--
+        作者:参考 auth/user/dialog/Add.vue
+        时间:2026-01-20
+        描述:区域代理商-管理员列表-添加管理员
+    -->
+  <el-dialog title="添加管理员" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false">
+    <!--form表单-->
+    <el-form size="small" ref="form" :model="form" :rules="formRules" :label-width="formLabelWidth">
+      <el-form-item label="用户名" prop="user_name"><el-input v-model="form.user_name" placeholder="请输入用户名"></el-input></el-form-item>
+      <el-form-item label="所属角色" prop="role_id">
+        <el-select v-model="form.role_id" :multiple="true">
+          <el-option v-for="item in roleList" :value="item.role_id" :key="item.role_id" :label="item.role_name"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="登录密码" prop="password"><el-input v-model="form.password" placeholder="请输入登录密码" type="password"></el-input></el-form-item>
+      <el-form-item label="确认密码" prop="confirm_password"><el-input v-model="form.confirm_password" placeholder="请输入确认密码" type="password"></el-input></el-form-item>
+      <el-form-item label="姓名" prop="real_name"><el-input v-model="form.real_name"></el-input></el-form-item>
+    </el-form>
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="dialogVisible = false">取 消</el-button>
+      <el-button type="primary" @click="onSubmit" :loading="loading">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import PlusApi from '@/api/plus/region.js';
+export default {
+  data() {
+    return {
+      /*左边长度*/
+      formLabelWidth: '120px',
+      /*是否显示*/
+      loading: false,
+      /*是否显示*/
+      dialogVisible: false,
+      /*form表单对象*/
+      form: {
+        user_name: '',
+        access_id: []
+      },
+      /*form验证*/
+      formRules: {
+        user_name: [
+          {
+            required: true,
+            message: ' ',
+            trigger: 'blur'
+          }
+        ],
+        role_id: [
+          {
+            required: true,
+            message: ' ',
+            trigger: 'blur'
+          }
+        ],
+        password: [
+          {
+            required: true,
+            message: ' ',
+            trigger: 'blur'
+          }
+        ],
+        confirm_password: [
+          {
+            required: true,
+            message: ' ',
+            trigger: 'blur'
+          }
+        ],
+        real_name: [
+          {
+            required: true,
+            message: ' ',
+            trigger: 'blur'
+          }
+        ]
+      }
+    };
+  },
+  props: ['open', 'roleList'],
+  watch: {
+    open: function(n, o) {
+      if (n != o) {
+        this.dialogVisible = this.open;
+      }
+    }
+  },
+  created() {},
+  methods: {
+    /*添加*/
+    onSubmit() {
+      let self = this;
+      self.loading = true;
+      let params = self.form;
+      PlusApi.regionAdminAdd(params, true)
+        .then(data => {
+          self.loading = false;
+          self.$message({
+            message: '恭喜你,添加成功',
+            type: 'success'
+          });
+          self.dialogFormVisible(true);
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    /*关闭弹窗*/
+    dialogFormVisible(e) {
+      if (e) {
+        this.$emit('close', {
+          type: 'success',
+          openDialog: false
+        });
+      } else {
+        this.$emit('close', {
+          type: 'error',
+          openDialog: false
+        });
+      }
+    }
+  }
+};
+</script>
+
+<style></style>
diff --git a/shop_vue/src/views/plus/region/auth/user/dialog/Edit.vue b/shop_vue/src/views/plus/region/auth/user/dialog/Edit.vue
new file mode 100644
index 0000000..18f289c
--- /dev/null
+++ b/shop_vue/src/views/plus/region/auth/user/dialog/Edit.vue
@@ -0,0 +1,154 @@
+<template>
+  <!--
+        作者:参考 auth/user/dialog/Edit.vue
+        时间:2026-01-20
+        描述:区域代理商-管理员列表-修改管理员
+    -->
+  <el-dialog title="修改管理员" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false">
+    <!--form表单-->
+    <el-form size="small" ref="form" :model="form" :rules="formRules" :label-width="formLabelWidth" v-loading="loading">
+      <el-form-item label="用户名" prop="user_name"><el-input v-model="form.user_name" placeholder="请输入用户名"></el-input></el-form-item>
+      <el-form-item label="所属角色" prop="access_id">
+        <el-select v-model="form.access_id" :multiple="true">
+          <el-option v-for="item in roleList" :value="item.role_id" :key="item.role_id" :label="item.role_name_h1"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="登录密码" prop="password"><el-input v-model="form.password" placeholder="请输入登录密码" type="password"></el-input></el-form-item>
+      <el-form-item label="确认密码" prop="confirm_password"><el-input v-model="form.confirm_password" placeholder="请输入确认密码" type="password"></el-input></el-form-item>
+      <el-form-item label="姓名" prop="real_name"><el-input v-model="form.real_name"></el-input></el-form-item>
+    </el-form>
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="dialogVisible = false">取 消</el-button>
+      <el-button type="primary" @click="onSubmit" :loading="loading">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import PlusApi from '@/api/plus/region.js';
+export default {
+  data() {
+    return {
+      /*左边长度*/
+      formLabelWidth: '120px',
+      /*是否显示*/
+      loading: false,
+      /*是否显示*/
+      dialogVisible: false,
+      /*form表单对象*/
+      form: {
+        confirm_password:'',
+        access_id:[]
+      },
+      /*当前角色*/
+      access_id: [],
+      /*角色对象*/
+      roleList: [],
+      /*form验证*/
+      formRules: {
+        user_name: [
+          {
+            required: true,
+            message: ' ',
+            trigger: 'blur'
+          }
+        ],
+        access_id: [
+          {
+            required: true,
+            message: ' ',
+            trigger: 'blur'
+          }
+        ],
+        password: [
+          {
+            required: true,
+            message: ' ',
+            trigger: 'blur'
+          }
+        ],
+        confirm_password: [
+          {
+            required: true,
+            message: ' ',
+            trigger: 'blur'
+          }
+        ],
+        real_name: [
+          {
+            required: true,
+            message: ' ',
+            trigger: 'blur'
+          }
+        ]
+      }
+    };
+  },
+  props: ['open','region_user_id'],
+  watch: {
+    open: function(n, o) {
+      if (n != o) {
+        this.dialogVisible = this.open;
+        this.getData();
+      }
+    }
+  },
+  created() {},
+  methods: {
+
+    /*获取数据*/
+    getData() {
+      let self = this;
+      PlusApi.regionAdminEditInfo({
+        region_user_id: this.region_user_id
+        }).then(res => {
+          self.loading = false;
+          self.roleList = res.data.roleList;
+          let obj=res.data.info;
+          obj.access_id = res.data.role_arr;
+          obj.password = '';
+          self.form=obj;
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    /*修改*/
+    onSubmit() {
+      let self = this;
+      self.loading = true;
+      let params = self.form;
+      PlusApi.regionAdminEdit(params, true)
+        .then(data => {
+          self.loading = false;
+          self.$message({
+            message: '恭喜你,修改成功',
+            type: 'success'
+          });
+          self.dialogFormVisible(true);
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    /*关闭弹窗*/
+    dialogFormVisible(e) {
+      if (e) {
+        this.$emit('close', {
+          type: 'success',
+          openDialog: false
+        });
+      } else {
+        this.$emit('close', {
+          type: 'error',
+          openDialog: false
+        });
+      }
+    }
+  }
+};
+</script>
+
+<style></style>
diff --git a/shop_vue/src/views/plus/region/role/add.vue b/shop_vue/src/views/plus/region/role/add.vue
new file mode 100644
index 0000000..ee75eee
--- /dev/null
+++ b/shop_vue/src/views/plus/region/role/add.vue
@@ -0,0 +1,121 @@
+<template>
+  <!--
+        作者:参考 auth/role
+        时间:2026-01-20
+        描述:区域代理商-角色管理-添加角色
+    -->
+  <div v-loading="loading">
+    <!--form表单-->
+    <el-form size="small" ref="form" :model="form" label-width="180px">
+      <!--添加门店-->
+      <div class="common-form">添加角色</div>
+
+      <el-form-item label="角色名称:" prop="role_name" :rules="[{ required: true, message: ' ' }]">
+        <el-input v-model="form.role_name" placeholder="请输入角色名称" class="max-w460"></el-input>
+      </el-form-item>
+
+      <el-form-item label="权限列表:" v-model="form.access_id">
+        <el-tree :data="data" show-checkbox node-key="access_id" :default-expand-all="true" :default-checked-keys="[]" :props="defaultProps" @check="handleCheckChange"></el-tree>
+      </el-form-item>
+
+      <el-form-item label="排序:"><el-input type="number" v-model="form.sort" placeholder="请输入排序" class="max-w460"></el-input></el-form-item>
+
+      <!--提交-->
+      <div class="common-button-wrapper">
+        <el-button size="small" type="info" @click="cancelFunc">取消</el-button>
+        <el-button type="primary" size="small" @click="onSubmit" :loading="loading">提交</el-button>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import PlusApi from '@/api/plus/region.js';
+
+export default {
+  data() {
+    return {
+      /*是否正在加载*/
+      loading:true,
+      /*表单数据对象*/
+      form: {
+        access_id: [],
+        sort: 1
+      },
+      data: [],
+      roleList: [],
+      defaultProps: {
+        children: 'children',
+        label: 'name'
+      }
+    };
+  },
+  created() {
+    /*获取列表*/
+    this.getData();
+  },
+  methods: {
+    /*添加角色*/
+    onSubmit() {
+      let self = this;
+      let form = self.form;
+      self.$refs.form.validate(valid => {
+        if (valid) {
+          self.loading = true;
+          PlusApi.regionRoleAdd({
+            params: JSON.stringify(form)
+          }, true)
+            .then(data => {
+              self.loading = false;
+              self.$message({
+                message: '添加成功',
+                type: 'success'
+              });
+              self.$router.push('/plus/region/role/index');
+            })
+            .catch(error => {
+              self.loading = false;
+            });
+        }
+      });
+    },
+
+    /*获取数据*/
+    getData() {
+      let self = this;
+      PlusApi.regionRoleAddInfo()
+        .then(data => {
+          self.data = data.data.menu;
+          self.roleList = data.data.roleList;
+           self.loading = false;
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    //监听选中
+    handleCheckChange(data, checked) {
+      this.form.access_id = checked.checkedKeys.concat(checked.halfCheckedKeys);
+    },
+
+    /*取消*/
+    cancelFunc() {
+      this.$router.back(-1);
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.basic-setting-content {
+}
+
+.product-add {
+  padding-bottom: 50px;
+}
+
+.img {
+  margin-top: 10px;
+}
+</style>
diff --git a/shop_vue/src/views/plus/region/role/edit.vue b/shop_vue/src/views/plus/region/role/edit.vue
new file mode 100644
index 0000000..3aa1284
--- /dev/null
+++ b/shop_vue/src/views/plus/region/role/edit.vue
@@ -0,0 +1,170 @@
+<template>
+  <!--
+        作者:参考 auth/role
+        时间:2026-01-20
+        描述:区域代理商-角色管理-编辑角色
+    -->
+  <div v-loading="loading">
+    <!--form表单-->
+    <el-form size="small" ref="form" :model="form" label-width="180px">
+      <!--编辑角色-->
+      <div class="common-form">编辑角色</div>
+
+      <el-form-item label="角色名称:" prop="role_name" :rules="[{ required: true, message: ' ' }]">
+        <el-input v-model="form.role_name" placeholder="请输入角色名称" class="max-w460"></el-input>
+      </el-form-item>
+      
+      <el-form-item label="权限列表:" v-model="form.access_id">
+        <el-tree
+          :data="data"
+          show-checkbox
+          node-key="access_id"
+          :default-expand-all="true"
+          :default-checked-keys="select_menu"
+          :props="defaultProps"
+          @check="handleCheckChange"
+        ></el-tree>
+      </el-form-item>
+
+      <el-form-item label="排序:"><el-input type="number" v-model="form.sort" placeholder="请输入排序" class="max-w460"></el-input></el-form-item>
+
+      <!--提交-->
+      <div class="common-button-wrapper">
+        <el-button size="small" type="info" @click="cancelFunc">取消</el-button>
+        <el-button type="primary" size="small" @click="onSubmit" :loading="loading">提交</el-button>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import PlusApi from '@/api/plus/region.js';
+
+export default {
+  data() {
+    return {
+      /*是否正在加载*/
+      loading:true,
+      /*表单数据对象*/
+      form: {
+        access_id: [],
+      },
+      data: [],
+      /*角色列表*/
+      roleList: [],
+      /*权限选中*/
+      select_menu: [],
+      /*权限树菜单重新自定义字段*/
+      defaultProps: {
+        children: 'children',
+        label: 'name'
+      },
+      role_id: 0
+    };
+  },
+  created() {
+    this.role_id = this.$route.query.role_id;
+    /*获取列表*/
+    this.getData();
+  },
+  methods: {
+    /*修改角色*/
+    onSubmit() {
+      let self = this;
+      let form = self.form;
+      self.$refs.form.validate(valid => {
+        if (valid) {
+          self.loading = true;
+          PlusApi.regionRoleEdit({
+            role_id: self.role_id,
+            params: JSON.stringify(form)
+          }, true)
+            .then(data => {
+              self.loading = false;
+              self.$message({
+                message: '修改成功',
+                type: 'success'
+              });
+              self.$router.push('/plus/region/role/index');
+            })
+            .catch(error => {
+              self.loading = false;
+            });
+        }
+      });
+    },
+
+    /*获取所有的数据*/
+    getData() {
+      let self = this;
+      PlusApi.regionRoleEditInfo({
+        role_id: self.role_id
+      })
+        .then(data => {
+          let obj = self.clearData(data.data.menu, data.data.select_menu);
+          self.select_menu = data.data.select_menu;
+          self.form = data.data.model;
+          self.roleList = data.data.roleList;
+          self.data = data.data.menu;
+          if (self.form.parent_id == 0) {
+            self.form.parent_id = 0 + '';
+          }
+          self.loading = false;
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    /*清除数据*/
+    clearData(list, authlist) {
+      let total = 0;
+      let leng = list.length;
+      for (let i = 0; i < leng; i++) {
+        let item = list[i];
+        if (item.children != null) {
+          let flag = this.clearData(item.children, authlist);
+          if (!flag) {
+            let _index = authlist.indexOf(item.access_id);
+            if (_index >= 0) {
+              authlist.splice(_index, 1);
+            }
+          }
+        }
+        if (authlist.indexOf(item.access_id) != -1) {
+          total++;
+        }
+      }
+      if (total < leng) {
+        return false;
+      } else {
+        return true;
+      }
+    },
+
+    /*监听选中*/
+    handleCheckChange(data, checked) {
+      this.form.access_id = checked.checkedKeys.concat(checked.halfCheckedKeys);
+    },
+
+    /*取消*/
+    cancelFunc() {
+      this.$router.back(-1);
+    }
+
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.basic-setting-content {
+}
+
+.product-add {
+  padding-bottom: 50px;
+}
+
+.img {
+  margin-top: 10px;
+}
+</style>
diff --git a/shop_vue/src/views/plus/region/role/index.vue b/shop_vue/src/views/plus/region/role/index.vue
new file mode 100644
index 0000000..857b1eb
--- /dev/null
+++ b/shop_vue/src/views/plus/region/role/index.vue
@@ -0,0 +1,135 @@
+<template>
+  <!--
+        作者:参考 auth/role
+        时间:2026-01-20
+        描述:区域代理商-角色管理
+    -->
+  <div class="user">
+    <div class="common-level-rail">
+      <el-button size="small" type="primary" icon="el-icon-plus" @click="addClick" v-auth="'/plus/region/role/add'">添加角色</el-button>
+    </div>
+
+    <!--内容-->
+    <div class="product-content">
+      <div class="table-wrap">
+        <el-table size="small" :data="tableData" border style="width: 100%" v-loading="loading">
+          <el-table-column prop="role_id" label="角色ID"></el-table-column>
+          <el-table-column prop="role_name_h1" label="角色名称"></el-table-column>
+          <el-table-column prop="sort" label="排序"></el-table-column>
+          <el-table-column prop="create_time" label="添加时间"></el-table-column>
+          <el-table-column fixed="right" label="操作" width="90">
+            <template slot-scope="scope">
+              <el-button @click="editClick(scope.row)" type="text" size="small" v-auth="'/plus/region/role/edit'">编辑</el-button>
+              <el-button @click="deleteClick(scope.row)" type="text" size="small" v-auth="'/plus/region/role/delete'">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import PlusApi from '@/api/plus/region.js';
+export default {
+  components: {},
+  inject: ['reload'],
+  data() {
+    return {
+      /*是否加载完成*/
+      loading: true,
+      /*列表数据*/
+      tableData: [],
+      /*横向表单数据模型*/
+      formInline: {
+        user: '',
+        region: ''
+      },
+      /*是否打开添加弹窗*/
+      open_add: false,
+      /*是否打开编辑弹窗*/
+      open_edit: false,
+      /*当前编辑的对象*/
+      userModel: {}
+    };
+  },
+  created() {
+    /*获取列表*/
+    this.getTableList();
+  },
+  methods: {
+    /*获取列表*/
+    getTableList() {
+      let self = this;
+      let Params = {};
+      PlusApi.regionRoleList(Params, true)
+        .then(data => {
+          self.loading = false;
+          self.tableData = data.data.list;
+        })
+        .catch(error => {
+          self.loading = false;
+        });
+    },
+
+    /*打开添加*/
+    addClick() {
+      this.$router.push('/plus/region/role/add');
+    },
+
+    /*打开编辑*/
+    editClick(row) {
+      let self = this;
+      this.$router.push({
+        path: '/plus/region/role/edit',
+        query: {
+          role_id: row.role_id
+        }
+      });
+    },
+
+    /*刷新页面*/
+    refresh() {
+      this.reload();
+    },
+
+    /*删除*/
+    deleteClick(row) {
+      let self = this;
+      self
+        .$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        .then(() => {
+          self.loading = true;
+          PlusApi.regionRoleDelete(
+            {
+              role_id: row.role_id
+            },
+            true
+          )
+            .then(data => {
+              self.loading = false;
+              if (data.code == 1) {
+                self.$message({
+                  message: '恭喜你,该角色删除成功',
+                  type: 'success'
+                });
+                self.getTableList();
+              } else {
+                self.loading = false;
+              }
+            })
+            .catch(error => {
+              self.loading = false;
+            });
+        })
+        .catch(() => {});
+    }
+  }
+};
+</script>
+
+<style></style>
diff --git a/shop_vue/src/views/plus/region/user/dialog/Add.vue b/shop_vue/src/views/plus/region/user/dialog/Add.vue
new file mode 100644
index 0000000..847988d
--- /dev/null
+++ b/shop_vue/src/views/plus/region/user/dialog/Add.vue
@@ -0,0 +1,305 @@
+<template>
+  <!--
+      	作者:luoyiming
+      	时间:2020-06-01
+      	描述:插件中心-区域代理-添加区域代理
+      -->
+  <el-dialog title="添加区域代理" :visible.sync="dialogVisible" @close="cancelFunc" :close-on-click-modal="false" :close-on-press-escape="false" width="500px">
+    <el-form :model="formData" :rules="rules" ref="formData" label-width="100px">
+      <el-form-item label="绑定用户" prop="user_id" :rules="[{required: true,message: '请选择用户'}]">
+        <el-row>
+          <el-button icon="el-icon-picture-outline" @click="userClick()">选择用户</el-button>
+          <div v-if="formData.user_id!=0" class="img">
+            <img :src="user_info.avatarUrl" width="100" height="100" />
+            <div style="margin-top: 5px;">{{ user_info.nickName }}</div>
+          </div>
+        </el-row>
+      </el-form-item>
+      <el-form-item label="姓名" prop="real_name">
+        <el-input type="text" v-model="formData.real_name" autocomplete="off" placeholder="请输入真实姓名"></el-input>
+      </el-form-item>
+      <el-form-item label="手机号" prop="mobile">
+        <el-input type="text" v-model="formData.mobile" autocomplete="off" placeholder="请输入手机号"></el-input>
+      </el-form-item>
+      <el-form-item label="代理级别" prop="region_level">
+        <el-select v-model="formData.region_level" placeholder="请选择代理级别" @change="handleLevelChange">
+          <el-option label="省级代理" :value="1"></el-option>
+          <el-option label="市级代理" :value="2"></el-option>
+          <el-option label="区/县级代理" :value="3"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="省份" prop="province_id">
+        <el-select v-model="formData.province_id" placeholder="请选择省份" @change="handleProvinceChange">
+          <el-option v-for="item in provinceList" :key="item.id" :label="item.name" :value="item.id"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="城市" prop="city_id" v-if="formData.region_level >= 2">
+        <el-select v-model="formData.city_id" placeholder="请选择城市" @change="handleCityChange" :disabled="!formData.province_id">
+          <el-option v-for="item in cityList" :key="item.id" :label="item.name" :value="item.id"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="区/县" prop="area_id" v-if="formData.region_level == 3">
+        <el-select v-model="formData.area_id" placeholder="请选择区/县" :disabled="!formData.city_id">
+          <el-option v-for="item in areaList" :key="item.id" :label="item.name" :value="item.id"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="代理等级" prop="grade_id">
+        <el-select v-model="formData.grade_id" placeholder="请选择代理等级">
+          <el-option label="默认等级" :value="0"></el-option>
+          <el-option v-for="(item,index) in gradeList" :key="index" :label="item.name" :value="item.grade_id"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="登录账号" prop="user_name">
+        <el-input type="text" v-model="formData.user_name" autocomplete="off" placeholder="请输入登录账号"></el-input>
+      </el-form-item>
+      <el-form-item label="登录密码" prop="password">
+        <el-input type="password" v-model="formData.password" autocomplete="off" placeholder="请输入登录密码"></el-input>
+      </el-form-item>
+    </el-form>
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="cancelFunc">取 消</el-button>
+      <el-button type="primary" @click="confirmFunc" :loading="loading">确 定</el-button>
+    </div>
+    <!--选择用户组件-->
+    <GetUser :is_open="open_user" :is_radio="true" @close="closeDialogFunc"></GetUser>
+  </el-dialog>
+</template>
+
+<script>
+import PlusApi from '@/api/plus/region.js';
+import DataApi from '@/api/data.js';
+import GetUser from '@/components/user/GetUser.vue';
+export default {
+  components: {
+    GetUser
+  },
+  data() {
+    return {
+      /*是否显示*/
+      dialogVisible: false,
+      /*表单数据模型*/
+      formData: {
+        user_id: 0,
+        real_name: '',
+        mobile: '',
+        region_level: 1,
+        province_id: '',
+        city_id: '',
+        area_id: '',
+        grade_id: 0,
+        user_name: '',
+        password: ''
+      },
+      /*表单验证规则*/
+      rules: {
+        user_id: [
+          { required: true, message: '请选择用户', trigger: 'change' }
+        ],
+        real_name: [
+          { required: true, message: '请输入真实姓名', trigger: 'blur' }
+        ],
+        mobile: [
+          { required: true, message: '请输入手机号', trigger: 'blur' },
+          { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
+        ],
+        region_level: [
+          { required: true, message: '请选择代理级别', trigger: 'change' }
+        ],
+        province_id: [
+          { required: true, message: '请选择省份', trigger: 'change' }
+        ],
+        city_id: [
+          { required: true, message: '请选择城市', trigger: 'change' }
+        ],
+        area_id: [
+          { required: true, message: '请选择区/县', trigger: 'change' }
+        ],
+        user_name: [
+          { required: true, message: '请输入登录账号', trigger: 'blur' }
+        ],
+        password: [
+          { required: true, message: '请输入登录密码', trigger: 'blur' },
+          { min: 6, message: '密码长度不能少于6位', trigger: 'blur' }
+        ]
+      },
+      /*地区数据*/
+      regionData: [],
+      /*等级列表*/
+      gradeList: [],
+      /*加载状态*/
+      loading: false,
+      /*是否打开选择用户弹窗*/
+      open_user: false,
+      /*选中的用户信息*/
+      user_info: {}
+    };
+  },
+  props: {
+    open_add: Boolean
+  },
+  watch: {
+    open_add: function(n, o) {
+      if (n != o) {
+        this.dialogVisible = this.open_add;
+        if (n) {
+          this.resetForm();
+          this.getGradeList();
+          this.getRegionData();
+        }
+      }
+    }
+  },
+  created() {
+  },
+  computed: {
+    /*获取省份列表*/
+    provinceList() {
+      return Object.values(this.regionData).filter(item => item.level === 1);
+    },
+    /*获取城市列表*/
+    cityList() {
+      if (this.formData.province_id && this.regionData[this.formData.province_id]) {
+        const provinceData = this.regionData[this.formData.province_id];
+        if (provinceData.city) {
+          return Object.values(provinceData.city);
+        }
+      }
+      return [];
+    },
+    /*获取区/县列表*/
+    areaList() {
+      if (this.formData.city_id && this.formData.province_id && this.regionData[this.formData.province_id]) {
+        const provinceData = this.regionData[this.formData.province_id];
+        if (provinceData.city && provinceData.city[this.formData.city_id]) {
+          const cityData = provinceData.city[this.formData.city_id];
+          if (cityData.region) {
+            return Object.values(cityData.region);
+          }
+        }
+      }
+      return [];
+    }
+  },
+  methods: {
+    /*获取等级列表*/
+    getGradeList(){
+      let self = this;
+      PlusApi.toRegionUserEdit({}, true)
+        .then(res => {
+          self.gradeList = res.data.gradeList;
+        })
+        .catch(() => {});
+    },
+
+    /*获取地区数据*/
+    getRegionData(){
+      let self = this;
+      DataApi.getRegion({}, true)
+        .then(res => {
+          self.regionData = res.data.regionData;
+        })
+        .catch(() => {});
+    },
+
+    /*省份改变*/
+    handleProvinceChange(){
+      this.formData.city_id = '';
+      this.formData.area_id = '';
+    },
+
+    /*城市改变*/
+    handleCityChange(){
+      this.formData.area_id = '';
+    },
+
+    /*代理级别改变*/
+    handleLevelChange(val){
+      if(val == 1){
+        this.formData.city_id = '';
+        this.formData.area_id = '';
+        this.$refs.formData.clearValidate(['city_id', 'area_id']);
+      }else if(val == 2){
+        this.formData.area_id = '';
+        this.$refs.formData.clearValidate(['area_id']);
+      }
+    },
+
+    /*确认添加*/
+    confirmFunc() {
+      let self = this;
+      this.$refs.formData.validate((valid) => {
+        if (valid) {
+          self.loading = true;
+          PlusApi.addRegionUser(self.formData, true)
+            .then(() => {
+              self.loading = false;
+              self.$message({
+                message: '添加成功',
+                type: 'success'
+              });
+              self.cancelFunc(true);
+            })
+            .catch(() => {
+              self.loading = false;
+            });
+        } else {
+          return false;
+        }
+      });
+    },
+
+    /*重置表单*/
+    resetForm(){
+      this.formData = {
+        user_id: 0,
+        real_name: '',
+        mobile: '',
+        region_level: 1,
+        province_id: '',
+        city_id: '',
+        area_id: '',
+        grade_id: 0,
+        user_name: '',
+        password: ''
+      };
+      this.user_info = {};
+      if(this.$refs.formData){
+        this.$refs.formData.resetFields();
+      }
+    },
+
+    /*打开选择用户弹窗*/
+    userClick() {
+      this.open_user = true;
+    },
+
+    /*关闭获取用户弹窗*/
+    closeDialogFunc(e) {
+      if (e.type != 'error') {
+        // e.params可能是单个对象(单选模式)或数组(多选模式)
+        const user = Array.isArray(e.params) ? e.params[0] : e.params;
+        this.user_info = user;
+        this.formData.user_id = user.user_id;
+      }
+      this.open_user = false;
+    },
+
+    /*关闭弹窗*/
+    cancelFunc(e) {
+      let type = 'cancel';
+      if(e){
+        type = 'success';
+      }
+      this.$emit('close', {
+        type: type
+      });
+    }
+  }
+};
+</script>
+
+<style>
+.img {
+  margin-top: 10px;
+}
+</style>
diff --git a/shop_vue/static/UE/dialogs/spechars/spechars.js b/shop_vue/static/UE/dialogs/spechars/spechars.js
index f4c155e..fd5d7e3 100644
--- a/shop_vue/static/UE/dialogs/spechars/spechars.js
+++ b/shop_vue/static/UE/dialogs/spechars/spechars.js
@@ -6,7 +6,7 @@
  * To change this template use File | Settings | File Templates.
  */
 var charsContent = [
-    { name:"tsfh", title:lang.tsfh, content:toArray("、,。,·,ˉ,ˇ,¨,〃,々,—,~,‖,…,‘,’,“,”,〔,〕,〈,〉,《,》,「,」,『,』,〖,〗,【,】,±,×,÷,∶,∧,∨,∑,∏,∪,∩,∈,∷,√,⊥,∥,∠,⌒,⊙,∫,∮,≡,≌,≈,∽,∝,≠,≮,≯,≤,≥,∞,∵,∴,♂,♀,°,′,″,℃,$,¤,¢,£,‰,§,№,☆,★,○,●,◎,◇,◆,□,■,△,▲,※,→,←,↑,↓,〓,〡,〢,〣,〤,〥,〦,〧,〨,〩,㊣,㎎,㎏,㎜,㎝,㎞,㎡,㏄,㏎,㏑,㏒,㏕,︰,¬,¦,℡,ˊ,ˋ,˙,–,―,‥,‵,℅,℉,↖,↗,↘,↙,∕,∟,∣,≒,≦,≧,⊿,═,║,╒,╓,╔,╕,╖,╗,╘,╙,╚,╛,╜,╝,╞,╟,╠,╡,╢,╣,╤,╥,╦,╧,╨,╩,╪,╫,╬,╭,╮,╯,╰,╱,╲,╳,▁,▂,▃,▄,▅,▆,▇,�,█,▉,▊,▋,▌,▍,▎,▏,▓,▔,▕,▼,▽,◢,◣,◤,◥,☉,⊕,〒,〝,〞")},
+    { name:"tsfh", title:lang.tsfh, content:toArray("、,。,·,ˉ,ˇ,¨,〃,々,—,~,‖,…,‘,’,“,”,〔,〕,〈,〉,《,》,「,」,『,』,〖,〗,【,】,±,×,÷,∶,∧,∨,∑,∏,∪,∩,∈,∷,√,⊥,∥,∠,⌒,⊙,∫,∮,≡,≌,≈,∽,∝,≠,≮,≯,≤,≥,∞,∵,∴,♂,♀,°,′,″,℃,$,¤,¢,£,‰,§,№,☆,★,○,●,◎,◇,◆,□,■,△,▲,※,→,←,↑,↓,〓,〡,〢,〣,〤,〥,〦,〧,〨,〩,㊣,㎎,㎏,㎜,㎝,㎞,㎡,㏄,㏎,㏑,㏒,㏕,︰,¬,¦,℡,ˊ,ˋ,˙,–,―,‥,‵,℅,℉,↖,↗,↘,↙,∕,∟,∣,≒,≦,≧,⊿,═,║,╒,╓,╔,╕,╖,╗,╘,╙,╚,╛,╜,╝,╞,╟,╠,╡,╢,╣,╤,╥,╦,╧,╨,╩,╪,╫,╬,╭,╮,╯,╰,╱,╲,╳,▁,▂,▃,▄,▅,▆,▇,█,█,▉,▊,▋,▌,▍,▎,▏,▓,▔,▕,▼,▽,◢,◣,◤,◥,☉,⊕,〒,〝,〞")},
     { name:"lmsz", title:lang.lmsz, content:toArray("ⅰ,ⅱ,ⅲ,ⅳ,ⅴ,ⅵ,ⅶ,ⅷ,ⅸ,ⅹ,Ⅰ,Ⅱ,Ⅲ,Ⅳ,Ⅴ,Ⅵ,Ⅶ,Ⅷ,Ⅸ,Ⅹ,Ⅺ,Ⅻ")},
     { name:"szfh", title:lang.szfh, content:toArray("⒈,⒉,⒊,⒋,⒌,⒍,⒎,⒏,⒐,⒑,⒒,⒓,⒔,⒕,⒖,⒗,⒘,⒙,⒚,⒛,⑴,⑵,⑶,⑷,⑸,⑹,⑺,⑻,⑼,⑽,⑾,⑿,⒀,⒁,⒂,⒃,⒄,⒅,⒆,⒇,①,②,③,④,⑤,⑥,⑦,⑧,⑨,⑩,㈠,㈡,㈢,㈣,㈤,㈥,㈦,㈧,㈨,㈩")},
     { name:"rwfh", title:lang.rwfh, content:toArray("ぁ,あ,ぃ,い,ぅ,う,ぇ,え,ぉ,お,か,が,き,ぎ,く,ぐ,け,げ,こ,ご,さ,ざ,し,じ,す,ず,せ,ぜ,そ,ぞ,た,だ,ち,ぢ,っ,つ,づ,て,で,と,ど,な,に,ぬ,ね,の,は,ば,ぱ,ひ,び,ぴ,ふ,ぶ,ぷ,へ,べ,ぺ,ほ,ぼ,ぽ,ま,み,む,め,も,ゃ,や,ゅ,ゆ,ょ,よ,ら,り,る,れ,ろ,ゎ,わ,ゐ,ゑ,を,ん,ァ,ア,ィ,イ,ゥ,ウ,ェ,エ,ォ,オ,カ,ガ,キ,ギ,ク,グ,ケ,ゲ,コ,ゴ,サ,ザ,シ,ジ,ス,ズ,セ,ゼ,ソ,ゾ,タ,ダ,チ,ヂ,ッ,ツ,ヅ,テ,デ,ト,ド,ナ,ニ,ヌ,ネ,ノ,ハ,バ,パ,ヒ,ビ,ピ,フ,ブ,プ,ヘ,ベ,ペ,ホ,ボ,ポ,マ,ミ,ム,メ,モ,ャ,ヤ,ュ,ユ,ョ,ヨ,ラ,リ,ル,レ,ロ,ヮ,ワ,ヰ,ヱ,ヲ,ン,ヴ,ヵ,ヶ")},
@@ -54,4 +54,4 @@
 })(charsContent);
 function toArray(str) {
     return str.split(",");
-}
+}
\ No newline at end of file

--
Gitblit v1.9.2