Browse Source

feat(proxy): 新增代理用户管理功能

- 新增 ProxyBaseDao 抽象基类,提供通用数据访问方法
- 新增 ProxyUserController 控制器,实现用户增删改查接口
- 新增 ProxyUserService 服务类,处理代理用户业务逻辑
- 新增 ProxyUserValidate 验证器,校验用户输入参数
- 新增代理用户相关路由配置,包括保存、更新、列表、详情、删除和封禁功能
- 新增 RequestUtils 工具类方法,获取代理用户信息
- 新增统计模块头部信息接口路由
- 实现用户密码加密存储和验证
- 实现用户账号唯一性校验
- 实现用户软删除功能
- 实现用户状态封禁/解封功能
- 添加事务处理确保数据一致性
- 添加分页和排序参数处理
- 添加字段默认值自动填充功能
master
zhangf@suq.cn 2 days ago
parent
commit
704624f980
  1. 6
      app/route/route.php
  2. 798
      plugin/piadmin/app/base/ProxyBaseDao.php
  3. 6
      plugin/piadmin/app/base/UserBaseDao.php
  4. 78
      plugin/piadmin/app/controller/v1/ProxyUserController.php
  5. 37
      plugin/piadmin/app/controller/v1/UserController.php
  6. 20
      plugin/piadmin/app/route/v1/route.php
  7. 152
      plugin/piadmin/app/service/ProxyUserService.php
  8. 151
      plugin/piadmin/app/service/UserService.php
  9. 24
      plugin/piadmin/app/utils/RequestUtils.php
  10. 38
      plugin/piadmin/app/validate/ProxyUserValidate.php

6
app/route/route.php

@ -9,12 +9,18 @@ use app\controller\EnterprisePortraitCategoryController;
use app\controller\EnterprisePortraitLibraryController;
use app\controller\ExpiosiveReplicaController;
use app\controller\GlobalProxyController;
use app\controller\IndexController;
use app\controller\KnowledgeLibraryController;
use app\controller\DistillationWordController;
use plugin\piadmin\app\middleware\UserAuthorizationMiddleware;
use Webman\Route;
Route::group('/service/v1', function () {
//控制台
Route::group('/statistic', function () {
Route::get('/head', [IndexController::class, 'head'])->setParams(['perm' => ['indexHead']]);
});
//蒸馏词
Route::group('/distillation', function () {
//新增

798
plugin/piadmin/app/base/ProxyBaseDao.php

@ -0,0 +1,798 @@
<?php
namespace plugin\piadmin\app\base;
use plugin\piadmin\app\exception\ApiException;
use plugin\piadmin\app\utils\RequestUtils;
use ReflectionException;
use think\Collection;
use think\db\exception\DbException;
use think\facade\Db;
use think\helper\Str;
use think\Model;
/**
* 抽象基类,提供数据访问对象(DAO)的基本结构和通用方法
* 该类不能直接实例化,旨在被其他DAO类继承,以利用其定义的通用功能
* 主要作用包括:
* - 定义了子类必须实现的抽象方法
* - 提供了数据库连接的通用逻辑(假设实现)
* - 其他通用数据操作方法的模板
*/
abstract class ProxyBaseDao
{
/**
* 当前表名别名
* @var string
*/
protected string $alias;
/**
* join表别名
* @var string
*/
protected string $joinAlis;
/**
* 获取当前模型
* @return string
*/
abstract protected function setModel(): string;
/**
* 设置join链表模型
* @return string
*/
protected function setJoinModel(): string
{
return '';
}
/**
* 读取数据条数
* @param array $where
* @param bool $search
* @return int
* @throws ReflectionException|DbException
*/
public function count(array $where = [], bool $search = true): int
{
return $this->search($where, $search)->count();
}
/**
* 根据指定条件选择数据列表
*
* 此方法用于根据多个条件查询数据,并支持分页、排序和关联加载等功能
* 它是构建复杂查询的一个灵活入口点,允许开发者指定所需的查询条件和选项,
* 并获取一个数据集合作为结果返回
*
* @param array $where 查询条件数组,用于指定查询的过滤条件
* @param string $field 要查询的字段,默认为 '*',表示查询所有字段
* @param int $page 分页页码,默认为 0,表示不分页
* @param int $limit 每页数据条数,默认为 0,表示不限制条数
* @param string $order 排序条件字符串,默认为空,表示不排序
* @param array $with 关联加载数组,用于指定要加载的关联关系
* @param bool $search 是否使用搜索模式,默认为 false
*
* @return Collection 查询结果集合
* @throws ReflectionException
*/
public function selectList(array $where, string $field = '*', int $page = 0, int $limit = 0,
string $order = '', array $with = [], bool $search = false): Collection
{
return $this->selectModel($where, $field, $page, $limit, $order, $with, $search)->select();
}
/**
* 根据查询条件构造模型
* @param array $where
* @param string $field
* @param int $page
* @param int $limit
* @param string $order
* @param array $with
* @param bool $search
* @return BaseModel
* @throws ReflectionException
*/
private function selectModel(array $where, string $field = '*', int $page = 0, int $limit = 0, string $order = '', array $with = [], bool $search = false): mixed
{
if ($search) {
$model = $this->search($where);
} else {
$model = $this->getModel()->where($where);
}
return $model->field($field)->when($page && $limit, function ($query) use ($page, $limit) {
$query->page($page, $limit);
})->when($order !== '', function ($query) use ($order) {
$query->order($order);
})->when($with, function ($query) use ($with) {
$query->with($with);
});
}
/**
* 获取满足条件的记录数
*
* 该方法用于执行一个查询,以获取数据库中满足给定条件的记录数
* 它通过传递一个数组参数来指定查询条件,然后使用模型的where方法来过滤数据,
* 最后使用count方法来统计满足条件的记录数
*
* @param array $where 查询条件数组,用于指定过滤条件
* @return int 满足条件的记录数
*/
public function getCount(array $where): int
{
return $this->getModel()->where($where)->count();
}
/**
* 获取唯一值的计数
*
* 该方法用于计算给定字段在特定条件下的唯一值数量根据$search参数的值,
* 选择使用search方法还是getModel方法来执行查询
*
* @param array $where 查询条件,用于筛选记录
* @param string $field 需要计算唯一值的字段名称
* @param bool $search 指示是否使用search方法来执行查询,默认为true如果为false,则使用getModel方法
*
* @return int 返回计算得到的唯一值数量如果没有匹配的记录,返回0
*/
public function getDistinctCount(array $where, $field, bool $search = true): int
{
if ($search) {
// 使用search方法执行查询,并计算指定字段的唯一值数量
return $this->search($where)->field('COUNT(distinct(' . $field . ')) as count')->select()->toArray()[0]['count'] ?? 0;
} else {
// 使用getModel方法执行查询,并计算指定字段的唯一值数量
return $this->getModel()->where($where)->field('COUNT(distinct(' . $field . ')) as count')->select()->toArray()[0]['count'] ?? 0;
}
}
/**
* 获取模型
* @return BaseModel
*/
public function getModel(): BaseModel
{
return app()->make($this->setModel());
}
/**
* 获取主键
* @return array|string
*/
protected function getPk(): array|string
{
return $this->getModel()->getPk();
}
/**
* 获取模型对应的表名
* @return string
*/
public function getTableName(): string
{
return $this->getModel()->getName();
}
/**
* 根据主键获取一条或多条数据
* @param $id
* @param array|null $field
* @param array|null $with
* @return array|Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function get($id, ?array $field = [], ?array $with = []): array|Model|null
{
if (is_array($id)) {
$where = $id;
} else {
$where = [$this->getPk() => $id];
}
return $this->getModel()->where($where)->when(count($with), function ($query) use ($with) {
$query->with($with);
})->field($field ?? ['*'])->find();
}
/**
* 查询一条数据是否存在
* @param $map
* @param string $field
* @return bool 是否存在
*/
public function be($map, string $field = '')
{
if (!is_array($map) && empty($field)) $field = $this->getPk();
$map = !is_array($map) ? [$field => $map] : $map;
return 0 < $this->getModel()->where($map)->count();
}
/**
* 根据条件获取一条数据
* @param array $where
* @param string|null $field
* @param array $with
* @return array|Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getOne(array $where, ?string $field = '*', array $with = [])
{
$field = explode(',', $field);
return $this->get($where, $field, $with);
}
/**
* 获取单个字段值
* @param $where
* @param string|null $field
* @param string $order
* @return mixed
*/
public function value($where, ?string $field = '', string $order = ''): mixed
{
$pk = $this->getPk();
return $this->getModel()->where($where)->order($order)->value($field ?: $pk);
}
/**
* 根据条件查询某一列数据
* @param array $where
* @param string $field
* @param string $key
* @return array
*/
public function getColumn(array $where, string $field, string $key = ''): array
{
return $this->getModel()->where($where)->column($field, $key);
}
/**
* 删除记录
*
* 该方法支持根据单个或多个条件删除记录当$id为数组时,表示根据多个条件删除记录;
* $id为单个值时,表示根据主键或指定的$key删除记录
*
* @param array|int|string $id 要删除的记录的ID或条件数组
* @param string|null $key $id为单个值时,指定的字段名,默认为主键
*
* @return bool 成功删除返回true,否则返回false
*/
public function delete(array|int|string $id, ?string $key = null): bool
{
// 判断$id是否为数组,如果是,则直接使用$id作为删除条件
if (is_array($id)) {
$where = $id;
} else {
// 如果$id不是数组,则根据是否设置了$key来决定使用主键还是$key作为删除条件
$where = [is_null($key) ? $this->getPk() : $key => $id];
}
// 使用确定的删除条件执行删除操作,并返回删除结果
return $this->getModel()->where($where)->delete();
}
/**
* 强制删除记录
*
* 该方法用于删除一个指定ID的资源。可以根据$force参数决定是软删除还是硬删除。
*
* @param int $id 要删除的资源的ID
* @param bool $force 是否强制删除,true为硬删除,false为软删除(默认)
* @return mixed 删除操作的结果,具体类型取决于getModel()->destroy方法的返回值
*/
public function destroy(int $id, bool $force = false)
{
return $this->getModel()->destroy($id, $force);
}
/**
* 更新数据
*
* 该方法用于更新数据库中与给定ID或条件相符的记录它接受一个ID(可以是数组、整数或字符串),
* 一个包含要更新的数据的数组,和一个可选的键名称如果ID是一个数组,它将直接用作查询条件
* 否则,它将与主键或提供的键名称一起构建查询条件
*
* @param array|int|string $id 要更新的记录的ID,可以是数组、整数或字符串如果是数组,则视为查询条件
* @param array $data 要更新的数据,以数组形式提供
* @param string|null $key 可选的键名称,用于指定查询时使用的键如果未提供,则使用主键
* @return mixed 更新操作的结果,具体类型取决于底层数据库操作
*/
public function update(array|int|string $id, array $data, ?string $key = null): mixed
{
// 根据$id的类型和$key的值构建查询条件
if (is_array($id)) {
$where = $id;
} else {
$where = [is_null($key) ? $this->getPk() : $key => $id];
}
// 调用模型的update方法执行数据库更新操作
return $this->getModel()::update($data, $where);
}
/**
* @param $where
* @return array|mixed
*/
protected function setWhere($where, ?string $key = null): mixed
{
if (!is_array($where)) {
$where = [is_null($key) ? $this->getPk() : $key => $where];
}
return $where;
}
/**
* 批量更新记录
*
* 该方法用于根据一组ID批量更新数据库中的记录它允许指定更新的数据以及可选的键,
* 如果未提供键,则使用主键进行更新操作
*
* @param array $ids 需要更新的记录的ID数组
* @param array $data 要更新的数据,以键值对形式表示
* @param string|null $key 可选参数,用于指定更新操作使用的键如果未提供,则默认使用主键
* @return BaseModel 更新操作的结果,
*/
public function batchUpdate(array $ids, array $data, ?string $key = null): BaseModel
{
// 获取模型实例,并使用whereIn方法来匹配IDs,如果$key为null,则使用主键
// 这里使用了三元运算符来判断$key是否为null,从而决定使用哪个键进行查询
// 最后调用update方法来执行批量更新操作
return $this->getModel()->whereIn(is_null($key) ? $this->getPk() : $key, $ids)->update($data);
}
/**
* 保存数据到模型
*
* 该方法主要用于将给定的数据数组保存到与模型关联的数据库表中它首先获取模型的字段信息,
* 然后对数据进行预处理,包括设置一些特殊字段的默认值最后,使用处理后的数据创建一个新的模型实例
*
* @param array $data 要保存到模型的数据数组
*/
public function save(array $data): BaseModel
{
// 获取模型的字段信息
$fields = $this->getModelField();
// 对数据进行预处理,设置特殊字段的默认值
$data = $this->setSpecialFieldDefaultValue($data,$fields);
// 使用处理后的数据创建并返回新的模型实例
return $this->getModel()::create($data);
}
/**
* 批量保存数据
*
* @param array $data 要保存的数据数组,每个元素代表一条记录
* @param bool $replace 是否使用替换插入的方式,默认为true
*
* @return mixed 保存结果,具体取决于底层数据库操作的返回值
* @throws \Exception
*/
public function saveAll(array $data, bool $replace = true): mixed
{
// 获取模型字段信息,为后续数据处理做准备
$fields = $this->getModelField();
// 初始化用于保存处理后数据的数组
$saveData = [];
// 遍历传入的数据数组,对每条记录进行处理
foreach ($data as $v) {
// 设置特殊字段的默认值,并将处理后的数据添加到保存数组中
$saveData[] = $this->setSpecialFieldDefaultValue($v,$fields);
}
// 调用模型的saveAll方法,批量保存处理后的数据
return $this->getModel()->saveAll($saveData, $replace);
}
/**
* 批量插入数据
*
* 该方法主要用于批量插入数据到数据库中它首先获取模型的字段信息,然后对输入的数据进行处理,
* 设置一些特殊字段的默认值,最后将处理后的数据批量插入数据库
*
* @param array $data 要插入的数据数组,每个元素代表一行数据
* @return int 插入操作影响的行数
*/
public function insertAll(array $data): int
{
// 获取模型字段信息,用于后续处理数据时参考
$fields = $this->getModelField();
// 初始化一个空数组,用于存储处理后的数据
$saveData = [];
// 遍历输入的数据数组
foreach ($data as $v) {
// 对每行数据,设置特殊字段的默认值,并将处理后的数据添加到保存数组中
$saveData[] = $this->setSpecialFieldDefaultValue($v,$fields);
}
// 调用模型的批量插入方法,插入处理后的数据,并返回插入操作影响的行数
return $this->getModel()->insertAll($saveData);
}
private function setSpecialFieldDefaultValue($data, $fields)
{
// if(in_array('id',$fields)){
// $data['id'] = $data['id'] ?? IdUtils::uuid();
// }
// if(session(('user'))){
// if(in_array('create_by',$fields)){
// $data['create_by'] = $data['create_by'] ?? session('user')['uid'];
// }
// if(in_array('update_by',$fields)){
// $data['update_by'] = $data['update_by'] ?? session('user')['uid'];
// }
// }
$proxyUserInfo = RequestUtils::getProxyInfo();
if($proxyUserInfo){
if(in_array('create_by',$fields)){
$data['create_by'] = $data['create_by'] ?? $proxyUserInfo['id'];
}
if(in_array('update_by',$fields)){
$data['update_by'] = $data['update_by'] ?? $proxyUserInfo['id'];
}
}
if(in_array('create_time',$fields)){
$data['create_time'] = $data['create_time'] ?? time();
}
if(in_array('update_time',$fields)){
$data['update_time'] = $data['update_time'] ?? time();
}
return $data;
}
/**
* 获取搜索器和搜索条件key,以及不在搜索器的条件数组
* @param array $where
* @return array[]
* @throws ReflectionException
*/
private function getSearchData(array $where)
{
$with = [];
$otherWhere = [];
$responses = new \ReflectionClass($this->setModel());
foreach ($where as $key => $value) {
if($value === '' || $value === null){
continue;
}
$method = 'search' . Str::studly($key) . 'Attr';
if ($responses->hasMethod($method)) {
$with[] = $key;
} else {
if(!in_array($key,['user'])){
if (!is_array($value)) {
$otherWhere[] = [$key, '=', $value];
} else if (count($value) === 3) {
$otherWhere[] = $value;
}
}
}
}
return [$with, $otherWhere];
}
/**
* 根据搜索器获取搜索内容
* @param $where
* @param $search
* @return BaseModel
* @throws ReflectionException
*/
protected function withSearchSelect($where, $search)
{
[$with, $otherWhere] = $this->getSearchData($where);
return $this->getModel()->withSearch($with, $where)->when($search, function ($query) use ($otherWhere) {
$query->where($this->filterWhere($otherWhere));
});
}
/**
* 过滤数据表中不存在的where条件字段
* @param array $where
* @return array
*/
protected function filterWhere(array $where = []): array
{
$fields = $this->getModel()->getTableFields();
foreach ($where as $key => $item) {
// 带有表别名前缀的去掉前缀
$cols = explode('.', $item[0]);
$col = $cols[count($cols) - 1];
if (!in_array($col, $fields)) {
unset($where[$key]);
}
}
return $where;
}
/**
* 根据给定的条件搜索模型
*
* 当提供了一个非空的条件数组时,该方法会执行一个带有搜索条件的查询;
* 如果条件数组为空,则直接返回模型实例
*
* @param array $where 搜索条件数组,用于指定查询条件,默认为空数组
* @param bool $search 是否执行搜索的标志,用于控制是否应用搜索条件,默认为true
*
* @return mixed 返回一个BaseModel实例,具体类型取决于getModel和withSearchSelect方法的返回值
*/
public function search(array $where = [], bool $search = true): mixed
{
// 判断是否有搜索条件提供
if ($where) {
//载入数据权限
$proxyUserInfo = RequestUtils::getProxyInfo();
$where[] = ['create_by', 'in', $proxyUserInfo['dataPermission']];
// 如果有搜索条件,则调用withSearchSelect方法执行带有搜索条件的查询
return $this->withSearchSelect($where, $search);
} else {
// 如果没有搜索条件,则直接返回模型实例
return $this->getModel();
}
}
/**
* 求和
* @param array $where
* @param string $field
* @param bool $search
* @return float
* @throws ReflectionException
*/
public function sum(array $where, string $field, bool $search = false): float
{
if ($search) {
return $this->search($where)->sum($field);
} else {
return $this->getModel()->where($where)->sum($field);
}
}
/**
* 高精度加法
* @param $key
* @param string $incField
* @param string $inc
* @param string|null $keyField
* @param int $acc
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function bcInc($key, string $incField, string $inc, string $keyField = null, int $acc = 2): bool
{
return $this->bc($key, $incField, $inc, $keyField, 1);
}
/**
* 高精度 减法
* @param $key
* @param string $decField
* @param string $dec
* @param string|null $keyField
* @param int $acc
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function bcDec($key, string $decField, string $dec, string $keyField = null, int $acc = 2): bool
{
return $this->bc($key, $decField, $dec, $keyField, 2);
}
/**
* 高精度计算并保存
* @param $key
* @param string $incField
* @param string $inc
* @param string|null $keyField
* @param int $type
* @param int $acc
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function bc($key, string $incField, string $inc, string $keyField = null, int $type = 1, int $acc = 2): bool
{
if ($keyField === null) {
$result = $this->get($key);
} else {
$result = $this->getOne([$keyField => $key]);
}
if (!$result) return false;
$new = 0;
if ($type === 1) {
$new = bcadd($result[$incField], $inc, $acc);
} else if ($type === 2) {
if ($result[$incField] < $inc) return false;
$new = bcsub($result[$incField], $inc, $acc);
}
$result->{$incField} = $new;
return false !== $result->save();
}
/**
* 获取条件数据中的某个值的最大值
* @param array $where
* @param string $field
* @return mixed
*/
public function getMax(array $where = [], string $field = ''): mixed
{
return $this->getModel()->where($where)->max($field);
}
/**
* 获取条件数据中的某个值的最小值
* @param array $where
* @param string $field
* @return mixed
*/
public function getMin(array $where = [], string $field = ''): mixed
{
return $this->getModel()->where($where)->min($field);
}
/**
* 软删除
* @param string $id
* @return mixed
*/
public function softDel(string $id): mixed
{
return $this->getModel()->where('id', $id)->update(['delete_time' => time()]);
}
/**
* 保存唯一验证
* @param array $where
* @param string $msg
*/
public function saveUnique(array $where, string $msg = '', $field = '*'): void
{
$res = $this->getModel()->field($field)->where($where)->findOrEmpty()->toArray();
if (!empty($res)) {
throw new ApiException($msg);
}
}
/**
* 更新唯一验证
* @param array $where
* @param int $id
* @param string $msg
*/
public function updateUnique(array $where, $id, string $msg = '', $field = '*'): void
{
$res = $this->getModel()->field($field)->where($where)->findOrEmpty()->toArray();
if (!empty($res) && $res['id'] != $id) {
throw new ApiException($msg);
}
}
public function getList($where, $field='*', $page=0, $limit=0, $order='id desc',$with=[],$withCOunt=[]): array
{
$query = $this->search($where)->field($field)->with($with)->withCount($withCOunt)->order($order);
if($page !== 0 && $limit !== 0){
$query = $query->page($page,$limit);
}
return $query->select()->toArray();
}
/**
* 批量插入或更新
* @param array $data
* @param string $duplicateKey
* @return bool
* @throws ApiException
*/
public function batchInsertOrUpdate(array $data,$duplicateKey = 'id'): bool
{
if(empty($data)){
return true;
}
// update on duplicate key
$fields = $this->getModel()->getTableFields();
// 获取所有字段
$userFields = array_keys($data[0]);
// 检查字段是否存在
foreach ($userFields as $field) {
if (!in_array($field, $fields)) {
throw new ApiException($field . '字段不存在',400 );
}
}
$fields = $userFields;
$table = $this->getModel()->getTable();
// 将数据转换为 SQL 语句中的值部分
$values = [];
foreach ($data as $row) {
$valueStr = '(' . implode(',', array_map(function ($value) {
return "'" . addslashes($value) . "'";
}, $row)) . ')';
$values[] = $valueStr;
}
// 构建更新部分的 SQL 语句
$updateStr = '';
foreach ($fields as $field) {
// 移除duplicateKey
if($field == $duplicateKey){
continue;
}
$updateStr .= "`$field` = VALUES(`$field`),";
}
// 构建字段部分的 SQL 语句
$fieldStr = implode(',', array_map(function ($field) {
return "`$field`";
}, $fields));
// 移除最后一个逗号
$updateStr = rtrim($updateStr, ',');
// 构建完整的 SQL 语句
$sql = "INSERT INTO {$table} ({$fieldStr}) VALUES " . implode(',', $values) . " ON DUPLICATE KEY UPDATE {$updateStr}";
// 使用 execute 方法执行 SQL 语句
return Db::execute($sql);
}
/**
* 根据条件更新数据
* @param array $where
* @param array $data
*/
public function updateByWhere(array $where, array $data)
{
return $this->getModel()->where($where)->update($data);
}
/**
* 获取模型字段列表
*
* 该方法用于获取当前模型所在表的所有字段名称
* 它通过查询数据库表的列信息来实现
*
* @return array 返回字段名称数组
*/
public function getModelField(): array
{
// 获取模型对应的表名
$table = $this->getModel()->getTable();
// 执行SQL语句,获取表中所有列的详细信息
$fields = Db::query("SHOW FULL COLUMNS FROM $table");
// 从查询结果中提取所有字段名,并返回
return array_column($fields, 'Field');
}
public function __call(string $name, array $arguments)
{
return call_user_func_array([$this->getModel(), $name], $arguments);
}
}

6
plugin/piadmin/app/base/UserBaseDao.php

@ -538,11 +538,11 @@ abstract class UserBaseDao
*/
public function search(array $where = [], bool $search = true): mixed
{
//载入数据权限
$userInfo = RequestUtils::getUserInfo();
$where[] = ['create_by', 'in', $userInfo['dataPermission']];
// 判断是否有搜索条件提供
if ($where) {
//载入数据权限
$userInfo = RequestUtils::getUserInfo();
$where[] = ['create_by', 'in', $userInfo['dataPermission']];
// 如果有搜索条件,则调用withSearchSelect方法执行带有搜索条件的查询
return $this->withSearchSelect($where, $search);
} else {

78
plugin/piadmin/app/controller/v1/ProxyUserController.php

@ -0,0 +1,78 @@
<?php
namespace plugin\piadmin\app\controller\v1;
use plugin\piadmin\app\base\BaseController;
use plugin\piadmin\app\service\ProxyUserService;
use plugin\piadmin\app\utils\ArrayUtils;
use plugin\piadmin\app\validate\ProxyUserValidate;
use support\Response;
class ProxyUserController extends BaseController
{
public function save(ProxyUserService $service): Response
{
$params = requestOnly([
'name' => '',
'account' => '',
'password' => '',
'phone' => '',
'email' => '',
'status' => 1,
'gender' => 3,
]);
validate(ProxyUserValidate::class)->check($params, 'save');
return success($service->saveData($params));
}
public function update(ProxyUserService $service): Response
{
$params = requestOnly([
'id' => '',
'name' => '',
'account' => '',
'password' => '',
'phone' => '',
'email' => '',
'status' => 1,
'gender' => 3,
]);
validate(ProxyUserValidate::class)->check($params, 'update');
return success($service->updateData(ArrayUtils::filterNotEmpty($params)));
}
public function index(ProxyUserService $service): Response
{
$params = requestOnly([
'name' => '',
'email' => '',
'phone' => '',
'status' => '',
]);
return success($service->listData($params));
}
public function read(ProxyUserService $service): Response
{
$id = input('id');
return success($service->readData($id));
}
public function delete(ProxyUserService $service): Response
{
$id = input('id');
return success($service->deleteData($id));
}
public function ban(ProxyUserService $service)
{
$params = requestOnly([
'id' => '',
]);
return success($service->banProxy($params));
}
}

37
plugin/piadmin/app/controller/v1/UserController.php

@ -0,0 +1,37 @@
<?php
namespace plugin\piadmin\app\controller\v1;
use plugin\piadmin\app\base\BaseController;
use plugin\piadmin\app\service\UserService;
use support\Response;
class UserController extends BaseController
{
public function index(UserService $service): Response
{
$params = requestOnly([
'name' => '',
'email' => '',
'phone' => '',
'status' => '',
'dept_id' => ''
]);
return success($service->listData($params));
}
public function read(UserService $service): Response
{
$id = input('id');
return success($service->readData($id));
}
public function ban(UserService $service)
{
$params = requestOnly([
'id' => '',
]);
return success($service->banUser($params));
}
}

20
plugin/piadmin/app/route/v1/route.php

@ -7,6 +7,7 @@ use plugin\piadmin\app\controller\v1\ProxyMenuController;
use plugin\piadmin\app\controller\v1\SystemAdminController;
use plugin\piadmin\app\controller\v1\SystemDeptController;
use plugin\piadmin\app\controller\v1\SystemRoleController;
use plugin\piadmin\app\controller\v1\UserController;
use plugin\piadmin\app\controller\v1\UserLoginController;
use plugin\piadmin\app\controller\v1\UserMenuController;
use plugin\piadmin\app\middleware\AdminAuthorizationMiddleware;
@ -101,6 +102,25 @@ Route::group('/piadmin/v1', function () {
//封禁/解封
Route::post('/ban', [SystemAdminController::class, 'ban'])->setParams(['perm' => ['adminBan']]);
});
// 前台用户
Route::group('/user', function () {
Route::get('/index', [UserController::class, 'index'])->setParams(['perm' => ['userIndex']]);
Route::get('/read', [UserController::class, 'read'])->setParams(['perm' => ['userRead']]);
//封禁/解封
Route::post('/ban', [UserController::class, 'ban'])->setParams(['perm' => ['userBan']]);
});
// 代理用户
Route::group('/proxyUser', function () {
Route::post('/save', [SystemAdminController::class, 'save'])->setParams(['perm' => ['adminSave']]);
Route::post('/update', [SystemAdminController::class, 'update'])->setParams(['perm' => ['adminUpdate']]);
Route::get('/index', [SystemAdminController::class, 'index'])->setParams(['perm' => ['adminIndex']]);
Route::get('/read', [SystemAdminController::class, 'read'])->setParams(['perm' => ['adminRead']]);
Route::post('/delete', [SystemAdminController::class, 'delete'])->setParams(['perm' => ['adminDelete']]);
//封禁/解封
Route::post('/ban', [SystemAdminController::class, 'ban'])->setParams(['perm' => ['adminBan']]);
});
//数据字典
Route::get('/dataDictionary', [DataDictionaryController::class, 'dictionary'])->setParams(['perm' => ['dataDictionary']]);
})->middleware([

152
plugin/piadmin/app/service/ProxyUserService.php

@ -7,6 +7,8 @@ use plugin\piadmin\app\dao\ProxyUserDao;
use plugin\piadmin\app\exception\ApiException;
use plugin\piadmin\app\utils\CacheUtils;
use plugin\piadmin\app\utils\JwtUtils;
use plugin\piadmin\app\utils\RequestUtils;
use support\think\Db;
class ProxyUserService extends BaseService
{
@ -32,6 +34,156 @@ class ProxyUserService extends BaseService
return $tokenInfo;
}
/**
* 保存用户信息
* @param array $params
* @return array
*/
public function saveData(array $params): array
{
// 检查账号
$accountExist = $this->dao->be(['account' => $params['account']]);
if ($accountExist) {
throw new ApiException(4040013);
}
$params['password'] = password_hash($params['password'], PASSWORD_ARGON2I);
// 落库
Db::startTrans();
try {
// 落库
$proxyUser = $this->dao->save($params);
Db::commit();
} catch (\Exception $exception) {
Db::rollback();
throw new ApiException($exception->getMessage());
}
return $proxyUser->toArray();
}
/**
* 修改用户信息
* @param array $params
* @return array
*/
public function updateData(array $params): array
{
$proxyUser = $this->dao->get(['id' => $params['id']]);
if (empty($proxyUser)) {
throw new ApiException(trans(4040016));
}
// 检查账号
if (!empty($proxyUser['account']) && $proxyUser['account'] != $params['account']) {
$accountExist = $this->dao->be(['account' => $params['account']]);
if ($accountExist) {
throw new ApiException(4040013);
}
}
// 检查密码
if (!empty($params['password']) && !password_verify($params['password'], $proxyUser['password'])) {
$params['password'] = password_hash($params['password'], PASSWORD_ARGON2I);
}
// 落库
Db::startTrans();
try {
$this->dao->update(['id' => $params['id']], $params);
Db::commit();
} catch (\Exception $exception) {
Db::rollback();
throw new ApiException($exception->getMessage());
}
return $params;
}
/**
* 获取用户列表
* @param array $params
* @return array
*/
public function listData(array $params): array
{
[$page, $limit] = RequestUtils::getPageParameter();
[$sortRule, $sortField] = RequestUtils::getSortParameter();
$query = [];
// 账号筛选
if (isNotBlank($params['email'])) {
$query[] = ['email', 'like', '%' . $params['email'] . '%'];
}
// 名称筛选
if (isNotBlank($params['name'])) {
$query[] = ['name', 'like', '%' . $params['name'] . '%'];
}
// 手机号筛选
if (isNotBlank($params['phone'])) {
$query[] = ['phone', 'like', '%' . $params['phone'] . '%'];
}
// 状态筛选
if (isNotBlank($params['status'])) {
$query[] = ['status', '=', $params['status']];
}
$list = $this->dao->getList($query, '*', $page, $limit, "$sortField $sortRule");
$count = $this->dao->getCount($query);
return compact('list', 'count');
}
/**
* 获取用户信息
* @param mixed $id
* @return array
*/
public function readData(mixed $id): array
{
$proxyUser = $this->dao->get(['id' => $id]);
if (empty($proxyUser)) {
throw new ApiException(trans(4040016));
}
return $proxyUser->toArray();
}
/**
* 删除用户信息
* @param mixed $id
* @return array
*/
public function deleteData(mixed $id): array
{
$proxyUser = $this->dao->get(['id' => $id]);
if (empty($proxyUser)) {
return [];
}
// 落库
Db::startTrans();
try {
$this->dao->softDel($id);
Db::commit();
} catch (\Exception $exception) {
Db::rollback();
throw new ApiException($exception->getMessage());
}
// todo 踢下线
return ['id' => $id];
}
public function banProxy($params)
{
$proxyUser = $this->dao->get(['id' => $params['id']]);
if (empty($proxyUser)) {
throw new ApiException(trans(4040016));
}
if ($proxyUser['status'] == 1) {
//todo 销毁token
}
$status = $proxyUser['status'] == 1 ? 2 : 1;
$this->dao->update(['id' => $params['id']], ['status' => $status]);
return [
'id' => $params['id'],
'status' => $status
];
}
// ============================================================ 私有方法 ===============================================

151
plugin/piadmin/app/service/UserService.php

@ -8,6 +8,8 @@ use plugin\piadmin\app\exception\ApiException;
use plugin\piadmin\app\utils\CacheUtils;
use plugin\piadmin\app\utils\Captcha;
use plugin\piadmin\app\utils\JwtUtils;
use plugin\piadmin\app\utils\RequestUtils;
use support\think\Db;
class UserService extends BaseService
{
@ -84,6 +86,155 @@ class UserService extends BaseService
return $tokenInfo;
}
/**
* 保存用户信息
* @param array $params
* @return array
*/
public function saveData(array $params): array
{
// 检查账号
$accountExist = $this->dao->be(['account' => $params['account']]);
if ($accountExist) {
throw new ApiException(4040013);
}
$params['password'] = password_hash($params['password'], PASSWORD_ARGON2I);
// 落库
Db::startTrans();
try {
// 落库
$user = $this->dao->save($params);
Db::commit();
} catch (\Exception $exception) {
Db::rollback();
throw new ApiException($exception->getMessage());
}
return $user->toArray();
}
/**
* 修改用户信息
* @param array $params
* @return array
*/
public function updateData(array $params): array
{
$user = $this->dao->get(['id' => $params['id']]);
if (empty($user)) {
throw new ApiException(trans(4040016));
}
// 检查账号
if (!empty($user['account']) && $user['account'] != $params['account']) {
$accountExist = $this->dao->be(['account' => $params['account']]);
if ($accountExist) {
throw new ApiException(4040013);
}
}
// 检查密码
if (!empty($params['password']) && !password_verify($params['password'], $user['password'])) {
$params['password'] = password_hash($params['password'], PASSWORD_ARGON2I);
}
// 落库
Db::startTrans();
try {
$this->dao->update(['id' => $params['id']], $params);
Db::commit();
} catch (\Exception $exception) {
Db::rollback();
throw new ApiException($exception->getMessage());
}
return $params;
}
/**
* 获取用户列表
* @param array $params
* @return array
*/
public function listData(array $params): array
{
[$page, $limit] = RequestUtils::getPageParameter();
[$sortRule, $sortField] = RequestUtils::getSortParameter();
$query = [];
// 账号筛选
if (isNotBlank($params['email'])) {
$query[] = ['email', 'like', '%' . $params['email'] . '%'];
}
// 名称筛选
if (isNotBlank($params['name'])) {
$query[] = ['name', 'like', '%' . $params['name'] . '%'];
}
// 手机号筛选
if (isNotBlank($params['phone'])) {
$query[] = ['phone', 'like', '%' . $params['phone'] . '%'];
}
// 状态筛选
if (isNotBlank($params['status'])) {
$query[] = ['status', '=', $params['status']];
}
$list = $this->dao->getList($query, '*', $page, $limit, "$sortField $sortRule");
$count = $this->dao->getCount($query);
return compact('list', 'count');
}
/**
* 获取用户信息
* @param mixed $id
* @return array
*/
public function readData(mixed $id): array
{
$user = $this->dao->get(['id' => $id]);
if (empty($user)) {
throw new ApiException(trans(4040016));
}
return $user->toArray();
}
/**
* 删除用户信息
* @param mixed $id
* @return array
*/
public function deleteData(mixed $id): array
{
$user = $this->dao->get(['id' => $id]);
if (empty($user)) {
return [];
}
// 落库
Db::startTrans();
try {
$this->dao->softDel($id);
Db::commit();
} catch (\Exception $exception) {
Db::rollback();
throw new ApiException($exception->getMessage());
}
// todo 踢下线
return ['id' => $id];
}
public function banUser($params)
{
$user = $this->dao->get(['id' => $params['id']]);
if (empty($user)) {
throw new ApiException(trans(4040016));
}
if ($user['status'] == 1) {
//todo 销毁token
}
$status = $user['status'] == 1 ? 2 : 1;
$this->dao->update(['id' => $params['id']], ['status' => $status]);
return [
'id' => $params['id'],
'status' => $status
];
}
// ============================================================ 私有方法 ===============================================

24
plugin/piadmin/app/utils/RequestUtils.php

@ -81,6 +81,30 @@ class RequestUtils
return $userinfo;
}
public static function getProxyInfo(): array{
$proxyInfo = [
'id'=>'',
'name'=>'',
'dataPermission'=> ''
];
try{
$proxy_user = request()->proxy_user;
if(!empty($proxy_user)){
$proxyInfo = [
'id'=>$proxy_user['id'] ?? '',
'name'=>$proxy_user['name'] ?? '',
'dataPermission'=>$proxy_user['dataPermission'] ?? ''
];
}
}catch(\Throwable $e){
}
return $proxyInfo;
}
/**
* 获取本次请求的排序参数
* @return array

38
plugin/piadmin/app/validate/ProxyUserValidate.php

@ -0,0 +1,38 @@
<?php
namespace plugin\piadmin\app\validate;
use plugin\piadmin\app\base\BaseValidate;
class ProxyUserValidate extends BaseValidate
{
protected $group = [
'save' => [
'name' => 'require|max:100',
'account' => 'require|max:100',
'password' => 'require|min:8|max:32',
'phone' => 'mobile',
'email' => 'email',
],
'update' => [
'id' => 'require',
'name' => 'max:100',
'account' => 'max:100',
'password' => 'min:8|max:32',
'phone' => 'mobile',
'email' => 'email',
]
];
protected $message = [
'name.require' => '4040001',
'name.max' => '4040002',
'account.require' => '4040003',
'account.max' => '4040004',
'password.require' => '4040006',
'password.min' => '4040007',
'password.max' => '4040008',
'phone.mobile' => '4040009',
'email.email' => '4040010',
'id.require' => '4040015'
];
}
Loading…
Cancel
Save