diff --git a/server/app/admin/controller/LoginController.php b/server/app/admin/controller/LoginController.php index 25fcf34e9c251f2fa27b47f0f55b2715a47b703b..68f77afbcfbeecfb326c561c5994a8b44f05f194 100644 --- a/server/app/admin/controller/LoginController.php +++ b/server/app/admin/controller/LoginController.php @@ -13,6 +13,7 @@ namespace app\admin\controller; use app\common\services\system\SysAdminService; +use core\cache\CacheService; use core\exception\handler\AdminException; use core\jwt\JwtToken; use core\utils\Json; @@ -55,7 +56,18 @@ class LoginController extends Crud */ public function getCaptchaOpenFlag(Request $request): \support\Response { - return Json::success('ok', ['flag' => config('core.captcha.app.enable', false)]); + try { + // 生成密钥对 + $cache = Container::make(CacheService::class,[]); + // 使用 uniqid 增加唯一性 + $keyId = bin2hex(random_bytes(8)) . uniqid(); + $keys = $this->service->generateRSAKeys(); + // 存储私钥到缓存,用于解密密码 + $cache->set("rsa_private_key:$keyId", $keys['private'], 60); // 5分钟过期 + return Json::success('ok', ['flag' => config('core.captcha.app.enable', false),'key_id'=>$keyId,'public_key'=>$keys['public']]); + } catch (\Throwable $e) { + return Json::fail($e->getMessage()); + } } /** @@ -113,9 +125,8 @@ class LoginController extends Crud $code = $request->input('code', ''); $uuid = $request->input('uuid', ''); $type = $request->input('type', 'admin'); - $tenantId = $request->input('tenant_id', ''); $grantType = $request->input('grant_type', 'default');//refresh_token sms default 可以自行定义拓展登录方式 - + $keyId = $request->input('key_id', '');//获取公钥Id $service = Container::make(SysAdminService::class); $captcha = new Captcha(); @@ -139,7 +150,7 @@ class LoginController extends Crud } $username = $info->getData('user_name'); } - $data = $service->login($username, $password, $type, $grantType, $tenantId); + $data = $service->login($username, $password, $type, $grantType, ['keyId'=> $keyId ?? '']); return Json::success('ok', $data); } catch (\Throwable $e) { return Json::fail($e->getMessage()); diff --git a/server/app/common/services/system/SysAdminService.php b/server/app/common/services/system/SysAdminService.php index e5f3bff763b5813df989a4688583192ccaf7fec7..81a4e71e8a3933259b870298f31aede7e40d65e2 100644 --- a/server/app/common/services/system/SysAdminService.php +++ b/server/app/common/services/system/SysAdminService.php @@ -15,6 +15,7 @@ namespace app\common\services\system; use app\common\dao\system\SysAdminDao; use app\common\model\system\SysAdmin; use core\abstract\BaseService; +use core\cache\CacheService; use core\casbin\Permission; use core\enum\system\PolicyPrefix; use core\exception\handler\AdminException; @@ -244,11 +245,12 @@ class SysAdminService extends BaseService * @return array * @throws \Exception */ - public function login(string $username, string $password = '', string $type = 'admin', string $grantType = 'default', string|int $tenantId = ''): array + public function login(string $username, string $password = '', string $type = 'admin', string $grantType = 'default', array $params = []): array { $adminInfo = $this->getAdminByName($username); $this->validateAdminStatus($adminInfo); - $this->validatePassword($adminInfo, $password, $grantType); + $decryptedPassword = $this->validateRsaKeys($params['keyId'], $password); + $this->validatePassword($adminInfo, $decryptedPassword, $grantType); [$userInfo, $token] = $this->generateTokenData($adminInfo, $type); $this->emitLoginSuccessEvent(array_merge($userInfo, $token), $tenant?->id ?? null); return $token ?? []; @@ -481,4 +483,28 @@ class SysAdminService extends BaseService preg_match($pattern, $url, $matches); return $matches[1] ?? ''; } + /** + * 校验密钥 + * @param $keyId + * @param $encryptedPassword + * @return string + * @throws AdminException + */ + private function validateRsaKeys($keyId, $encryptedPassword): string + { + $cache = Container::make(CacheService::class,[]); + $privateKey = $cache->get("rsa_private_key:$keyId"); + if (!$privateKey) { + throw new AdminException('私钥不存在或已过期,请刷新页面重试'); + } + $privateKeyResource = openssl_pkey_get_private($privateKey); + $decrypted = ''; + $encryptedData = base64_decode($encryptedPassword); + if (openssl_private_decrypt($encryptedData, $decrypted, $privateKeyResource)) { + $cache->delete("rsa_private_key:$keyId"); // 删除私钥,防止泄露 + return $decrypted; + } else { + throw new AdminException('解密失败!'); + } + } } diff --git a/server/core/abstract/BaseDao.php b/server/core/abstract/BaseDao.php index e7dd0008306a7d225534575c148f990449265080..f72c5e8a39df18a46fdab2868f5c499aae2e0e7d 100644 --- a/server/core/abstract/BaseDao.php +++ b/server/core/abstract/BaseDao.php @@ -1,4 +1,5 @@ search($where); // search 返回的是一个查询构建器 } else { - $query->where($where); // 应用 where 条件 + $whereInConditions = []; + foreach ($where as $key => $condition) { + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($where[$key]);//移除分离后的条件 + } + } + } + //普通条件格式直接传入构建 + if (!empty($where)) { + $query->where($where); + } + + //特殊条件格式额外处理 + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } + } } // 返回满足条件的记录数量 return $query->count(); } + /** * 查询列表 * - * @param array $where - * @param string $field - * @param int $page - * @param int $limit - * @param string $order - * @param array $with - * @param bool $search + * @param array $where + * @param string|array $field + * @param int $page + * @param int $limit + * @param string $order + * @param array $with + * @param bool $search * @param array|null $withoutScopes * - * @return \Illuminate\Database\Eloquent\Collection|null - * @throws \Exception + * @return Collection|null + * @throws Exception */ - public function selectList(array $where, string $field = '*', int $page = 0, int $limit = 0, string $order = '', array $with = [], bool $search = false, ?array $withoutScopes = null): ?\Illuminate\Database\Eloquent\Collection + public function selectList(array $where, string|array $field = '*', int $page = 0, int $limit = 0, string $order = '', array $with = [], bool $search = false, ?array $withoutScopes = null): ?Collection { // 使用 selectModel 方法获取查询构建器 $query = $this->selectModel($where, $field, $page, $limit, $order, $with, $search, $withoutScopes); - // 如果字段不是 '*',则应用 selectRaw() - if ($field !== '*') { - $query->selectRaw($field); // 确保在查询构建器上调用 + // 如果字段不是 '*' 或 ['*'],则应用 selectRaw() + $isWildcard = ($field === '*' || ($field === ['*'])); + if (!$isWildcard) { + if (is_array($field)) { + // 如果是数组,转换为字符串 + $field = implode(',', $field); + } + $query->selectRaw($field); } + // 应用分页 if ($page > 0 && $limit > 0) { // 只返回数据部分 return $query->paginate($limit, ['*'], 'page', $page)->getCollection(); } + // var_dump($query->toSql());die; return $query->get(); // 返回所有数据 } + /** * 获取某些条件数据 * - * @param array $where - * @param string $field - * @param int $page - * @param int $limit - * @param string $order - * @param array $with - * @param bool $search + * @param array $where + * @param array|string $field + * @param int $page + * @param int $limit + * @param string $order + * @param array $with + * @param bool $search * @param array|null $withoutScopes * - * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder|\Illuminate\Pagination\LengthAwarePaginator|null - * @throws \Exception + * @return Builder|\Illuminate\Database\Query\Builder|LengthAwarePaginator|null + * @throws Exception */ - public function selectModel(array $where, string $field = '*', int $page = 0, int $limit = 0, string $order = '', array $with = [], bool $search = false, ?array $withoutScopes = null): \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder|\Illuminate\Pagination\LengthAwarePaginator|null + public function selectModel(array $where, array|string $field = '*', int $page = 0, int $limit = 0, string $order = '', array $with = [], bool $search = false, ?array $withoutScopes = null): Builder|\Illuminate\Database\Query\Builder|LengthAwarePaginator|null { // 获取模型的查询构建器 $query = $this->getModel()->query(); @@ -146,12 +189,14 @@ abstract class BaseDao if ($search) { $query = $this->search($where); // search 返回的是一个查询构建器 } else { -// $query->where($where); // 应用 where 条件 $whereInConditions = []; foreach ($where as $key => $condition) { - if (is_array($condition) && count($condition) === 3 && ($condition[1] === 'in' || $condition[1] === 'IN')) { - $whereInConditions[] = $condition; - unset($where[$key]);//移除分离后的条件 + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($where[$key]);//移除分离后的条件 + } } } //普通条件格式直接传入构建 @@ -164,13 +209,28 @@ abstract class BaseDao if (empty($condition[2])) { continue; } + $operator = strtolower($condition[1]); $value = Arr::normalize($condition[2]); - $query->whereIn($condition[0], $value); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } } } + // 应用字段选择 - if ($field !== '*') { - $query->selectRaw($field); // 在这里应用 selectRaw + $isWildcard = ($field === '*' || ($field === ['*'])); + if (!$isWildcard) { + if (is_array($field)) { + // 过滤空值并合并为字符串 + $field = array_filter($field, function($f) { return !empty($f); }); + $field = implode(',', $field); + } + + if (!empty($field)) { + $query->selectRaw($field); + } } // 应用分页和其他查询条件 if ($page > 0 && $limit > 0) { @@ -191,11 +251,43 @@ abstract class BaseDao * @param array $where * * @return int - * @throws \Exception + * @throws Exception */ public function getCount(array $where): int { - return $this->getModel()->where($where)->count(); + // 获取模型的查询构建器 + $query = $this->getModel()->query(); + + $whereInConditions = []; + foreach ($where as $key => $condition) { + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($where[$key]);//移除分离后的条件 + } + } + } + //普通条件格式直接传入构建 + if (!empty($where)) { + $query->where($where); + } + + //特殊条件格式额外处理 + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } + } + + return $query->count(); } /** @@ -206,41 +298,67 @@ abstract class BaseDao * @param bool $search * * @return int - * @throws \Exception + * @throws Exception */ public function getDistinctCount(array $where, string $field, bool $search = true): int { // 构建查询 - $query = $this->getModel(); + $query = $this->getModel()->query(); + // 应用搜索条件 if ($search) { - $query = $this->search($query, $where); + $query = $this->search($where); } else { - $query = $query->where($where); + $whereInConditions = []; + foreach ($where as $key => $condition) { + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($where[$key]);//移除分离后的条件 + } + } + } + //普通条件格式直接传入构建 + if (!empty($where)) { + $query->where($where); + } + + //特殊条件格式额外处理 + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } + } } // 获取唯一计数 return $query->distinct()->count($field); } + /** * 获取模型 * * @return mixed - * @throws \Exception + * @throws Exception */ public function getModel(): mixed { try { $className = $this->setModel(); - if (is_object($className)) { - return $className; - } if (!class_exists($className)) { - throw new \Exception($className . ' 不是一个有效的模型类'); + throw new Exception($className . ' 不是一个有效的模型类'); } return new $className(); - } catch (\Throwable $e) { - throw new \Exception($className . ' 未知模型: ' . $e->getMessage()); + } catch (Throwable $e) { + throw new Exception($className . ' 未知模型: ' . $e->getMessage()); } } @@ -248,7 +366,7 @@ abstract class BaseDao * 获取模型主键 * * @return string - * @throws \Exception + * @throws Exception */ public function getPk(): string { @@ -259,7 +377,7 @@ abstract class BaseDao * 获取表名 * * @return string - * @throws \ReflectionException|\Exception + * @throws ReflectionException|Exception */ public function getTableName(): string { @@ -270,18 +388,48 @@ abstract class BaseDao * 获取一条数据 * * @param $id - * @param array|null $field + * @param string|array|null $field * @param array|null $with - * @param string $order + * @param string $order * @param array|null $withoutScopes * - * @return \Illuminate\Database\Eloquent\Model|null - * @throws \Exception + * @return Model|null + * @throws Exception */ - public function get($id, ?array $field = null, ?array $with = [], string $order = '', ?array $withoutScopes = null): ?\Illuminate\Database\Eloquent\Model + public function get($id, string|array $field = null, ?array $with = [], string $order = '', ?array $withoutScopes = null): ?Model { $where = is_array($id) ? $id : [$this->getPk() => $id]; - $query = $this->getModel()->where($where); + $query = $this->getModel()->query(); + + $whereInConditions = []; + foreach ($where as $key => $condition) { + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($where[$key]);//移除分离后的条件 + } + } + } + //普通条件格式直接传入构建 + if (!empty($where)) { + $query->where($where); + } + + //特殊条件格式额外处理 + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } + } + $this->applyScopeRemoval($query, $withoutScopes); // 添加关联加载 if (!empty($with)) { @@ -294,6 +442,7 @@ abstract class BaseDao return $query->select($field ?? ['*'])->first(); } + /** * 查询一条数据是否存在 * @@ -301,7 +450,7 @@ abstract class BaseDao * @param string $field * * @return bool - * @throws \Exception + * @throws Exception */ public function be($map, string $field = ''): bool { @@ -314,9 +463,41 @@ abstract class BaseDao $map = !is_array($map) ? [$field => $map] : $map; // 使用 Eloquent 查询构建器检查记录是否存在 - return $this->getModel()->where($map)->exists(); + $query = $this->getModel()->query(); + + $whereInConditions = []; + foreach ($map as $key => $condition) { + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($map[$key]);//移除分离后的条件 + } + } + } + //普通条件格式直接传入构建 + if (!empty($map)) { + $query->where($map); + } + + //特殊条件格式额外处理 + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } + } + + return $query->exists(); } + /** * 根据条件获取一条数据 * @@ -324,17 +505,55 @@ abstract class BaseDao * @param string|null $field * @param array $with * - * @return \Illuminate\Database\Eloquent\Model|null - * @throws \Exception + * @return Model|null + * @throws Exception */ - public function getOne(array $where, ?string $field = '*', array $with = []): ?\Illuminate\Database\Eloquent\Model + public function getOne(array $where, ?string $field = '*', array $with = []): ?Model { // 将字段字符串转换为数组 $fieldArray = $field === '*' ? ['*'] : explode(',', $field); + // 使用 Eloquent 查询构建器获取一条数据 - return $this->getModel()->with($with)->where($where)->select($fieldArray)->first(); + $query = $this->getModel()->query(); + + $whereInConditions = []; + foreach ($where as $key => $condition) { + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($where[$key]);//移除分离后的条件 + } + } + } + //普通条件格式直接传入构建 + if (!empty($where)) { + $query->where($where); + } + + //特殊条件格式额外处理 + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } + } + + // 添加关联加载 + if (!empty($with)) { + $query->with($with); + } + + return $query->select($fieldArray)->first(); } + /** * 获取某字段的值 * @@ -342,16 +561,48 @@ abstract class BaseDao * @param string|null $field * * @return mixed - * @throws \Exception + * @throws Exception */ public function value($where, ?string $field = null): mixed { - $pk = $this->getPk(); // 获取主键 - $query = $this->getModel()->where($this->setWhere($where)); // 设置查询条件 + $pk = $this->getPk(); // 获取主键 + $where = $this->setWhere($where); // 设置查询条件 + + $query = $this->getModel()->query(); + + $whereInConditions = []; + foreach ($where as $key => $condition) { + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($where[$key]);//移除分离后的条件 + } + } + } + //普通条件格式直接传入构建 + if (!empty($where)) { + $query->where($where); + } + + //特殊条件格式额外处理 + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } + } return $query->value($field ?? $pk); // 返回指定字段的值,默认为主键 } + /** * 获取某个字段数组 * @@ -360,7 +611,7 @@ abstract class BaseDao * @param string $key * * @return array - * @throws \ReflectionException|\Exception + * @throws ReflectionException|Exception */ public function getColumn(array $where, string $field, string $key = ''): array { @@ -369,9 +620,12 @@ abstract class BaseDao $whereInConditions = []; foreach ($where as $k => $condition) { - if (is_array($condition) && count($condition) === 3 && ($condition[1] === 'in' || $condition[1] === 'IN')) { - $whereInConditions[] = $condition; - unset($where[$k]);//移除分离后的条件 + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($where[$k]);//移除分离后的条件 + } } } //普通条件格式直接传入构建 @@ -384,10 +638,16 @@ abstract class BaseDao if (empty($condition[2])) { continue; } + $operator = strtolower($condition[1]); $value = Arr::normalize($condition[2]); - $query->whereIn($condition[0], $value); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } } + // 如果指定了键,则使用 keyBy 方法 if ($key) { return $query->pluck($field, $key)->toArray(); @@ -404,7 +664,7 @@ abstract class BaseDao * @param string|null $key * * @return mixed - * @throws \Exception + * @throws Exception */ public function delete(array|int|string $id, ?string $key = null): int { @@ -427,8 +687,8 @@ abstract class BaseDao $model->delete();//触发事件 } return $models->count(); - } catch (\Exception $e) { - throw new \Exception("删除失败:" . $e->getMessage(), $e->getCode(), $e); + } catch (Exception $e) { + throw new Exception("删除失败:" . $e->getMessage(), $e->getCode(), $e); } } @@ -439,7 +699,7 @@ abstract class BaseDao * @param bool $force * * @return bool - * @throws \Exception + * @throws Exception */ public function destroy(mixed $id, bool $force = false): bool { @@ -455,7 +715,7 @@ abstract class BaseDao * @param string|null $key * * @return mixed - * @throws \Exception + * @throws Exception */ public function update(string|int|array $id, array $data, ?string $key = null): mixed { @@ -486,15 +746,19 @@ abstract class BaseDao $query->where($where); } - // 处理 IN 条件 + // 处理 IN/NOT IN 条件 foreach ($whereInConditions as $condition) { list($column, $operator, $value) = $condition; $normalizedValue = is_array($value) ? $value : [$value]; $query->where(function ($q) use ($column, $operator, $normalizedValue) { - $q->whereIn($column, $normalizedValue); + $op = strtolower($operator); + if ($op === 'in') { + $q->whereIn($column, $normalizedValue); + } elseif ($op === 'not in') { + $q->whereNotIn($column, $normalizedValue); + } }); } - return $query->update($data); } @@ -505,7 +769,7 @@ abstract class BaseDao * @param string|null $key * * @return array - * @throws \Exception + * @throws Exception */ protected function setWhere($where, ?string $key = null): array { @@ -524,7 +788,7 @@ abstract class BaseDao * @param string|null $key * * @return mixed - * @throws \Exception + * @throws Exception */ public function batchUpdate(array $ids, array $data, ?string $key = null): bool { @@ -536,10 +800,10 @@ abstract class BaseDao * * @param array $data * - * @return \Illuminate\Database\Eloquent\Model|null - * @throws \Exception + * @return Model|null + * @throws Exception */ - public function save(array $data): ?\Illuminate\Database\Eloquent\Model + public function save(array $data): ?Model { return $this->getModel()->create($data); } @@ -572,7 +836,7 @@ abstract class BaseDao }); return $savedAll; - } catch (\Exception $e) { + } catch (Exception $e) { return false; } } @@ -586,7 +850,7 @@ abstract class BaseDao * @param array|null $where * * @return mixed - * @throws \Exception + * @throws Exception */ public function getFieldValue($value, string $field, ?string $valueKey = null, ?array $where = []): mixed { @@ -596,17 +860,50 @@ abstract class BaseDao } else { $where[$this->getPk()] = $value; // 默认使用主键作为条件 } + // 使用 Eloquent 查询构建器获取字段值 - return $this->getModel()->where($where)->value($field); + $query = $this->getModel()->query(); + + $whereInConditions = []; + foreach ($where as $key => $condition) { + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($where[$key]);//移除分离后的条件 + } + } + } + //普通条件格式直接传入构建 + if (!empty($where)) { + $query->where($where); + } + + //特殊条件格式额外处理 + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } + } + + return $query->value($field); } + /** * 获取搜索器和搜索条件key,以及不在搜索器的条件数组 * * @param array $where * * @return array[] - * @throws \ReflectionException + * @throws ReflectionException */ private function getSearchData(array $where): array { @@ -642,7 +939,7 @@ abstract class BaseDao * @param bool $search * * @return \Illuminate\Database\Query\Builder - * @throws \Exception + * @throws Exception */ protected function withSearchSelect(array $where, bool $search): mixed { @@ -670,7 +967,7 @@ abstract class BaseDao * @param array $where * * @return array - * @throws \Exception + * @throws Exception */ protected function filterWhere(array $where = []): array { @@ -691,7 +988,7 @@ abstract class BaseDao * @param bool $search * * @return mixed - * @throws \Exception + * @throws Exception */ public function search(array $where = [], bool $search = true): mixed { @@ -710,22 +1007,50 @@ abstract class BaseDao * @param bool $search * * @return float - * @throws \Exception + * @throws Exception */ public function sum(array $where, string $field, bool $search = false): float { // 构建查询 - $query = $this->getModel(); + $query = $this->getModel()->query(); // 应用搜索条件 if ($search) { - $query = $this->search($query, $where); + $query = $this->search($where); } else { - $query = $query->where($where); + $whereInConditions = []; + foreach ($where as $key => $condition) { + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($where[$key]);//移除分离后的条件 + } + } + } + //普通条件格式直接传入构建 + if (!empty($where)) { + $query->where($where); + } + + //特殊条件格式额外处理 + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } + } } // 计算总和并返回 return (float)$query->sum($field); } + /** * 高精度加法(修正精度问题) * @@ -736,7 +1061,7 @@ abstract class BaseDao * @param int $acc 精度(小数位数) * * @return bool - * @throws \Exception + * @throws Exception */ public function bcInc(mixed $key, string $incField, string $inc, string $keyField = null, int $acc = 2): bool { @@ -758,7 +1083,7 @@ abstract class BaseDao * @param int $acc * * @return bool - * @throws \ReflectionException + * @throws ReflectionException */ public function bcDec($key, string $decField, string $dec, string $keyField = null, int $acc = 2): bool { @@ -776,7 +1101,7 @@ abstract class BaseDao * @param int $acc * * @return bool - * @throws \ReflectionException + * @throws ReflectionException */ public function bc($key, string $field, string $value, string $keyField = null, int $type = 1, int $acc = 2): bool { @@ -807,13 +1132,64 @@ abstract class BaseDao * @param string $sales * * @return bool - * @throws \Exception + * @throws Exception */ public function decStockIncSales(array $where, int $num, string $stock = 'stock', string $sales = 'sales'): bool { - $product = $this->getModel()->where($where)->first(); + $query = $this->getModel()->query(); + + $whereInConditions = []; + foreach ($where as $key => $condition) { + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($where[$key]);//移除分离后的条件 + } + } + } + //普通条件格式直接传入构建 + if (!empty($where)) { + $query->where($where); + } + + //特殊条件格式额外处理 + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } + } + + $product = $query->first(); if ($product) { - return $this->getModel()->where($where)->decrement($stock, $num)->increment($sales, $num); + // 重新构建查询以执行更新操作 + $updateQuery = $this->getModel()->query(); + + // 重新应用条件 + if (!empty($where)) { + $updateQuery->where($where); + } + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $updateQuery->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $updateQuery->whereNotIn($condition[0], $value); + } + } + + return $updateQuery->decrement($stock, $num)->increment($sales, $num); } return false; } @@ -827,15 +1203,72 @@ abstract class BaseDao * @param string $sales * * @return bool - * @throws \Exception + * @throws Exception */ public function incStockDecSales(array $where, int $num, string $stock = 'stock', string $sales = 'sales'): bool { - $product = $this->getModel()->where($where)->first(); + $query = $this->getModel()->query(); + + $whereInConditions = []; + foreach ($where as $key => $condition) { + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($where[$key]);//移除分离后的条件 + } + } + } + //普通条件格式直接传入构建 + if (!empty($where)) { + $query->where($where); + } + + //特殊条件格式额外处理 + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } + } + + $product = $query->first(); if ($product) { - return $this->getModel()->where($where)->increment($stock, $num)->decrement($sales, $num); + // 重新构建查询以执行更新操作 + $updateQuery1 = $this->getModel()->query(); + $updateQuery2 = $this->getModel()->query(); + + // 重新应用条件 + if (!empty($where)) { + $updateQuery1->where($where); + $updateQuery2->where($where); + } + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $updateQuery1->whereIn($condition[0], $value); + $updateQuery2->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $updateQuery1->whereNotIn($condition[0], $value); + $updateQuery2->whereNotIn($condition[0], $value); + } + } + + $updateQuery1->increment($stock, $num); + $updateQuery2->decrement($sales, $num); + return true; } - return true; + return false; } /** @@ -845,11 +1278,42 @@ abstract class BaseDao * @param string $field * * @return mixed - * @throws \Exception + * @throws Exception */ public function getMax(array $where = [], string $field = ''): mixed { - return $this->getModel()->where($where)->max($field); + $query = $this->getModel()->query(); + + $whereInConditions = []; + foreach ($where as $key => $condition) { + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($where[$key]);//移除分离后的条件 + } + } + } + //普通条件格式直接传入构建 + if (!empty($where)) { + $query->where($where); + } + + //特殊条件格式额外处理 + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } + } + + return $query->max($field); } /** @@ -859,11 +1323,42 @@ abstract class BaseDao * @param string $field * * @return mixed - * @throws \Exception + * @throws Exception */ public function getMin(array $where = [], string $field = ''): mixed { - return $this->getModel()->where($where)->min($field); + $query = $this->getModel()->query(); + + $whereInConditions = []; + foreach ($where as $key => $condition) { + if (is_array($condition) && count($condition) === 3) { + $operator = strtolower($condition[1]); + if ($operator === 'in' || $operator === 'not in') { + $whereInConditions[] = $condition; + unset($where[$key]);//移除分离后的条件 + } + } + } + //普通条件格式直接传入构建 + if (!empty($where)) { + $query->where($where); + } + + //特殊条件格式额外处理 + foreach ($whereInConditions as $condition) { + if (empty($condition[2])) { + continue; + } + $operator = strtolower($condition[1]); + $value = Arr::normalize($condition[2]); + if ($operator === 'in') { + $query->whereIn($condition[0], $value); + } elseif ($operator === 'not in') { + $query->whereNotIn($condition[0], $value); + } + } + + return $query->min($field); } private function studly(string $string): string @@ -911,5 +1406,14 @@ abstract class BaseDao return count($condition) === 3 && in_array(strtolower($condition[1] ?? ''), ['in', 'not in'], true); } + /** + * 检测表是否存在 + * @param $table + * @return bool + */ + public function tableExists($table): bool + { + return Db::schema()->hasTable($table); + } } diff --git a/web/package.json b/web/package.json index e4ee02330abc06a5d5729ba64dcbcd6b2e2b10af..59db53847542fcb724e0edcd7a282035dc8e8c18 100644 --- a/web/package.json +++ b/web/package.json @@ -39,6 +39,7 @@ "dotenv": "^16.4.7", "echarts": "^5.6.0", "epic-designer": "^1.0.1", + "jsencrypt": "^3.5.4", "lodash-es": "^4.17.21", "lodash.clonedeep": "^4.5.0", "lodash.get": "^4.4.2", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index a61c6760fd280771022780ff5e19dc0928063c19..510e4777e6aeda26f3c7b68a311c52c14b49c685 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -86,6 +86,9 @@ importers: epic-designer: specifier: ^1.0.1 version: 1.0.1(ant-design-vue@4.2.6(vue@3.5.13(typescript@5.7.3)))(element-plus@2.9.9(vue@3.5.13(typescript@5.7.3)))(monaco-editor@0.52.2)(naive-ui@2.41.0(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3)) + jsencrypt: + specifier: ^3.5.4 + version: 3.5.4 lodash-es: specifier: ^4.17.21 version: 4.17.21 diff --git a/web/src/api/core/auth.ts b/web/src/api/core/auth.ts index 23ea35a1f423c2ead5268a3d46d3c48960f36819..5662519718106945395216e782d818fee21f250d 100644 --- a/web/src/api/core/auth.ts +++ b/web/src/api/core/auth.ts @@ -7,6 +7,7 @@ export namespace AuthApi { user_name?: string; uuid?:string; code?:string; + key_id?:string; mobile_phone?:number|string; } @@ -26,7 +27,6 @@ export namespace AuthApi { export interface AccountSet { id: number|string; - tenant_id:string|number; name: string; } diff --git a/web/src/views/core/authentication/login.vue b/web/src/views/core/authentication/login.vue index 2754f869b1821539c066c0cf613b3c30af082799..a04a414b5d1fe0cc199b2de79bdf10bcaa5e984c 100644 --- a/web/src/views/core/authentication/login.vue +++ b/web/src/views/core/authentication/login.vue @@ -1,6 +1,5 @@