Ver código fonte

管理员,组员列表、添加修改组员信息

dong025 6 dias atrás
pai
commit
1f2be241c4

+ 2 - 1
.gitignore

@@ -7,4 +7,5 @@ vendor.zip
 public/.htaccess
 public/nginx.htaccess
 config/nginx.htaccess
-config/.htaccess
+config/.htaccess
+public/uploads/

+ 227 - 0
app/admin/controller/user/GroupUser.php

@@ -0,0 +1,227 @@
+<?php
+
+declare(strict_types=1);
+
+namespace app\admin\controller\user;
+
+use app\common\controller\Backend;
+use app\admin\traits\Actions;
+use think\annotation\route\Group;
+use think\annotation\route\Route;
+use app\common\model\GroupUser as GroupUserModel;
+use think\facade\Db;
+
+#[Group("user/group_user")]
+class GroupUser extends Backend
+{
+
+    use Actions;
+
+    protected function _initialize()
+    {
+        parent::_initialize();
+        $this->model = new GroupUserModel();
+    }
+
+    /**
+     * 列表
+     */
+    #[Route('GET,POST,JSON', 'index')]
+    public function index()
+    {
+
+        if (false === $this->request->isAjax()) {
+            return $this->fetch();
+        }
+        if ($this->request->post('selectpage')) {
+            return $this->selectpage();
+        }
+        $type = (string)$this->request->get('type', 2);
+
+
+        [$where, $order, $limit, $with] = $this->buildparams();
+        $list=[];
+        if ($type == '1'){
+             $list = $this->model->alias('g')
+            ->join("yun_user u", "g.pid = u.id", "LEFT")
+            ->with($with)
+            ->where($where)
+            ->order($order)
+            ->field(['u.*','u.nickname' => 'manage_nickname'])
+            ->group('g.pid')
+            ->paginate($limit)->each(function ($item, $key) {
+                $item['avatar']=$this->startsWithHttp($item['avatar'])?$item['avatar']:request()->domain().'/' . $item['avatar'];
+                return $item;
+            });
+        }else if($type == '2'){
+             $list = $this->model->alias('g')
+            ->join("yun_user u", "g.pid = u.id", "INNER")
+            ->with($with)
+            ->where($where)
+
+            ->order($order)
+            ->field(['g.*'])
+            ->paginate($limit)->each(function ($item, $key) {
+                $item['avatar']=$this->startsWithHttp($item['avatar'])?$item['avatar']:request()->domain().'/' . $item['avatar'];
+                return $item;
+            });
+        }
+
+       
+
+        $result = ['total' => $list->total(), 'rows' => $list->items(), 'ceshi' => $type];
+        return json($result);
+    }
+
+
+
+    /**
+     * 添加
+     */
+    #[Route('GET,POST', 'add')]
+    public function add()
+    {
+        if (false === $this->request->isPost()) {
+            return $this->fetch();
+        }
+        $params = array_merge($this->request->post("row/a"), $this->postParams);
+        if (empty($params)) {
+            $this->error(__('提交的参数不能为空'));
+        }
+        if (!$this->request->checkToken('__token__', ['__token__' => $this->request->post('__token__')])) {
+            $this->error(__('token错误,请刷新页面重试'));
+        }
+        foreach ($params as &$value) {
+            if (is_array($value)) {
+                $value = implode(',', $value);
+            }
+            if ($value === '') {
+                $value = null;
+            }
+        }
+        $result = false;
+        Db::startTrans();
+        try {
+            $params['salt']   = str_rand(4);
+            $params['password'] = md5(md5($params['password'] . $params['salt']));
+            $params['avatar']  = empty($params['avatar']) ? '/assets/img/logo.jpg' : $params['avatar']; //默认头像
+            $result = $this->model->save($params);
+            if ($this->callback) {
+                $callback = $this->callback;
+                $callback($this->model);
+            }
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if ($result === false) {
+            $this->error(__('没有新增任何数据'));
+        }
+        $this->success();
+    }
+    /**
+     * 编辑
+     */
+    #[Route('GET,POST', 'edit')]
+    public function edit(mixed $row = null)
+    {
+        $ids = $this->request->get('ids');
+        if (!$row || is_array($row)) {
+            $row = $this->model->find($ids);
+        }
+        if (!$row) {
+            $this->error(__('没有找到记录'));
+        }
+        if (count($this->volidateFields) > 0) {
+            foreach ($this->volidateFields as $field => $value) {
+                if ($row[$field] != $value) {
+                    $this->error(__('没有操作权限'));
+                }
+            }
+        }
+        if (false === $this->request->isPost()) {
+            $row['password'] = '';
+            $this->assign('row', $row);
+            return $this->fetch();
+        }
+        $params = array_merge($this->request->post("row/a"), $this->postParams);
+        if (empty($params)) {
+            $this->error(__('提交的参数不能为空'));
+        }
+        if (!$this->request->checkToken('__token__', ['__token__' => $this->request->post('__token__')])) {
+            $this->error(__('token错误,请刷新页面重试'));
+        }
+        foreach ($params as &$value) {
+            if (is_array($value)) {
+                $value = implode(',', $value);
+            }
+            if ($value === '') {
+                $value = null;
+            }
+        }
+        $result = false;
+        Db::startTrans();
+        try {
+            if (!empty($params['password'])) {
+                $params['salt'] = str_rand(4);
+                $params['password'] = md5(md5($params['password'] . $params['salt']));
+            } else {
+                unset($params['password']);
+            }
+            if ($params['type'] == '1' && empty($params['group_name'])) {
+                $this->error(__('管理身份,必须设置组名'));
+            }
+            $params['avatar']  = empty($params['avatar']) ? '/assets/img/logo.jpg' : $params['avatar']; //默认头像
+            $result = $row->save($params);
+            if ($this->callback) {
+                $callback = $this->callback;
+                $callback($row);
+            }
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if (false === $result) {
+            $this->error(__('没有数据被更新'));
+        }
+        $this->success();
+    }
+
+    /**
+     * 列表
+     */
+    #[Route('GET,JSON', 'group_list')]
+    public function group_list()
+    {
+
+        if (false === $this->request->isAjax()) {
+            return $this->fetch();
+        }
+        $pid = (string)$this->request->get('pid', '0');
+
+
+        [$where, $order, $limit, $with] = $this->buildparams();
+        $where_item = [];
+        if ($pid != '0') $where_item[] = ['pid', '=', (string)$pid];
+        $list = $this->model
+            ->with($with)
+            ->where($where_item)
+            ->where($where)
+            ->order($order)
+            ->paginate($limit)->each(function ($item, $key) {
+                $item['avatar']=$this->startsWithHttp($item['avatar'])?$item['avatar']:request()->domain().'/' . $item['avatar'];
+                return $item;
+            });
+
+        $result = ['total' => $list->total(), 'rows' => $list->items()];
+        return json($result);
+    }
+    // 方法1.1:使用strpos()精准匹配
+    public function startsWithHttp($url)
+    {
+        return strpos($url, 'https://') === 0
+            || strpos($url, 'http://') === 0;
+    }
+}

+ 60 - 0
app/admin/view/user/group_user/add.html

@@ -0,0 +1,60 @@
+<template>
+    <el-card shadow="never" style="border: 0;">
+        <yun-form :data="row" :columns="columns">
+            {:token_field()}
+        </yun-form>
+    </el-card>
+</template>
+<script>
+    import form from "@components/Form.js";
+    export default {
+        components: { 'YunForm': form },
+        data: {
+            row: Yunqi.data.row,
+            columns: [
+                { field: 'id', title: __('ID'), edit: 'hidden' },
+                { field: 'nickname', title: __('姓名'), edit: 'text', rules: "required", searchList: Yunqi.data.varietyList },
+                { field: 'username', title: __('账号'), edit: 'text', rules: 'required' },
+                { field: 'id_card', title: __('身份证号'), edit: 'text', rules: 'required;length(6~30)' },
+                {field: 'password',title: __('密码'),edit:{
+                    form:'input',
+                    type:'password',
+                    value:'',
+                    rules:'required;length(6~30)',
+                    placeholder:'不填写则不修改'
+                }},
+                { field: 'avatar', title: __('头像'), edit: 'image', rules: 'required' },
+                { field: 'mobile', title: __('手机号'), edit: 'text', rules: 'required;mobile' },
+                {field: 'role',title: __('角色'),edit:'checkbox',searchList: {1:'录入员', 2:'库管', 3:'记账'}},
+                { field: 'sex', title: __('性别'), edit: { form: 'radio', value: 1 }, rules: 'required', searchList: { 1: '男', 2: '女' } },
+                { field: 'type', title: __('类型'), edit: { form: 'radio', value: 2 }, rules: 'required', searchList: { 1: '管理', 2: '普通员工' } },
+                { field: 'group_name', title: __('组名'), edit: 'text' },
+                { field: 'status', title: __('状态'), edit: 'switch', searchList: { 'normal': __('正常'), 'hidden': __('隐藏') } },
+            ]
+        },
+        //页面加载完成时执行
+        onLoad: function (query) {
+            let columns = this.columns;
+            for (let i in columns) {
+                if (query.add_type == '1') {
+                    if (columns[i].field == 'type') {
+                        columns[i].edit.value = 1;
+                    }
+                } else if (query.add_type == '2') {
+                    if (columns[i].field == 'type') {
+                        columns[i].edit.value = 2;
+                    }
+                }
+
+
+            }
+            this.columns = columns
+        },
+        methods: {
+
+        }
+    }
+</script>
+<style>
+
+</style>

+ 61 - 0
app/admin/view/user/group_user/edit.html

@@ -0,0 +1,61 @@
+<template>
+    <el-card shadow="never" style="border: 0;">
+        <yun-form :data="row" :columns="columns">
+            {:token_field()}
+        </yun-form>
+    </el-card>
+</template>
+<script>
+    import form from "@components/Form.js";
+    export default {
+        components: { 'YunForm': form },
+        data: {
+            row: Yunqi.data.row,
+            columns: [
+                { field: 'id', title: __('ID'), edit: 'hidden' },
+                { field: 'nickname', title: __('姓名'), edit: 'text', rules: "required", searchList: Yunqi.data.varietyList },
+                { field: 'username', title: __('账号'), edit: 'text', rules: 'required' },
+                { field: 'id_card', title: __('身份证号'), edit: 'text', rules: 'required;length(6~30)' },
+                {field: 'password',title: __('密码'),edit:{
+                    form:'input',
+                    type:'password',
+                    value:'',
+                    rules:'required;length(6~30)',
+                    placeholder:'不填写则不修改'
+                }},
+                { field: 'avatar', title: __('头像'), edit: 'image', rules: 'required' },
+                { field: 'mobile', title: __('手机号'), edit: 'text', rules: 'required;mobile' },
+                {field: 'role',title: __('角色'),edit:'checkbox',searchList: {1:'录入员', 2:'库管', 3:'记账'}},
+                { field: 'sex', title: __('性别'), edit: { form: 'radio', value: 1 }, rules: 'required', searchList: { 1: '男', 2: '女' } },
+                { field: 'type', title: __('类型'), edit: { form: 'radio', value: 2 }, rules: 'required', searchList: { 1: '管理', 2: '普通员工' } },
+                { field: 'group_name', title: __('组名'), edit: 'text' },
+                { field: 'status', title: __('状态'), edit: 'switch', searchList: { 'normal': __('正常'), 'hidden': __('隐藏') } },
+            ]
+        },
+        //页面加载完成时执行
+        onLoad: function (query) {
+            let columns = this.columns;
+            for (let i in columns) {
+                if (query.add_type == '1') {
+                    if (columns[i].field == 'type') {
+                        columns[i].edit.value = 1;
+                    }
+                } else if (query.add_type == '2') {
+                    if (columns[i].field == 'type') {
+                        columns[i].edit.value = 2;
+                    }
+                }
+
+
+            }
+            this.columns = columns
+            console.log(this.columns)
+        },
+        methods: {
+
+        }
+    }
+</script>
+<style>
+
+</style>

+ 82 - 0
app/admin/view/user/group_user/group_list.html

@@ -0,0 +1,82 @@
+<template>
+    <el-card shadow="never">
+        <yun-table :columns="columns" ref="yuntable" @render="onTableRender"
+            toolbar="refresh,add,edit,del,more,import,download" :auth="{
+                    download:{:$auth->check('app\\admin\\controller\\user\\GroupUser','download')},
+                }" :extend="extend">
+        </yun-table>
+    </el-card>
+</template>
+<script>
+    import table from "@components/Table.js";
+    export default {
+        components: {
+            'YunTable': table
+        },
+        data: {
+            extend: {
+                index_url: 'user/group_user/index',
+                download_url: 'user/group_user/download',
+            },
+            columns: [
+                {
+                    checkbox: true, selectable: function (row, index) {
+                        //可以根据业务需求返回false让某些行不可选中
+                        return true;
+                    }
+                },
+                { field: "id", title: "ID", operate: false },
+                { field: "nickname", title: "姓名" },
+                { field: 'avatar', title: __('头像'), formatter: Yunqi.formatter.image, operate: false },
+                // { field: "email", title: "电子邮箱" },
+                { field: "mobile", title: "手机号" },
+                { field: "id_card", title: "身份证号" },
+                { field: 'sex', title: __('性别'), width: 100, searchList: { 1: __('男'), 2: __('女') }, operate: false },
+                // { field: "jointime", title: "加入时间", operate: "daterange", formatter: Yunqi.formatter.datetime },
+                { field: "status", title: "状态", operate: "select", searchList: { normal: "正常", hidden: "隐藏" }},
+                { field: "createtime", title: "创建时间", operate: "daterange", formatter: Yunqi.formatter.datetime }
+                
+            ]
+        },
+        //页面加载完成时执行
+        onLoad: function (query) {
+            this.getList(query.pid)
+            
+        },
+        //页面初始显示或在框架内显示时执行
+        onShow: function () {
+
+        },
+        //页面在框架内隐藏时执行
+        onHide: function () {
+
+        },
+        //页面在框架内关闭时执行
+        onUnload: function () {
+
+        },
+        methods: {
+            getList(pid) {
+                let that = this;
+                this.extend.index_url = 'user/group_user/group_list?pid=' + pid
+                Yunqi.ajax.get(this.extend.index_url, {}).then(res => {
+                    
+                    this.$refs.yuntable.reload();
+                })
+            },
+            onTableRender: function (list) {
+                //表格渲染完成后执行
+                /**
+                 * table常用方法
+                 * this.$refs.yuntable.reset();//重新渲染整个组件,当columns修改时,需要重新渲染表格才能生效,可以执行该方法。
+                 * this.$refs.yuntable.reload();//保持当前的page,重新获取数据
+                 * this.$refs.yuntable.submit();//返回第一页,重新获取数据
+                 * this.$refs.yuntable.expandAllTree();//树形表格展开所有节点
+                 * this.$refs.yuntable.expandTree(topid);//树形表格展开指定节点
+                 */
+            }
+        }
+    }
+</script>
+<style>
+</style>

+ 171 - 0
app/admin/view/user/group_user/index.html

@@ -0,0 +1,171 @@
+<template>
+    <el-card shadow="never">
+        <el-tabs type="card" v-model="tabs" @tab-change="tabChange">
+            <el-tab-pane name="all">
+                <template #label>
+                    录入人员
+                </template>
+            </el-tab-pane>
+            <el-tab-pane name="group">
+                <template #label>
+                    组员管理
+                </template>
+            </el-tab-pane>
+        </el-tabs>
+        <yun-table :columns="columns" ref="yuntable" @render="onTableRender" toolbar="refresh" :auth="" :extend="extend">
+        </yun-table>
+    </el-card>
+</template>
+<script>
+    import table from "@components/Table.js";
+    export default {
+        components: {
+            'YunTable': table
+        },
+        data: {
+            extend: {
+                index_url: 'user/group_user/index',
+                // add_url: 'user/group_user/add?add_type=2',
+                // edit_url: 'user/group_user/edit',
+                // del_url: 'user/group_user/del',
+                // multi_url: 'user/group_user/multi',
+                download_url: 'user/group_user/download',
+                // import_url: 'user/group_user/import',
+            },
+            columns: [
+                {
+                    checkbox: true, selectable: function (row, index) {
+                        //可以根据业务需求返回false让某些行不可选中
+                        return true;
+                    }
+                },
+                { field: "id", title: "ID", operate: false },
+                // { field: "group_name", title: "组名", operate: false, visible: false },
+                // { field: "username", title: "账号" },
+
+                { field: "manage_nickname", title: "管理员", visible: false },
+                { field: "nickname", title: "录入人员姓名" },
+                { field: 'avatar', title: __('头像'), formatter: Yunqi.formatter.image, operate: false },
+                // { field: "email", title: "电子邮箱" },
+                { field: "mobile", title: "手机号" },
+                {
+                    field: 'role', title: __('角色'), sortable: true, operate: 'selects', formatter(value, row, index) {
+                        var role = "";
+                        if (value.indexOf("1") > -1) role = role + "录入员";
+                        if (value.indexOf("2") > -1) role = role + "-库管";
+                        if (value.indexOf("3") > -1) role = role + "-记账";
+                        return role;
+                    }
+                },
+                { field: "id_card", title: "身份证号" },
+                { field: 'sex', title: __('性别'), width: 100, searchList: { 1: __('男'), 2: __('女') }, operate: false },
+                // { field: "jointime", title: "加入时间", operate: "daterange", formatter: Yunqi.formatter.datetime },
+                { field: "status", title: "状态", operate: "select", searchList: { normal: "正常", hidden: "隐藏" } },
+                { field: "createtime", title: "创建时间", sortable: true, operate: "daterange", formatter: Yunqi.formatter.datetime },
+                { field: "updatetime", title: "更新时间", visible: false, operate: "daterange", formatter: Yunqi.formatter.datetime },
+                {
+                    field: 'operate',
+                    fixed: 'right',
+                    title: __('操作'),
+                    width: 150,
+                    action: {
+                        list: {
+                            tooltip: true,
+                            icon: 'fa fa-list',
+                            type: 'info',
+                            text: __('小组成员'),
+                            method: 'group_list'
+                        },
+                    },
+                    visible: false 
+                }
+            ],
+            tabs: 'all'
+        },
+        //页面加载完成时执行
+        onLoad: function (query) {
+            
+        },
+        //页面初始显示或在框架内显示时执行
+        onShow: function () {
+
+        },
+        //页面在框架内隐藏时执行
+        onHide: function () {
+
+        },
+        //页面在框架内关闭时执行
+        onUnload: function () {
+
+        },
+        methods: {
+            tabChange(e) {
+                this.tabs = e
+                let group_name_visible = true
+                let type = 2;
+                if (this.tabs == 'all') {
+                    group_name_visible = false
+                    this.extend.add_url = 'user/group_user/add?add_type=2'
+                } else if (this.tabs == 'group') {
+                    type = 1
+                    this.extend.add_url = 'user/group_user/add?add_type=1'
+                }
+
+
+                let columns = this.columns;
+                for (let i in columns) {
+                    if (columns[i].field == 'manage_nickname') {
+                        columns[i].visible = group_name_visible;
+                    }
+                    if (columns[i].field == 'nickname') {
+                        columns[i].visible = !group_name_visible;
+                    }
+
+
+                    if (columns[i].field == 'operate') {
+                        columns[i].visible = group_name_visible;
+                    }
+
+
+                }
+                this.columns = columns
+                this.$nextTick(() => {
+                    this.$refs.yuntable.reset();
+                });
+                this.getList(type)
+            },
+            getList(type) {
+                let that = this;
+                this.extend.index_url = 'user/group_user/index?type=' + type
+                Yunqi.ajax.get(this.extend.index_url, {}).then(res => {
+                    this.$refs.yuntable.reload();
+                })
+            },
+            group_list: function (row) {
+                let that = this;
+                Yunqi.api.open({
+                    url: 'user/group_user/group_list?pid=' + row.id,
+                    width: 1000,
+                    title: __(row.group_name),
+                    icon: 'fa fa-list',
+                    close: function (r) {
+                        that.$refs.yuntable.reload();
+                    }
+                });
+            },
+            onTableRender: function (list) {
+                //表格渲染完成后执行
+                /**
+                 * table常用方法
+                 * this.$refs.yuntable.reset();//重新渲染整个组件,当columns修改时,需要重新渲染表格才能生效,可以执行该方法。
+                 * this.$refs.yuntable.reload();//保持当前的page,重新获取数据
+                 * this.$refs.yuntable.submit();//返回第一页,重新获取数据
+                 * this.$refs.yuntable.expandAllTree();//树形表格展开所有节点
+                 * this.$refs.yuntable.expandTree(topid);//树形表格展开指定节点
+                 */
+            }
+        }
+    }
+</script>
+<style>
+</style>

+ 2 - 0
app/admin/view/user/index/index.html

@@ -38,6 +38,8 @@
                 {field: 'username',title: __('用户名'),operate:'='},
                 {field: 'avatar', title: __('头像'), formatter: Yunqi.formatter.image, operate: false},
                 {field: 'nickname',title: __('昵称'),operate: 'LIKE',formatter: Yunqi.formatter.tag},
+                {field: 'id_card',title: __('身份证号'),operate: 'LIKE',formatter: Yunqi.formatter.tag},
+                
                 {field: 'sex', title: __('性别'),width:100,searchList: {1: __('男'), 2: __('女')},operate:false,formatter:Yunqi.formatter.select},
                 {field: 'email',title: __('邮箱'),operate:'LIKE'},
                 {field: 'mobile',title: __('手机'),operate: '='},

+ 244 - 0
app/api/controller/GroupUser.php

@@ -0,0 +1,244 @@
+<?php
+
+namespace app\api\controller;
+
+use app\api\service\auth\GroupMysqlAdapter;
+use app\api\service\auth\ApiAuthGroupService;
+use app\api\validate\User as UserValidate;
+use think\exception\ValidateException;
+use app\common\model\GroupUser as GroupUserModel;
+use app\common\model\User as UserModel;
+use \think\facade\Filesystem;
+
+class GroupUser extends Base
+{
+
+    protected $noNeedLogin = ['login'];
+
+
+    public function userinfo(GroupUserModel $userModel)
+    {
+        $user = $userModel->find($this->userinfo['id']);
+        return  $this->success('ok', $user);
+    }
+
+    //编辑用户
+    public function edit(GroupUserModel $userModel)
+    {
+        $data = $this->request->post();
+        try {
+            validate(UserValidate::class)->scene('edit')->check($data);
+            $user = $userModel->find($this->userinfo['id']);
+            if (!$user) {
+                return $this->error('用户不存在');
+            }
+            $user->save($data);
+            return $this->success('ok');
+        } catch (ValidateException $e) {
+            return $this->error($e->getError());
+        }
+    }
+
+    //修改密码
+    public function password(GroupUserModel $userModel)
+    {
+        $data = $this->request->post();
+        try {
+            validate(UserValidate::class)->scene('password')->check($data);
+            $user = $userModel->find($this->userinfo['id']);
+            if (!$user) {
+                return $this->error('用户不存在');
+            }
+            if ($user->password != md5(md5($data['oldpassword'] . $user->salt))) {
+                return $this->error('旧密码错误');
+            }
+            $user->password = md5(md5($data['password'] . $user->salt));
+            $user->save();
+            return $this->success('ok');
+        } catch (ValidateException $e) {
+            return $this->error($e->getError());
+        }
+    }
+
+    public function login(ApiAuthGroupService $authService, GroupUserModel $userModel)
+    {
+        $data = $this->request->post();
+        try {
+
+            validate(UserValidate::class)->scene('login')->check($data);
+            $terminal = $this->request->post('terminal/d', 0);
+            $user = $authService->login($data['username'], $data['password'], $terminal);
+        } catch (ValidateException $e) {
+
+            return $this->error($e->getError());
+        } catch (\Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return  $this->success('ok', $user);
+    }
+
+
+    //退出登录
+    public function logout()
+    {
+        GroupMysqlAdapter::logout($this->userinfo['id']);
+        return  $this->success('ok');
+    }
+
+    //获取全部人员
+    public function getAllUser(GroupUserModel $userModel)
+    {
+        $list = $userModel->where('status', 'normal')->field('id,nickname,avatar')->select();
+        return $this->success('ok', $list);
+    }
+
+    //组员列表
+    public function group_list(GroupUserModel $userModel)
+    {
+        
+        $list = $userModel->where('status', 'normal')->where('pid', $this->userinfo['id'])->select();
+
+        return $this->success('ok', $list);
+    }
+
+    //添加组员
+    public function add_group_user(GroupUserModel $groupUserModel,UserModel $userModel)
+    {
+        $file = request()->file('avatar');
+        $param = $this->request->post();
+        try {
+            validate(UserValidate::class)->scene('add_group_user')->check($param);
+            $todayTime = strtotime('today');
+
+            //判断手机号和身份证号是否注册今天是否添加到该团队
+            $where_item_id_card = [];
+            $where_item_id_card[]=['pid', '=',$this->userinfo['id']];
+            $where_item_id_card[]=['id_card', '=',$param['id_card']];
+            $where_item_id_card[]=['createtime', '>=',$todayTime];
+            
+            $group_user_data = $groupUserModel->where($where_item_id_card)->find();
+            if(!empty($group_user_data)) return $this->error('该身份证号已添加',$param['id_card']);
+            
+            $where_item_mobile = [];
+            $where_item_mobile[]=['pid', '=',$this->userinfo['id']];
+            $where_item_mobile[]=['mobile', '=',$param['mobile']];
+            $where_item_mobile[]=['createtime', '>=',$todayTime];
+
+            $group_user_data = $groupUserModel->where($where_item_mobile)->find();
+            if(!empty($group_user_data)) return $this->error('该手机号已添加');
+
+            $user = $userModel->find($this->userinfo['id']);
+            
+            $pid=$user['id'];
+            $time=time();
+            $add_data=[
+                'pid'=>$pid,
+                'nickname'=>$param['nickname'],
+                'id_card'=>$param['id_card'],
+                'avatar'=>'',
+                'mobile'=>$param['mobile'],
+                'sex'=>$param['sex'],
+                'role'=>'1',
+                'status'=>'normal',
+                'joinip'=>request()->ip(),
+                'jointime'=>$time
+            ];
+            if (!empty($file)) {
+                // 文件夹
+                $folder = strtotime('today');
+                $fileName = time() . '_' . mt_rand(1000, 9999) . '.png';
+
+                $avatar = $file->move('uploads/avatar/' . $folder, $fileName);
+                
+                //检查目标文件是否存在
+                if (!empty($avatar)) {
+                    //有图片上传,进行添加用户
+                    $add_data['avatar']=$avatar;
+                    $res=$groupUserModel->save($add_data);
+                    if($res) return $this->success('添加成功',$res);
+                }
+            }
+        } catch (ValidateException $e) {
+            return $this->error($e->getError());
+        }
+        return $this->error('添加失败');
+    }
+    //修改组员
+    public function edit_group_user(GroupUserModel $groupUserModel,UserModel $userModel)
+    {
+        $file = request()->file('avatar');
+        $param = $this->request->post();
+        try {
+            validate(UserValidate::class)->scene('edit_group_user')->check($param);
+            $edit_data=$groupUserModel->find($param['id']);
+            
+            $todayTime = strtotime('today');
+
+            //判断手机号和身份证号是否注册今天是否添加到该团队
+            $where_item_id_card = [];
+            $where_item_id_card[]=['pid', '=',$this->userinfo['id']];
+            $where_item_id_card[]=['id_card', '=',$param['id_card']];
+            $where_item_id_card[]=['id_card', '<>',$edit_data['id_card']];
+            $where_item_id_card[]=['createtime', '>=',$todayTime];
+            
+            $group_user_data = $groupUserModel->where($where_item_id_card)->find();
+            if(!empty($group_user_data)) return $this->error('该身份证号已添加',$param['id_card']);
+            
+            $where_item_mobile = [];
+            $where_item_mobile[]=['pid', '=',$this->userinfo['id']];
+            $where_item_mobile[]=['mobile', '=',$param['mobile']];
+            $where_item_mobile[]=['mobile', '<>',$edit_data['mobile']];
+            $where_item_mobile[]=['createtime', '>=',$todayTime];
+
+            $group_user_data = $groupUserModel->where($where_item_mobile)->find();
+            if(!empty($group_user_data)) return $this->error('该手机号已添加');
+
+            $user = $userModel->find($this->userinfo['id']);
+            
+            $pid=$user['id'];
+            $time=time();
+            $add_data=[
+                'pid'=>$pid,
+                'nickname'=>$param['nickname'],
+                'id_card'=>$param['id_card'],
+                'mobile'=>$param['mobile'],
+                'sex'=>$param['sex'],
+                'role'=>'1',
+                'status'=>'normal',
+                'joinip'=>request()->ip(),
+                'updatetime'=>$time
+            ];
+            if (!empty($file)) {
+                // 文件夹
+                $folder = strtotime('today');
+                $fileName = time() . '_' . mt_rand(1000, 9999) . '.png';
+
+                $avatar = $file->move('uploads/avatar/' . $folder, $fileName);
+                
+                
+                //检查目标文件是否存在
+                if (!empty($avatar)) {
+                    if(!empty($edit_data['avatar'])){
+                        $avatar_file=root_path() . 'public' . DS . $edit_data['avatar'];
+                        if (file_exists($avatar_file)) {
+                            unlink($avatar_file);
+                        }
+                    }
+                    //有图片上传,进行添加用户
+                    $add_data['avatar']=$avatar;
+                    $res=$edit_data->save($add_data);
+                    if($res) return $this->success('修改成功',$res);
+                }
+            }else{
+                $res=$edit_data->save($add_data);
+                if($res) return $this->success('修改成功',$res);
+            }
+        } catch (ValidateException $e) {
+            return $this->error($e->getError());
+        }
+        return $this->error('修改失败');
+    }
+
+    
+    
+}

+ 1 - 1
app/api/controller/Worker.php

@@ -30,7 +30,7 @@ class Worker extends Base
     {
         parent::_initialize();
         $this->shopDeliveryModel = new ShopDeliveryModel();
-        if (!str_contains($this->userinfo['role'], "4")) {
+        if (!str_contains($this->userinfo['role'], "1")) {
             $this->error(__('没有权限' . $this->userinfo['role']));
         }
     }

+ 11 - 0
app/api/route/route.php

@@ -11,6 +11,7 @@ Route::group('user', function () {
     Route::rule('logout','user/logout','GET|POST');
     Route::rule('edit','user/edit','POST');
     Route::rule('password','user/password','POST');
+
     //平台
     Route::rule('platform','index/getPlatform','POST');
     //店铺
@@ -62,6 +63,16 @@ Route::group('user', function () {
     Route::rule('getAllUser','User/getAllUser','POST');
     //支收总览
     Route::rule('getMoneyCountAll','MoneyLog/getCountAll','POST');
+
+    //组员列表
+    
+    Route::rule('groupList','GroupUser/group_list','POST');
+    //添加组员
+    Route::rule('add_group_user','GroupUser/add_group_user','POST');
+    //修改组员
+    Route::rule('edit_group_user','GroupUser/edit_group_user','POST');
+    
+    
   })->middleware(AllowCrossDomain::class);
 
 // 定义 API 路由组

+ 65 - 0
app/api/service/auth/ApiAuthGroupService.php

@@ -0,0 +1,65 @@
+<?php
+declare(strict_types=1);
+namespace app\api\service\auth;
+
+use app\api\service\auth\Adapter;
+use think\facade\Cache;
+use app\common\model\GroupUser;
+use app\common\model\UserToken;
+use think\facade\Config;
+
+
+class ApiAuthGroupService 
+{
+    protected $allowFields = ['id', 'nickname', 'mobile', 'avatar', 'balance', 'score'];
+    
+
+    public function login(string $username, string $password, int $terminal = 0)
+    {
+        $token=uuid();
+        $user=GroupUser::where('username',$username)->find();
+        if(!$user){
+            throw new \Exception('账号或密码错误');
+        }
+        if($user->password!=md5(md5($password.$user->salt))){
+            //throw new \Exception('账号或密码错误' . md5(md5($password.$user->salt)));
+            throw new \Exception('账号或密码错误');
+        }
+        if($user->status!='normal'){
+            throw new \Exception('账号已经被禁用');
+        }
+        if($terminal==1 && strpos($user->role, "3") === false){
+            throw new \Exception('账号已经被禁用');
+        }
+        //刷新token
+        $token = GroupMysqlAdapter::login($token, $user);
+        $user->loginfailure = 0;
+        $user->logintime = time();
+        $user->loginip = request()->ip();
+        $user->save();
+
+        Cache::store('redis')->set('user_info_'.$user->id, $user->toArray(), Config::get('app.user_login.keepalive_time'));
+        $data = [
+            'userinfo' => $user,
+            'token' => $token,
+            'page' => '',//page:stock_clerk 仓库管理员 worker:打包员工
+         ];
+        $role_arr = explode(',', $user->role);
+        if(in_array('3', $role_arr)){
+            $data['page'] = 'stock_clerk';//仓库管理员
+        }else if(in_array('4', $role_arr)){
+            $data['page'] = 'worker';//打包员工
+        }
+
+        return $data;
+    }
+
+   
+
+
+    public function updateToken(int $uid, array $arr)
+    {   
+        return UserToken::where('user_id', $uid)->update($arr);
+    }
+
+}

+ 53 - 0
app/api/service/auth/GroupMysqlAdapter.php

@@ -0,0 +1,53 @@
+<?php
+declare(strict_types=1);
+namespace app\api\service\auth;
+
+use think\facade\Cache;
+use app\common\model\UserToken;
+use app\common\model\GroupUser;
+use think\facade\Config;
+
+class GroupMysqlAdapter
+{
+    private UserToken $usertoken;
+
+  
+
+    public  static function userinfo(string $token):int
+    {
+        return UserToken::where('token',$token)->where('expire','>', time())->value('user_id');
+    }
+
+    public static function getUserToken($token):bool
+    {
+        return boolval(UserToken::where('token',$token)->where('expire','>', time())->order('id','asc')->count());
+    }
+
+    public static function login(string $token,GroupUser $user)
+    {
+        $keepalive_time=Config::get('app.user_login.keepalive_time');
+        $token = md5($token);
+        UserToken::create([
+            'token'=> $token ,
+            'user_id'=>$user->id,
+            'expire'=>time()+$keepalive_time
+        ]);
+      
+        $allow_device_num=Config::get('app.user_login.allow_device_num');
+        //如果数据库中保存的设备数大于允许的设备数,如果超出则挤出去最早登陆的设备
+        $time=time();
+        $count=UserToken::where('user_id',$user->id)->where('expire','>',$time)->count();
+        if($count>$allow_device_num){
+            $usertoken=UserToken::where('user_id',$user->id)->where('expire','>',$time)->order('id','asc')->find();
+            $usertoken->delete();
+        }
+        return $token ;
+    }
+
+    public static function logout(int $uid)
+    {   
+        $token = request()->header('token');
+        UserToken::where('token', $token)->delete();
+        Cache::store('redis')->delete('user_info_'.$uid);
+    }
+}

+ 11 - 2
app/api/validate/User.php

@@ -9,11 +9,16 @@ class User extends Validate
         'username'  => 'require|max:25',
         'password'  => 'require|length:6,32',
         'nickname'  => 'require|max:25',
-        'mobile'    => 'require|number|length:11',
+        'mobile'    => 'require|mobile|number|length:11',
         'email' => 'email',  
         'password' => 'require|length:6,32',
         'repassword' => 'require|length:6,32|confirm:password',
         'oldpassword' => 'require|length:6,32',
+        'id_card'  => 'require|idCard',
+        'sex'  => 'require|in:1,0'
+
+        
+        
     ];
     
     protected $message  =   [
@@ -24,6 +29,7 @@ class User extends Validate
         'nickname'  => '昵称格式错误',
         'oldpassword' => '旧密码错误',
         'repassword' => '两次密码不一致',
+        'id_card' => '身份证格式错误',
     ];
 
 
@@ -31,6 +37,9 @@ class User extends Validate
     protected $scene = [
         'login'  =>  ['name','password'],
         'edit'   =>  ['mobile','nickname','email'],
-        'password' => ['password','oldpassword', 'repassword']
+        'password' => ['password','oldpassword', 'repassword'],
+        'add_group_user'   =>  ['nickname','id_card','mobile','sex'],
+        'edit_group_user'   =>  ['id','nickname','id_card','mobile','sex'],
+        
     ]; 
 }

+ 11 - 0
app/common/model/GroupUser.php

@@ -0,0 +1,11 @@
+<?php
+declare(strict_types=1);
+
+namespace app\common\model;
+
+use app\common\model\base\BaseModel;
+
+class GroupUser extends BaseModel
+{
+
+}