ThinkAdmin使用

1,313 阅读2分钟

前言

ThinkAdmin是基于thinkphp开发的后台管理系统,较为容易上手。

它有完整的商城系统和用户管理系统。

介绍在文档里有我就不过多赘述,这里主要整理一些使用时的情况

目录结构

.
├─ app                              应用基础目录
│  ├─ admin                         后台应用目录
│  │  ├─ controller                 应用控制器
│  │  ├─ route                      应用路由配置
│  │  ├─ view                       应用视图目录
│  │  └─ sys.php                    模块注册文件
│  ├─ index                         默认应用入口
│  │  └─ controller                 控制器目录
│  └─ wechat                        微信应用目录
│     ├─ command                    应用指令目录
│     ├─ controller                 控制器目录
│     ├─ service                    应用服务目录
│     ├─ view                       应用视图目录
│     └─ sys.php                    模块注册文件
├─ config                           全局配置目录
│  ├─ app.php                       应用配置
│  ├─ cache.php                     缓存配置 
│  ├─ cookie.php                    Cookie 配置
│  ├─ database.php                  数据库配置
│  ├─ filesystem.php                文件磁盘配置
│  ├─ lang.php                      系统多语言配置
│  ├─ log.php                       全局日志配置
│  ├─ route.php                     URL和路由配置
│  ├─ session.php                   Session 配置   
│  └─ view.php                      视图配置 
├─ public                           网站开放目录
│  ├─ static                        静态资源目录
│  │  ├─ plugs                      后台应用插件
│  │  └─ theme                      后台应用主题
│  ├─ upload                        上传存储目录
│  ├─ index.php                     网站访问入口
│  ├─ router.php                    网站测试入口
│  └─ think                         指令访问入口
├─ runtime                          应用的运行时目录,需要可写权限
│  ├─ admin                         系统应用运行目录
│  ├─ cache                         系统默认缓存目录
│  ├─ log                           系统指令运行日志
│  ├─ session                       Session 会话缓存
│  └─ wechat                        微信应用运行目录
├─ safefile                         安全文件上传目录
└─ vendor                           Composer 安装的第三方类库目录

用户相关

对于前端的一些接口都是放在data目录下的,请求头都需要添加api-type用于后续token验证

注册

/data/api.login/register

测试的时候直接将手机验证注释了

   public function register()
    {
        $data = $this->_vali([
            'region_province.default' => '',
            'region_city.default'     => '',
            'region_area.default'     => '',
            'username.default'        => '',
            'phone.mobile'            => '手机格式错误!',
            'phone.require'           => '手机不能为空!',
            'verify.require'          => '验证码不能为空!',
            'password.require'        => '登录密码不能为空!',
        ]);
		//隐藏需要手机验证
        // if (!MessageService::instance()->checkVerifyCode($data['verify'], $data['phone'])) {
        //     $this->error('手机短信验证失败!');
        // }
        $map = ['phone' => $data['phone'], 'deleted' => 0];
        if (DataUser::mk()->where($map)->count() > 0) {
            $this->error('手机号已注册,请使用其它手机号!');
        }
        $data['password'] = md5($data['password']);
        $user = UserAdminService::set($map, $data, $this->type, true);
        empty($user) ? $this->error('手机注册失败!') : $this->success('用户注册成功!', $user);
    }

登录

登录主要用于获取token,有关个人用户的数据是需要token验证的

/data/api.login/in
    public function in()
    {
        $data = $this->_vali([
            'phone.mobile'     => '手机号码格式错误!',
            'phone.require'    => '手机号码不能为空!',
            'password.require' => '登录密码不能为空!',
        ]);
        $map = ['deleted' => 0, 'phone' => $data['phone']];
        $user = DataUser::mk()->where($map)->find();
        if (empty($user)) $this->error('该手机号还没有注册哦!');
        if (empty($user['status'])) $this->error('该用户账号状态异常!');
        if (md5($data['password']) === $user['password']) {
            $this->success('手机登录成功!', UserAdminService::set($map, [], $this->type, true));
        } else {
            $this->error('账号登录失败,请稍候再试!');
        }
    }

授权

查看Auth文件可知,初始化的时候需要传api-type判断类型

    /**
     * 控制器初始化
     */
    protected function initialize()
    {
        // 接收接口类型
        $this->type = $this->request->request('api');
        $this->type = $this->type ?: $this->request->header('api-name');
        $this->type = $this->type ?: $this->request->header('api-type');
        // 检查接口类型
        if (empty($this->type)) {
            $this->error("未获取到接口类型字段!");
        }
        if (!isset(UserAdminService::TYPES[$this->type])) {
            $this->error("接口类型[{$this->type}]未定义!");
        }
        // 获取用户数据
        $this->user = $this->getUser();
        $this->uuid = $this->user['id'] ?? '';
        if (empty($this->uuid)) {
            $this->error('用户登录失败!', '{-null-}', 401);
        }
    }

检测授权是需要api-token用来判断用户

    protected function getUser(): array
    {
        try {
            if (empty($this->uuid)) {
                $token = input('token') ?: $this->request->header('api-token');
                if (empty($token)) $this->error('登录认证TOKEN不能为空!');
                [$state, $info, $this->uuid] = UserTokenService::instance()->check($this->type, $token);
                if (empty($state)) $this->error($info, '{-null-}', 401);
            }
            return UserAdminService::instance()->get($this->uuid, $this->type);
        } catch (HttpResponseException $exception) {
            throw $exception;
        } catch (\Exception $exception) {
            trace_file($exception);
            $this->error($exception->getMessage());
        }
    }

UserTokenService中检测token是否合规

  public static function check(string $type, string $token, array $data = []): array
    {
        if (empty($data)) {
            $map = ['type' => $type, 'token' => $token];
            $data = DataUserToken::mk()->where($map)->find();
        }
        if (empty($data) || empty($data['uuid'])) {
            return [0, '请重新登录,登录认证无效', 0, 0];
        } elseif ($token !== 'token' && $data['time'] < time()) {
            return [0, '请重新登录,登录认证失效', 0, 0];
        } elseif ($token !== 'token' && $data['tokenv'] !== static::buildVerify()) {
            return [0, '请重新登录,客户端已更换', 0, 0];
        } else {
            static::expire($type, $token);
            return [1, '登录验证成功', $data['uuid'], $data['time']];
        }
    }

查询用户

/data/api.auth.center/get

用户的数据是从DataUser拿到的

<?php

namespace app\data\model;

use think\admin\Model;

/**
 * 用户数据模型
 * Class DataUser
 * @package app\data\model
 */
class DataUser extends Model
{

}

对应数据表data_user

image.png

image.png

    public static function get(int $uuid, string $type): array
    {
        $map = ['id' => $uuid, 'deleted' => 0];
        $user = DataUser::mk()->where($map)->findOrEmpty();
        if ($user->isEmpty()) throw new Exception('用户还没有注册!');
        // 用户认证令牌处理
        $map = ['uuid' => $uuid, 'type' => $type];
        if (!($access = DataUserToken::mk()->where($map)->find())) {
            [$state, $message, $access] = UserTokenService::token($uuid, $type);
            if (empty($state) || empty($access)) throw new Exception($message);
        }
        $user['token'] = ['token' => $access['token'], 'expire' => $access['time']];
        return $user->hidden(['deleted', 'password'])->toArray();
    }