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 @@