Explorar o código

新增注册功能

kuaifan %!s(int64=5) %!d(string=hai) anos
pai
achega
e4890b4b6f

+ 58 - 0
app/Http/Controllers/Api/SystemController.php

@@ -0,0 +1,58 @@
+<?php
+
+namespace App\Http\Controllers\Api;
+
+use App\Http\Controllers\Controller;
+use App\Module\Base;
+use App\Module\Users;
+use Request;
+
+/**
+ * @apiDefine system
+ *
+ * 系统
+ */
+class SystemController extends Controller
+{
+    public function __invoke($method, $action = '')
+    {
+        $app = $method ? $method : 'main';
+        if ($action) {
+            $app .= "__" . $action;
+        }
+        return (method_exists($this, $app)) ? $this->$app() : Base::ajaxError("404 not found (" . str_replace("__", "/", $app) . ").");
+    }
+
+    /**
+     * 获取设置、保存设置
+     *
+     * @apiParam {String} type
+     * - get: 获取(默认)
+     * - save: 保存设置(支持:reg)
+     */
+    public function setting()
+    {
+        $type = trim(Request::input('type'));
+        if ($type == 'save') {
+            $user = Users::authE();
+            if (Base::isError($user)) {
+                return $user;
+            } else {
+                $user = $user['data'];
+            }
+            if ($user['id'] != 1) {
+                return Base::retError('权限不足!');
+            }
+            $all = Request::input();
+            foreach ($all AS $key => $value) {
+                if (!in_array($key, ['reg'])) {
+                    unset($all[$key]);
+                }
+            }
+            $setting = Base::setting('system', Base::newTrim($all));
+        } else {
+            $setting = Base::setting('system');
+        }
+        return Base::retSuccess('success', $setting ? $setting : json_decode('{}'));
+    }
+}

+ 71 - 50
app/Http/Controllers/Api/UsersController.php

@@ -27,17 +27,38 @@ class UsersController extends Controller
     }
 
     /**
-     * 登陆
-     * @return array
+     * 登陆、注册
+     *
+     * @apiParam {String} type           类型
+     * - login:登录(默认)
+     * - reg:注册
+     * @apiParam {String} username       用户名
+     * @apiParam {String} userpass       密码
      */
     public function login()
     {
-        $user = Base::DBC2A(DB::table('users')->where('username', trim(Request::input('username')))->first());
-        if (empty($user)) {
-            return Base::retError('账号或密码错误。');
-        }
-        if ($user['userpass'] != Base::md52(Request::input('userpass'))) {
-            return Base::retError('账号或密码错误!');
+        $type = trim(Request::input('type'));
+        $username = trim(Request::input('username'));
+        $userpass = trim(Request::input('userpass'));
+        if ($type == 'reg') {
+            $setting = Base::setting('system');
+            if ($setting['reg'] == 'close') {
+                return Base::retError('未开放注册。');
+            }
+            $user = Users::reg($username, $userpass);
+            if (Base::isError($user)) {
+                return $user;
+            } else {
+                $user = $user['data'];
+            }
+        } else {
+            $user = Base::DBC2A(DB::table('users')->where('username', $username)->first());
+            if (empty($user)) {
+                return Base::retError('账号或密码错误。');
+            }
+            if ($user['userpass'] != Base::md52($userpass)) {
+                return Base::retError('账号或密码错误!');
+            }
         }
         //
         $array = [
@@ -51,15 +72,13 @@ class UsersController extends Controller
         Base::array_over($user, $array);
         DB::table('users')->where('id', $user['id'])->update($array);
         //
-        if (intval(Request::input('onlydata')) !== 1) {
-            Session::put('sessionToken', $array['token']);
-        }
-        return Base::retSuccess("登陆成功!", Users::retInfo($user));
+        return Base::retSuccess($type == 'reg' ? "注册成功!" : "登陆成功!", Users::retInfo($user));
     }
 
     /**
-     * 获取会员信息
-     * @return array|mixed
+     * 获取我的信息
+     *
+     * @apiParam {String} [callback]           jsonp返回字段
      */
     public function info()
     {
@@ -82,8 +101,9 @@ class UsersController extends Controller
     }
 
     /**
-     * 获取基本信息
-     * @return array
+     * 获取指定会员基本信息
+     *
+     * @apiParam {String} username           会员用户名
      */
     public function basic()
     {
@@ -92,6 +112,16 @@ class UsersController extends Controller
 
     /**
      * 搜索会员列表
+     *
+     * @apiParam {Object} where            搜索条件
+     * - where.usernameequal
+     * - where.username
+     * - where.nousername
+     * - where.identity
+     * - where.noidentity
+     * - where.projectid
+     * - where.noprojectid
+     * @apiParam {Number} [take]           获取数量,10-100
      */
     public function searchinfo()
     {
@@ -144,7 +174,11 @@ class UsersController extends Controller
 
     /**
      * 修改资料
-     * @return array|mixed
+     *
+     * @apiParam {Object} [userimg]             会员头像
+     * @apiParam {String} [nickname]            昵称
+     * @apiParam {String} [profession]          职位/职称
+     * @apiParam {String} [bgid]                背景编号
      */
     public function editdata()
     {
@@ -200,7 +234,9 @@ class UsersController extends Controller
 
     /**
      * 修改密码
-     * @return array|mixed
+     *
+     * @apiParam {String} oldpass           旧密码
+     * @apiParam {String} newpass           新密码
      */
     public function editpass()
     {
@@ -275,6 +311,12 @@ class UsersController extends Controller
 
     /**
      * 添加团队成员
+     *
+     * @apiParam {String} username              用户名
+     * @apiParam {String} userpass              密码
+     * @apiParam {Object} [userimg]             会员头像
+     * @apiParam {String} [nickname]            昵称
+     * @apiParam {String} [profession]          职位/职称
      */
     public function team__add()
     {
@@ -311,44 +353,23 @@ class UsersController extends Controller
                 return Base::retError('昵称最多只能设置20个字!');
             }
         }
-        //用户名
-        $username = trim(Request::input('username'));
-        if (strlen($username) < 2) {
-            return Base::retError('用户名不可以少于2个字符!');
-        } elseif (strlen($username) > 16) {
-            return Base::retError('用户名最多只能设置16个字符!');
-        }
-        if (!preg_match('/^[A-Za-z0-9_\x{4e00}-\x{9fa5}]+$/u', $username)) {
-            return Base::retError('用户名由2-16位数字或字母、汉字、下划线组成!');
-        }
-        if (Users::username2id($username) > 0) {
-            return Base::retError('用户名已存在!');
-        }
-        //密码
-        $userpass = trim(Request::input('userpass'));
-        if (strlen($userpass) < 6) {
-            return Base::retError('密码设置不能小于6位数!');
-        } elseif (strlen($userpass) > 32) {
-            return Base::retError('密码最多只能设置32位数!');
-        }
-        //
-        if (DB::table('users')->insert([
+        //开始注册
+        $user = Users::reg(trim(Request::input('username')), trim(Request::input('userpass')), [
             'userimg' => $userimg ?: '',
             'nickname' => $nickname ?: '',
             'profession' => $profession ?: '',
-            'username' => $username,
-            'userpass' => Base::md52($userpass),
-            'regip' => Base::getIp(),
-            'regdate' => Base::time()
-        ])) {
-            return Base::retSuccess('添加成功!');
+        ]);
+        if (Base::isError($user)) {
+            return $user;
         } else {
-            return Base::retError('添加失败!');
+            return Base::retSuccess('添加成功!');
         }
     }
 
     /**
      * 删除团队成员
+     *
+     * @apiParam {String} username           用户名
      */
     public function team__delete()
     {
@@ -362,12 +383,12 @@ class UsersController extends Controller
         if (Base::isError(Users::identity('admin'))) {
             return Base::retError('身份权限不足!', [], -1);
         }
-        $id = intval(Request::input('id'));
-        if ($user['id'] == $id) {
+        $username = intval(Request::input('username'));
+        if ($user['username'] == $username) {
             return Base::retError('不能删除自己!');
         }
         //
-        if (DB::table('users')->where('id', $id)->delete()) {
+        if (DB::table('users')->where('username', $username)->delete()) {
             return Base::retSuccess('删除成功!');
         } else {
             return Base::retError('删除失败!');

+ 45 - 0
app/Module/Users.php

@@ -14,6 +14,51 @@ use Session;
 class Users
 {
     /**
+     * 注册会员
+     * @param $username
+     * @param $userpass
+     * @param array $other
+     * @return array
+     */
+    public static function reg($username, $userpass, $other = [])
+    {
+        //用户名
+        if (strlen($username) < 2) {
+            return Base::retError('用户名不可以少于2个字符!');
+        } elseif (strlen($username) > 16) {
+            return Base::retError('用户名最多只能设置16个字符!');
+        }
+        if (!preg_match('/^[A-Za-z0-9_\x{4e00}-\x{9fa5}]+$/u', $username)) {
+            return Base::retError('用户名由2-16位数字或字母、汉字、下划线组成!');
+        }
+        if (Users::username2id($username) > 0) {
+            return Base::retError('用户名已存在!');
+        }
+        //密码
+        if (strlen($userpass) < 6) {
+            return Base::retError('密码设置不能小于6位数!');
+        } elseif (strlen($userpass) > 32) {
+            return Base::retError('密码最多只能设置32位数!');
+        }
+        //开始注册
+        $inArray = [
+            'username' => $username,
+            'userpass' => Base::md52($userpass),
+            'regip' => Base::getIp(),
+            'regdate' => Base::time()
+        ];
+        if ($other) {
+            $inArray = array_merge($inArray, $other);
+        }
+        DB::table('users')->insert($inArray);
+        $user = Base::DBC2A(DB::table('users')->where('username', $username)->first());
+        if (empty($user)) {
+            return Base::retError('注册失败,请稍后再试。');
+        }
+        return Base::retSuccess('success', $user);
+    }
+
+    /**
      * 临时身份标识
      * @return mixed|string
      */

+ 16 - 8
resources/assets/js/main/components/UserInput.vue

@@ -27,7 +27,7 @@
                        :style="tableStyle"
                        :columns="columns"
                        :data="userLists"
-                       @on-current-change="userChange"
+                       @on-row-click="userChange"
                        :no-data-text="noDataText"></Table>
             </div>
         </transition>
@@ -177,8 +177,8 @@
         created() {
             this.columns = [
                 {
-                    "title": this.$L("昵称"),
-                    "key": "nickname",
+                    "title": this.$L("用户名"),
+                    "key": "username",
                     "minWidth": 80,
                     "ellipsis": true,
                     "tooltip": true,
@@ -192,16 +192,19 @@
                                 style: { marginRight: '6px', fontSize: '16px', color: '#FF5722' },
                             }));
                         }
-                        arr.push(h('span', params.row.nickname || '-'));
+                        arr.push(h('span', username));
                         return h('div', arr);
                     }
                 }, {
-                    "title": this.$L("用户名"),
-                    "key": "username",
+                    "title": this.$L("昵称"),
+                    "key": "nickname",
                     "minWidth": 80,
                     "ellipsis": true,
                     "tooltip": true,
-                },
+                    render: (h, params) => {
+                        return h('span', params.row.nickname || '-');
+                    }
+                }
             ];
             this.noDataText = this.$L("数据加载中.....");
         },
@@ -408,7 +411,12 @@
 
             userChange(item) {
                 if (this.multiple) {
-                    this.addMultipleLists(item);
+                    let tempLists = this.multipleLists.filter((res) => { return res.username == item.username });
+                    if (tempLists.length > 0) {
+                        this.multipleLists = this.multipleLists.filter((res) => { return res.username != item.username });
+                    } else {
+                        this.addMultipleLists(item);
+                    }
                 } else {
                     this.userName = item.username;
                     this.seleName = item.nickname || item.username;

+ 56 - 0
resources/assets/js/main/components/WHeader.vue

@@ -21,6 +21,7 @@
                        <Icon type="md-arrow-dropdown"/>
                    </div>
                     <Dropdown-menu slot="list">
+                        <Dropdown-item v-if="userInfo.id==1" name="system">{{$L('系统设置')}}</Dropdown-item>
                         <Dropdown-item name="user">{{$L('个人中心')}}</Dropdown-item>
                         <Dropdown-item name="out">{{$L('退出登录')}}</Dropdown-item>
                     </Dropdown-menu>
@@ -41,6 +42,20 @@
                 </Dropdown>
             </div>
         </div>
+        <WDrawer v-model="systemDrawerShow" maxWidth="640" title="系统设置">
+            <Form ref="formSystem" :model="formSystem" :label-width="80">
+                <FormItem :label="$L('允许注册')" prop="userimg">
+                    <RadioGroup v-model="formSystem.reg">
+                        <Radio label="open">允许</Radio>
+                        <Radio label="close">禁止</Radio>
+                    </RadioGroup>
+                </FormItem>
+                <FormItem>
+                    <Button :loading="loadIng > 0" type="primary" @click="handleSubmit('formSystem')">{{$L('提交')}}</Button>
+                    <Button :loading="loadIng > 0" @click="handleReset('formSystem')" style="margin-left: 8px">{{$L('重置')}}</Button>
+                </FormItem>
+            </Form>
+        </WDrawer>
         <WDrawer v-model="userDrawerShow" maxWidth="1000">
             <Tabs v-model="userDrawerTab">
                 <TabPane :label="$L('个人资料')" name="personal">
@@ -259,9 +274,16 @@
 
                 loadIng: 0,
                 userInfo: {},
+
+                systemDrawerShow: false,
+
                 userDrawerShow: false,
                 userDrawerTab: 'personal',
 
+                formSystem: {
+                    reg: 'open',
+                },
+
                 formDatum: {
                     userimg: '',
                     nickname: '',
@@ -361,6 +383,11 @@
             },
             setRightSelect(act) {
                 switch (act) {
+                    case 'system':
+                        this.systemSetting(false);
+                        this.systemDrawerShow = true;
+                        break;
+
                     case 'user':
                         this.userDrawerShow = true;
                         break;
@@ -379,10 +406,39 @@
                     },
                 });
             },
+            systemSetting(save) {
+                this.loadIng++;
+                $A.aAjax({
+                    url: 'system/setting?type=' + (save ? 'save' : 'get'),
+                    data: this.formSystem,
+                    complete: () => {
+                        this.loadIng--;
+                    },
+                    success: (res) => {
+                        if (res.ret === 1) {
+                            this.formSystem = res.data;
+                            if (!this.formSystem.reg) {
+                                this.formSystem.reg = 'open';
+                            }
+                            if (save) {
+                                this.$Message.success(this.$L('修改成功'));
+                            }
+                        } else {
+                            if (save) {
+                                this.$Modal.error({title: this.$L('温馨提示'), content: res.msg });
+                            }
+                        }
+                    }
+                });
+            },
             handleSubmit(name) {
                 this.$refs[name].validate((valid) => {
                     if (valid) {
                         switch (name) {
+                            case "formSystem": {
+                                this.systemSetting(true);
+                                break;
+                            }
                             case "formDatum": {
                                 this.loadIng++;
                                 $A.aAjax({

+ 4 - 1
resources/assets/js/main/components/chat/message.vue

@@ -134,6 +134,9 @@
             .item-username {
                 text-align: right;
             }
+            .item-link {
+                transform-origin: right center;
+            }
         }
         .item-userimg {
             width: 38px;
@@ -189,7 +192,7 @@
         padding: 0 5px;
         border-radius: 4px;
         transform: scale(0.96);
-        transform-origin: 0 0;
+        transform-origin: left center;
         > a {
             color: #3D90E2;
             padding-left: 3px;

+ 5 - 5
resources/assets/js/main/components/project/users.vue

@@ -68,6 +68,11 @@
                     });
                 }
             }, {
+                "title": this.$L("用户名"),
+                "key": 'username',
+                "minWidth": 80,
+                "ellipsis": true,
+            }, {
                 "title": this.$L("昵称"),
                 "minWidth": 80,
                 "ellipsis": true,
@@ -75,11 +80,6 @@
                     return h('span', params.row.nickname || '-');
                 }
             }, {
-                "title": this.$L("用户名"),
-                "key": 'username',
-                "minWidth": 80,
-                "ellipsis": true,
-            }, {
                 "title": this.$L("职位/职称"),
                 "minWidth": 100,
                 "ellipsis": true,

+ 69 - 6
resources/assets/js/main/pages/index.vue

@@ -90,8 +90,6 @@
 
         <Modal
             v-model="loginShow"
-            :title="$L('用户登录')"
-            :closable="false"
             :mask-closable="false">
             <Form ref="login" :model="formLogin" :rules="ruleLogin">
                 <FormItem prop="username">
@@ -104,15 +102,46 @@
                         <Icon type="ios-lock-outline" slot="prepend"></Icon>
                     </Input>
                 </FormItem>
+                <FormItem v-if="loginType=='reg'" prop="userpass2">
+                    <Input type="password" v-model="formLogin.userpass2" :placeholder="$L('确认密码')" @on-enter="onLogin">
+                        <Icon type="ios-lock-outline" slot="prepend"></Icon>
+                    </Input>
+                </FormItem>
             </Form>
+            <div slot="header" class="login-header">
+                <div @click="loginType='login'" class="login-header-item" :class="{active:loginType=='login'}">{{$L('用户登录')}}</div>
+                <div v-if="regOpen" @click="loginType='reg'" class="login-header-item" :class="{active:loginType=='reg'}">{{$L('注册账号')}}</div>
+            </div>
             <div slot="footer">
                 <Button type="default" @click="loginShow=false">{{$L('取消')}}</Button>
-                <Button type="primary" :loading="loadIng > 0" @click="onLogin">{{$L('登录')}}</Button>
+                <Button type="primary" :loading="loadIng > 0" @click="onLogin">{{$L(loginType=='reg'?'注册':'登录')}}</Button>
             </div>
         </Modal>
     </div>
 </template>
 
+<style lang="scss">
+    .login-header {
+        display: flex;
+        align-items: center;
+        .login-header-item {
+            height: 20px;
+            line-height: 20px;
+            font-size: 14px;
+            color: #444444;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+            padding-right: 12px;
+            cursor: pointer;
+            &.active {
+                font-size: 16px;
+                color: #17233d;
+                font-weight: 500;
+            }
+        }
+    }
+</style>
 <style lang="scss" scoped>
     .index {
         position: absolute;
@@ -323,11 +352,14 @@
             return {
                 loadIng: 0,
                 loginShow: false,
+                loginType: 'login',
                 formLogin: {
                     username: '',
-                    userpass: ''
+                    userpass: '',
+                    userpass2: ''
                 },
-                ruleLogin: {}
+                ruleLogin: {},
+                regOpen: false,
             }
         },
         created() {
@@ -339,12 +371,43 @@
                 userpass: [
                     { required: true, message: this.$L('请填写登录密码!'), trigger: 'change' },
                     { type: 'string', min: 6, message: this.$L('密码错长度至少6位!'), trigger: 'change' }
+                ],
+                userpass2: [
+                    { required: true, message: this.$L('请填写确认密码!'), trigger: 'change' },
+                    { type: 'string', min: 6, message: this.$L('确认密码错长度至少6位!'), trigger: 'change' },
+                    {
+                        validator: (rule, value, callback) => {
+                            if (value !== this.formLogin.userpass) {
+                                callback(new Error(this.$L('两次密码输入不一致!')));
+                            } else {
+                                callback();
+                            }
+                        },
+                        required: true,
+                        trigger: 'change'
+                    },
                 ]
             };
         },
         deactivated() {
             this.loginShow = false;
         },
+        watch: {
+            loginShow(val) {
+                if (val) {
+                    $A.aAjax({
+                        url: 'system/setting',
+                        success: (res) => {
+                            if (res.ret === 1) {
+                                this.regOpen = res.data.reg || 'open';
+                            }
+                        }
+                    });
+                } else {
+                    this.loginType = 'login';
+                }
+            }
+        },
         methods: {
             loginChack() {
                 if ($A.getToken() !== false) {
@@ -358,7 +421,7 @@
                     if (valid) {
                         this.loadIng++;
                         $A.ajax({
-                            url: $A.urlApi('users/login'),
+                            url: $A.urlApi('users/login?type=' + this.loginType),
                             data: this.formLogin,
                             complete: () => {
                                 this.loadIng--;

+ 18 - 5
resources/assets/js/main/pages/team.vue

@@ -136,17 +136,30 @@
                     });
                 }
             }, {
-                "title": this.$L("昵称"),
+                "title": this.$L("用户名"),
+                "key": 'username',
                 "minWidth": 80,
                 "ellipsis": true,
                 render: (h, params) => {
-                    return h('span', params.row.nickname || '-');
+                    let arr = [];
+                    if (params.row.username == $A.getUserName()) {
+                        arr.push(h('span', {
+                            style: {
+                                color: '#ff0000',
+                                paddingRight: '4px'
+                            }
+                        }, '[自己]'))
+                    }
+                    arr.push(h('span', params.row.username))
+                    return h('span', arr);
                 }
             }, {
-                "title": this.$L("用户名"),
-                "key": 'username',
+                "title": this.$L("昵称"),
                 "minWidth": 80,
                 "ellipsis": true,
+                render: (h, params) => {
+                    return h('span', params.row.nickname || '-');
+                }
             }, {
                 "title": this.$L("职位/职称"),
                 "minWidth": 100,
@@ -202,7 +215,7 @@
                                         loading: true,
                                         onOk: () => {
                                             $A.aAjax({
-                                                url: 'users/team/delete?id=' + params.row.id,
+                                                url: 'users/team/delete?username=' + params.row.username,
                                                 error: () => {
                                                     this.$Modal.remove();
                                                     alert(this.$L('网络繁忙,请稍后再试!'));

+ 3 - 0
routes/web.php

@@ -22,6 +22,9 @@ Route::prefix('api')->middleware(ApiMiddleware::class)->group(function () {
     //聊天
     Route::any('chat/{method}',                     'Api\ChatController');
     Route::any('chat/{method}/{action}',            'Api\ChatController');
+    //系统
+    Route::any('system/{method}',                   'Api\SystemController');
+    Route::any('system/{method}/{action}',          'Api\SystemController');
 });