quanwei
14 hours ago b90b528cb5c6eaebe03fba972fef658a741ce896
活动评价
28 files added
19 files modified
4846 ■■■■■ changed files
admin/app/api/controller/branch/ActivityComment.php 75 ●●●●● patch | view | raw | blame | history
admin/app/api/model/branch/ActivityComment.php 49 ●●●●● patch | view | raw | blame | history
admin/app/branch/controller/activity/Comment.php 62 ●●●●● patch | view | raw | blame | history
admin/app/branch/model/activity/Comment.php 90 ●●●●● patch | view | raw | blame | history
admin/app/common/model/branch/ActivityComment.php 218 ●●●●● patch | view | raw | blame | history
admin/app/common/model/branch/ActivityCommentImage.php 22 ●●●●● patch | view | raw | blame | history
admin/app/shop/controller/branch/ActivityComment.php 62 ●●●●● patch | view | raw | blame | history
admin/app/shop/model/branch/ActivityComment.php 78 ●●●●● patch | view | raw | blame | history
admin/app/shop/service/region/MenusService.php 82 ●●●●● patch | view | raw | blame | history
admin/config/cache.php 24 ●●●●● patch | view | raw | blame | history
agent_vue/src/api/plugs.js 4 ●●●● patch | view | raw | blame | history
agent_vue/src/api/user.js 4 ●●●● patch | view | raw | blame | history
agent_vue/src/views/help/Fonticon.vue 6 ●●●● patch | view | raw | blame | history
branch_vue/src/api/branch.js 21 ●●●●● patch | view | raw | blame | history
branch_vue/src/views/activity/activity/add.vue 75 ●●●● patch | view | raw | blame | history
branch_vue/src/views/activity/activity/drawer/part/edit.vue 81 ●●●● patch | view | raw | blame | history
branch_vue/src/views/activity/comment/detail.vue 147 ●●●●● patch | view | raw | blame | history
branch_vue/src/views/activity/comment/index.vue 233 ●●●●● patch | view | raw | blame | history
branch_vue/static/UE/dialogs/spechars/spechars.js 4 ●●●● patch | view | raw | blame | history
mobile/pages.json 12 ●●●●● patch | view | raw | blame | history
mobile/pages/branch/activity/evaluate/evaluate.vue 277 ●●●●● patch | view | raw | blame | history
mobile/pages/branch/admin/activity/add.vue 45 ●●●●● patch | view | raw | blame | history
mobile/pages/branch/admin/activity/edit.vue 45 ●●●●● patch | view | raw | blame | history
mobile/pages/user/my_activity/detail.vue 14 ●●●●● patch | view | raw | blame | history
mobile/pages/user/my_activity/index.vue 29 ●●●●● patch | view | raw | blame | history
operations_vue/static/UE/dialogs/spechars/spechars.js 4 ●●●● patch | view | raw | blame | history
shop_vue/src/api/branch.js 21 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/branch/activity/add.vue 74 ●●●● patch | view | raw | blame | history
shop_vue/src/views/branch/activity/drawer/part/edit.vue 74 ●●●● patch | view | raw | blame | history
shop_vue/src/views/branch/comment/detail.vue 150 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/branch/comment/index.vue 236 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/branch/setting/part/Basic.vue 6 ●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/region/auth/access/Index.vue 288 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/region/auth/access/part/Add.vue 218 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/region/auth/access/part/Edit.vue 210 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/region/auth/index.vue 35 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/region/auth/role/Index.vue 142 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/region/auth/role/add.vue 179 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/region/auth/role/edit.vue 228 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/region/auth/user/Admin.vue 203 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/region/auth/user/dialog/Add.vue 130 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/region/auth/user/dialog/Edit.vue 154 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/region/role/add.vue 121 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/region/role/edit.vue 170 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/region/role/index.vue 135 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/region/user/dialog/Add.vue 305 ●●●●● patch | view | raw | blame | history
shop_vue/static/UE/dialogs/spechars/spechars.js 4 ●●●● patch | view | raw | blame | history
admin/app/api/controller/branch/ActivityComment.php
New file
@@ -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);
    }
}
admin/app/api/model/branch/ActivityComment.php
New file
@@ -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);
    }
}
admin/app/branch/controller/activity/Comment.php
New file
@@ -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('删除成功');
    }
}
admin/app/branch/model/activity/Comment.php
New file
@@ -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]);
    }
}
admin/app/common/model/branch/ActivityComment.php
New file
@@ -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);
    }
}
admin/app/common/model/branch/ActivityCommentImage.php
New file
@@ -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');
    }
}
admin/app/shop/controller/branch/ActivityComment.php
New file
@@ -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('删除成功');
    }
}
admin/app/shop/model/branch/ActivityComment.php
New file
@@ -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]);
    }
}
admin/app/shop/service/region/MenusService.php
New file
@@ -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;
    }
}
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'  => [],
        ],
    ],
];
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;
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;
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>
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);
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;
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;
branch_vue/src/views/activity/comment/detail.vue
New file
@@ -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>
branch_vue/src/views/activity/comment/index.vue
New file
@@ -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>
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(",");
}
}
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",
mobile/pages/branch/activity/evaluate/evaluate.vue
New file
@@ -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>
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
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
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({
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>
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(",");
}
}
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);
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;
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;
shop_vue/src/views/branch/comment/detail.vue
New file
@@ -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>
shop_vue/src/views/branch/comment/index.vue
New file
@@ -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>
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>
shop_vue/src/views/plus/region/auth/access/Index.vue
New file
@@ -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>
shop_vue/src/views/plus/region/auth/access/part/Add.vue
New file
@@ -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>
shop_vue/src/views/plus/region/auth/access/part/Edit.vue
New file
@@ -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>
shop_vue/src/views/plus/region/auth/index.vue
New file
@@ -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>
shop_vue/src/views/plus/region/auth/role/Index.vue
New file
@@ -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>
shop_vue/src/views/plus/region/auth/role/add.vue
New file
@@ -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>
shop_vue/src/views/plus/region/auth/role/edit.vue
New file
@@ -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>
shop_vue/src/views/plus/region/auth/user/Admin.vue
New file
@@ -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>
shop_vue/src/views/plus/region/auth/user/dialog/Add.vue
New file
@@ -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>
shop_vue/src/views/plus/region/auth/user/dialog/Edit.vue
New file
@@ -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>
shop_vue/src/views/plus/region/role/add.vue
New file
@@ -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>
shop_vue/src/views/plus/region/role/edit.vue
New file
@@ -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>
shop_vue/src/views/plus/region/role/index.vue
New file
@@ -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>
shop_vue/src/views/plus/region/user/dialog/Add.vue
New file
@@ -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>
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(",");
}
}